ENGR00300658-6 csi: imx6sx: add clock handling in driver
authorRobby Cai <R63905@freescale.com>
Wed, 19 Mar 2014 10:27:20 +0000 (18:27 +0800)
committerNitin Garg <nitin.garg@freescale.com>
Wed, 16 Apr 2014 13:58:06 +0000 (08:58 -0500)
According to IC team, DCIC1 clock is used in the IPSYNC for CSI1 and
DCIC2 clock is used in the IPSYNC for the CSI2. So dcic clock is needed for CSI.

The display axi clock is a clock gating newly added on imx6sx.
It needs to be enabled for lcdif/pxp/csi/pcie to work.

CSI clock seems to be implemented different other than other SoCs.
It needs also to be enabled before access the registers, otherwise
the system will hang.

Signed-off-by: Robby Cai <R63905@freescale.com>
drivers/media/platform/mxc/capture/csi_v4l2_capture.c
drivers/media/platform/mxc/capture/fsl_csi.c
drivers/media/platform/mxc/capture/fsl_csi.h

index 1947896947a3db22a61b24a8f6985471c3c6540a..fe8594363a7a66517b3d9448b5af4b347af1827f 100644 (file)
@@ -1148,6 +1148,7 @@ static int csi_v4l_open(struct file *file)
                vidioc_int_g_ifparm(cam->sensor, &ifparm);
 
                cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               csi_clk_enable();
                clk_prepare_enable(sensor->sensor_clk);
                vidioc_int_s_power(cam->sensor, 1);
                vidioc_int_init(cam->sensor);
@@ -1205,6 +1206,7 @@ static int csi_v4l_close(struct file *file)
                file->private_data = NULL;
                vidioc_int_s_power(cam->sensor, 0);
                clk_disable_unprepare(sensor->sensor_clk);
+               csi_clk_disable();
        }
 
        return err;
index 1808ef93a76d33703bc5f46a32a7cb5b4a704a78..0a1770648a3aafd655ea354ee31107c38731de3f 100644 (file)
@@ -38,6 +38,25 @@ EXPORT_SYMBOL(csi_regbase);
 static int irq_nr;
 static csi_irq_callback_t g_callback;
 static void *g_callback_data;
+static struct clk *disp_axi_clk;
+static struct clk *dcic_clk;
+static struct clk *csi_clk;
+
+void csi_clk_enable(void)
+{
+       clk_prepare_enable(disp_axi_clk);
+       clk_prepare_enable(dcic_clk);
+       clk_prepare_enable(csi_clk);
+}
+EXPORT_SYMBOL(csi_clk_enable);
+
+void csi_clk_disable(void)
+{
+       clk_disable_unprepare(csi_clk);
+       clk_disable_unprepare(dcic_clk);
+       clk_disable_unprepare(disp_axi_clk);
+}
+EXPORT_SYMBOL(csi_clk_disable);
 
 static irqreturn_t csi_irq_handler(int irq, void *data)
 {
@@ -285,9 +304,28 @@ static int csi_probe(struct platform_device *pdev)
                goto err;
        }
 
+       disp_axi_clk = devm_clk_get(&pdev->dev, "disp-axi");
+       if (IS_ERR(disp_axi_clk)) {
+               dev_err(&pdev->dev, "get csi clock failed\n");
+               return PTR_ERR(disp_axi_clk);
+       }
+       csi_clk = devm_clk_get(&pdev->dev, "csi_mclk");
+       if (IS_ERR(csi_clk)) {
+               dev_err(&pdev->dev, "get csi mclk failed\n");
+               return PTR_ERR(csi_clk);
+       }
+
+       dcic_clk = devm_clk_get(&pdev->dev, "dcic");
+       if (IS_ERR(dcic_clk)) {
+               dev_err(&pdev->dev, "get dcic clk failed\n");
+               return PTR_ERR(dcic_clk);
+       }
+
+       csi_clk_enable();
        csihw_reset();
        csi_init_interface();
        csi_dmareq_rff_disable();
+       csi_clk_disable();
 
 err:
        return ret;
index f5a1c5bdf938d3650bd8129da7d09d95b0addaa4..d9d179b41da402a4cd24da0ffb8e2f32fe697904 100644 (file)
@@ -199,7 +199,7 @@ void csi_stop_callback(void *data);
 void csi_enable_int(int arg);
 void csi_enable(int arg);
 void csi_disable_int(void);
-void csi_mclk_enable(void);
-void csi_mclk_disable(void);
+void csi_clk_enable(void);
+void csi_clk_disable(void);
 void csi_dmareq_rff_enable(void);
 void csi_dmareq_rff_disable(void);