aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/dream/camera/msm_io7x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/dream/camera/msm_io7x.c')
-rw-r--r--drivers/staging/dream/camera/msm_io7x.c291
1 files changed, 291 insertions, 0 deletions
diff --git a/drivers/staging/dream/camera/msm_io7x.c b/drivers/staging/dream/camera/msm_io7x.c
new file mode 100644
index 000000000000..55c020bb7afa
--- /dev/null
+++ b/drivers/staging/dream/camera/msm_io7x.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2008-2009 QUALCOMM Incorporated
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <mach/gpio.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+
+#define CAMIF_CFG_RMSK 0x1fffff
+#define CAM_SEL_BMSK 0x2
+#define CAM_PCLK_SRC_SEL_BMSK 0x60000
+#define CAM_PCLK_INVERT_BMSK 0x80000
+#define CAM_PAD_REG_SW_RESET_BMSK 0x100000
+
+#define EXT_CAM_HSYNC_POL_SEL_BMSK 0x10000
+#define EXT_CAM_VSYNC_POL_SEL_BMSK 0x8000
+#define MDDI_CLK_CHICKEN_BIT_BMSK 0x80
+
+#define CAM_SEL_SHFT 0x1
+#define CAM_PCLK_SRC_SEL_SHFT 0x11
+#define CAM_PCLK_INVERT_SHFT 0x13
+#define CAM_PAD_REG_SW_RESET_SHFT 0x14
+
+#define EXT_CAM_HSYNC_POL_SEL_SHFT 0x10
+#define EXT_CAM_VSYNC_POL_SEL_SHFT 0xF
+#define MDDI_CLK_CHICKEN_BIT_SHFT 0x7
+#define APPS_RESET_OFFSET 0x00000210
+
+static struct clk *camio_vfe_mdc_clk;
+static struct clk *camio_mdc_clk;
+static struct clk *camio_vfe_clk;
+
+static struct msm_camera_io_ext camio_ext;
+static struct resource *appio, *mdcio;
+void __iomem *appbase, *mdcbase;
+
+static struct msm_camera_io_ext camio_ext;
+static struct resource *appio, *mdcio;
+void __iomem *appbase, *mdcbase;
+
+extern int clk_set_flags(struct clk *clk, unsigned long flags);
+
+int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
+{
+ int rc = -1;
+ struct clk *clk = NULL;
+
+ switch (clktype) {
+ case CAMIO_VFE_MDC_CLK:
+ clk = camio_vfe_mdc_clk = clk_get(NULL, "vfe_mdc_clk");
+ break;
+
+ case CAMIO_MDC_CLK:
+ clk = camio_mdc_clk = clk_get(NULL, "mdc_clk");
+ break;
+
+ case CAMIO_VFE_CLK:
+ clk = camio_vfe_clk = clk_get(NULL, "vfe_clk");
+ break;
+
+ default:
+ break;
+ }
+
+ if (!IS_ERR(clk)) {
+ clk_enable(clk);
+ rc = 0;
+ }
+
+ return rc;
+}
+
+int msm_camio_clk_disable(enum msm_camio_clk_type clktype)
+{
+ int rc = -1;
+ struct clk *clk = NULL;
+
+ switch (clktype) {
+ case CAMIO_VFE_MDC_CLK:
+ clk = camio_vfe_mdc_clk;
+ break;
+
+ case CAMIO_MDC_CLK:
+ clk = camio_mdc_clk;
+ break;
+
+ case CAMIO_VFE_CLK:
+ clk = camio_vfe_clk;
+ break;
+
+ default:
+ break;
+ }
+
+ if (!IS_ERR(clk)) {
+ clk_disable(clk);
+ clk_put(clk);
+ rc = 0;
+ }
+
+ return rc;
+}
+
+void msm_camio_clk_rate_set(int rate)
+{
+ struct clk *clk = camio_vfe_clk;
+
+ if (clk != ERR_PTR(-ENOENT))
+ clk_set_rate(clk, rate);
+}
+
+int msm_camio_enable(struct platform_device *pdev)
+{
+ int rc = 0;
+ struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
+ struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
+ camio_ext = camdev->ioext;
+
+ appio = request_mem_region(camio_ext.appphy,
+ camio_ext.appsz, pdev->name);
+ if (!appio) {
+ rc = -EBUSY;
+ goto enable_fail;
+ }
+
+ appbase = ioremap(camio_ext.appphy,
+ camio_ext.appsz);
+ if (!appbase) {
+ rc = -ENOMEM;
+ goto apps_no_mem;
+ }
+
+ mdcio = request_mem_region(camio_ext.mdcphy,
+ camio_ext.mdcsz, pdev->name);
+ if (!mdcio) {
+ rc = -EBUSY;
+ goto mdc_busy;
+ }
+
+ mdcbase = ioremap(camio_ext.mdcphy,
+ camio_ext.mdcsz);
+ if (!mdcbase) {
+ rc = -ENOMEM;
+ goto mdc_no_mem;
+ }
+
+ camdev->camera_gpio_on();
+
+ msm_camio_clk_enable(CAMIO_VFE_CLK);
+ msm_camio_clk_enable(CAMIO_MDC_CLK);
+ msm_camio_clk_enable(CAMIO_VFE_MDC_CLK);
+ return 0;
+
+mdc_no_mem:
+ release_mem_region(camio_ext.mdcphy, camio_ext.mdcsz);
+mdc_busy:
+ iounmap(appbase);
+apps_no_mem:
+ release_mem_region(camio_ext.appphy, camio_ext.appsz);
+enable_fail:
+ return rc;
+}
+
+void msm_camio_disable(struct platform_device *pdev)
+{
+ struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
+ struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
+ iounmap(mdcbase);
+ release_mem_region(camio_ext.mdcphy, camio_ext.mdcsz);
+ iounmap(appbase);
+ release_mem_region(camio_ext.appphy, camio_ext.appsz);
+
+ camdev->camera_gpio_off();
+
+ msm_camio_clk_disable(CAMIO_VFE_CLK);
+ msm_camio_clk_disable(CAMIO_MDC_CLK);
+ msm_camio_clk_disable(CAMIO_VFE_MDC_CLK);
+}
+
+void msm_camio_camif_pad_reg_reset(void)
+{
+ uint32_t reg;
+ uint32_t mask, value;
+
+ /* select CLKRGM_VFE_SRC_CAM_VFE_SRC: internal source */
+ msm_camio_clk_sel(MSM_CAMIO_CLK_SRC_INTERNAL);
+
+ reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
+
+ mask = CAM_SEL_BMSK |
+ CAM_PCLK_SRC_SEL_BMSK |
+ CAM_PCLK_INVERT_BMSK;
+
+ value = 1 << CAM_SEL_SHFT |
+ 3 << CAM_PCLK_SRC_SEL_SHFT |
+ 0 << CAM_PCLK_INVERT_SHFT;
+
+ writel((reg & (~mask)) | (value & mask), mdcbase);
+ mdelay(10);
+
+ reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
+ mask = CAM_PAD_REG_SW_RESET_BMSK;
+ value = 1 << CAM_PAD_REG_SW_RESET_SHFT;
+ writel((reg & (~mask)) | (value & mask), mdcbase);
+ mdelay(10);
+
+ reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
+ mask = CAM_PAD_REG_SW_RESET_BMSK;
+ value = 0 << CAM_PAD_REG_SW_RESET_SHFT;
+ writel((reg & (~mask)) | (value & mask), mdcbase);
+ mdelay(10);
+
+ msm_camio_clk_sel(MSM_CAMIO_CLK_SRC_EXTERNAL);
+ mdelay(10);
+}
+
+void msm_camio_vfe_blk_reset(void)
+{
+ uint32_t val;
+
+ val = readl(appbase + 0x00000210);
+ val |= 0x1;
+ writel(val, appbase + 0x00000210);
+ mdelay(10);
+
+ val = readl(appbase + 0x00000210);
+ val &= ~0x1;
+ writel(val, appbase + 0x00000210);
+ mdelay(10);
+}
+
+void msm_camio_camif_pad_reg_reset_2(void)
+{
+ uint32_t reg;
+ uint32_t mask, value;
+
+ reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
+ mask = CAM_PAD_REG_SW_RESET_BMSK;
+ value = 1 << CAM_PAD_REG_SW_RESET_SHFT;
+ writel((reg & (~mask)) | (value & mask), mdcbase);
+ mdelay(10);
+
+ reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
+ mask = CAM_PAD_REG_SW_RESET_BMSK;
+ value = 0 << CAM_PAD_REG_SW_RESET_SHFT;
+ writel((reg & (~mask)) | (value & mask), mdcbase);
+ mdelay(10);
+}
+
+void msm_camio_clk_sel(enum msm_camio_clk_src_type srctype)
+{
+ struct clk *clk = NULL;
+
+ clk = camio_vfe_clk;
+
+ if (clk != NULL && clk != ERR_PTR(-ENOENT)) {
+ switch (srctype) {
+ case MSM_CAMIO_CLK_SRC_INTERNAL:
+ clk_set_flags(clk, 0x00000100 << 1);
+ break;
+
+ case MSM_CAMIO_CLK_SRC_EXTERNAL:
+ clk_set_flags(clk, 0x00000100);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+int msm_camio_probe_on(struct platform_device *pdev)
+{
+ struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
+ struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+ camdev->camera_gpio_on();
+ return msm_camio_clk_enable(CAMIO_VFE_CLK);
+}
+
+int msm_camio_probe_off(struct platform_device *pdev)
+{
+ struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
+ struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+ camdev->camera_gpio_off();
+ return msm_camio_clk_disable(CAMIO_VFE_CLK);
+}