From 6e9a8ed420020b5692b511b3e8a7c2c1325e1ca2 Mon Sep 17 00:00:00 2001 From: Penda, Naveen Date: Thu, 22 Oct 2009 06:07:01 +0530 Subject: [PATCH 18/75] Fix: Moved MCLK setting to the board file This patch provides the flexibility to set the MCLK frequency from the board file Signed-off-by: Naveen Penda Signed-off-by: Curran, Dominic --- arch/arm/mach-omap2/board-zoom2-camera.c | 10 ++++++ drivers/media/video/isp/isp.c | 51 +++++++++++++++++++---------- drivers/media/video/isp/isp.h | 6 +++ 3 files changed, 49 insertions(+), 18 deletions(-) diff --git a/arch/arm/mach-omap2/board-zoom2-camera.c b/arch/arm/mach-omap2/board-zoom2-camera.c index 1ba2982..8c035c4 100644 --- a/arch/arm/mach-omap2/board-zoom2-camera.c +++ b/arch/arm/mach-omap2/board-zoom2-camera.c @@ -41,6 +41,8 @@ static struct device *zoom2cam_dev; #define CAMZOOM2_USE_XCLKB 1 +#define ISP_IMX046_MCLK 216000000 + /* Sensor specific GPIO signals */ #define IMX046_RESET_GPIO 98 #define IMX046_STANDBY_GPIO 58 @@ -148,6 +150,7 @@ static struct isp_interface_config imx046_if_config = { .shutter = 0x0, .wenlog = ISPCCDC_CFG_WENLOG_AND, .wait_hs_vs = 2, + .cam_mclk = ISP_IMX046_MCLK, .u.csi.crc = 0x0, .u.csi.mode = 0x0, .u.csi.edge = 0x0, @@ -264,6 +267,8 @@ static int imx046_sensor_power_set(struct v4l2_int_device *s, enum v4l2_power po #ifdef CONFIG_OMAP_PM_SRF omap_pm_set_min_bus_tput(vdev->cam->isp, OCP_INITIATOR_AGENT, 0); #endif + if (previous_power != V4L2_POWER_OFF) + isp_disable_mclk(isp); break; case V4L2_POWER_STANDBY: printk(KERN_DEBUG "imx046_sensor_power_set(STANDBY)\n"); @@ -272,9 +277,14 @@ static int imx046_sensor_power_set(struct v4l2_int_device *s, enum v4l2_power po #ifdef CONFIG_OMAP_PM_SRF omap_pm_set_min_bus_tput(vdev->cam->isp, OCP_INITIATOR_AGENT, 0); #endif + + + isp_disable_mclk(isp); + break; } + /* Save powerstate to know what was before calling POWER_ON. */ previous_power = power; return err; diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c index 9d46c01..cf68720 100644 --- a/drivers/media/video/isp/isp.c +++ b/drivers/media/video/isp/isp.c @@ -552,7 +552,7 @@ EXPORT_SYMBOL(isp_unset_callback); * Configures the specified MCLK divisor in the ISP timing control register * (TCTRL_CTRL) to generate the desired xclk clock value. * - * Divisor = CM_CAM_MCLK_HZ / xclk + * Divisor = mclk / xclk * * Returns the final frequency that is actually being generated **/ @@ -560,15 +560,16 @@ u32 isp_set_xclk(struct device *dev, u32 xclk, u8 xclksel) { u32 divisor; u32 currentxclk; + struct isp_device *isp = dev_get_drvdata(dev); - if (xclk >= CM_CAM_MCLK_HZ) { + if (xclk >= isp->mclk) { divisor = ISPTCTRL_CTRL_DIV_BYPASS; - currentxclk = CM_CAM_MCLK_HZ; + currentxclk = isp->mclk; } else if (xclk >= 2) { - divisor = CM_CAM_MCLK_HZ / xclk; + divisor = isp->mclk / xclk; if (divisor >= ISPTCTRL_CTRL_DIV_BYPASS) divisor = ISPTCTRL_CTRL_DIV_BYPASS - 1; - currentxclk = CM_CAM_MCLK_HZ / divisor; + currentxclk = isp->mclk / divisor; } else { divisor = xclk; currentxclk = 0; @@ -874,6 +875,8 @@ int isp_configure_interface(struct device *dev, /* Set sensor specific fields in CCDC and Previewer module. */ ispccdc_set_wenlog(&isp->isp_ccdc, config->wenlog); + isp->mclk = config->cam_mclk; + isp_enable_mclk(dev); /* FIXME: this should be set in ispccdc_config_vp() */ fmtcfg = isp_reg_readl(dev, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG); fmtcfg &= ISPCCDC_FMTCFG_VPIF_FRQ_MASK; @@ -2333,16 +2336,6 @@ static int isp_enable_clocks(struct device *dev) dev_err(dev, "clk_enable cam_ick failed\n"); goto out_clk_enable_ick; } - r = clk_set_rate(isp->dpll4_m5_ck, CM_CAM_MCLK_HZ/2); - if (r) { - dev_err(dev, "clk_set_rate for dpll4_m5_ck failed\n"); - goto out_clk_enable_mclk; - } - r = clk_enable(isp->cam_mclk); - if (r) { - dev_err(dev, "clk_enable cam_mclk failed\n"); - goto out_clk_enable_mclk; - } r = clk_enable(isp->csi2_fck); if (r) { dev_err(dev, "clk_enable csi2_fck failed\n"); @@ -2351,13 +2344,34 @@ static int isp_enable_clocks(struct device *dev) return 0; out_clk_enable_csi2_fclk: - clk_disable(isp->cam_mclk); -out_clk_enable_mclk: clk_disable(isp->cam_ick); out_clk_enable_ick: return r; } +int isp_enable_mclk(struct device *dev) +{ + struct isp_device *isp = dev_get_drvdata(dev); + int r; + + r = clk_set_rate(isp->dpll4_m5_ck, isp->mclk); + if (r) { + dev_err(dev, "clk_set_rate for dpll4_m5_ck failed\n"); + return r; + } + r = clk_enable(isp->cam_mclk); + if (r) { + dev_err(dev, "clk_enable cam_mclk failed\n"); + return r; + } + return 0; +} + +void isp_disable_mclk(struct isp_device *isp) +{ + clk_disable(isp->cam_mclk); +} + /** * isp_disable_clocks - Disable ISP clocks * @dev: Device pointer specific to the OMAP3 ISP. @@ -2367,7 +2381,6 @@ static void isp_disable_clocks(struct device *dev) struct isp_device *isp = dev_get_drvdata(dev); clk_disable(isp->cam_ick); - clk_disable(isp->cam_mclk); clk_disable(isp->csi2_fck); } @@ -2668,6 +2681,8 @@ static int isp_probe(struct platform_device *pdev) goto out_free_mmio; } + isp->mclk = CM_CAM_MCLK_HZ / 2; + isp->cam_ick = clk_get(&camera_dev, "cam_ick"); if (IS_ERR(isp->cam_ick)) { dev_err(isp->dev, "clk_get cam_ick failed\n"); diff --git a/drivers/media/video/isp/isp.h b/drivers/media/video/isp/isp.h index 6b100b6..85c3fa9 100644 --- a/drivers/media/video/isp/isp.h +++ b/drivers/media/video/isp/isp.h @@ -199,6 +199,7 @@ struct isp_interface_config { u32 prev_slv; u32 wenlog; int wait_hs_vs; + u32 cam_mclk; unsigned int pixelclk; union { struct par { @@ -425,6 +426,7 @@ struct isp_device { struct isp_irq irq; struct isp_pipeline pipeline; u32 interrupts; + u32 mclk; enum isp_running running; int current_field; int bt656ifen; @@ -489,6 +491,10 @@ struct device *isp_get(void); int isp_put(void); +int isp_enable_mclk(struct device *dev); + +void isp_disable_mclk(struct isp_device *dev); + int isp_queryctrl(struct v4l2_queryctrl *a); int isp_querymenu(struct v4l2_querymenu *a); -- 1.6.6.1