From 6e9a8ed420020b5692b511b3e8a7c2c1325e1ca2 Mon Sep 17 00:00:00 2001
From: Penda, Naveen <pnaveen@ti.com>
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 <pnaveen@ti.com>
Signed-off-by: Curran, Dominic <dcurran@ti.com>
---
 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

