From 2164330c88cbca1efd2d954371277b51788e530b Mon Sep 17 00:00:00 2001 From: Robby Cai Date: Wed, 19 Mar 2014 18:27:20 +0800 Subject: [PATCH] ENGR00300658-6 csi: imx6sx: add clock handling in driver 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 --- .../platform/mxc/capture/csi_v4l2_capture.c | 2 + drivers/media/platform/mxc/capture/fsl_csi.c | 38 +++++++++++++++++++ drivers/media/platform/mxc/capture/fsl_csi.h | 4 +- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/mxc/capture/csi_v4l2_capture.c b/drivers/media/platform/mxc/capture/csi_v4l2_capture.c index 1947896947a3..fe8594363a7a 100644 --- a/drivers/media/platform/mxc/capture/csi_v4l2_capture.c +++ b/drivers/media/platform/mxc/capture/csi_v4l2_capture.c @@ -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; diff --git a/drivers/media/platform/mxc/capture/fsl_csi.c b/drivers/media/platform/mxc/capture/fsl_csi.c index 1808ef93a76d..0a1770648a3a 100644 --- a/drivers/media/platform/mxc/capture/fsl_csi.c +++ b/drivers/media/platform/mxc/capture/fsl_csi.c @@ -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; diff --git a/drivers/media/platform/mxc/capture/fsl_csi.h b/drivers/media/platform/mxc/capture/fsl_csi.h index f5a1c5bdf938..d9d179b41da4 100644 --- a/drivers/media/platform/mxc/capture/fsl_csi.h +++ b/drivers/media/platform/mxc/capture/fsl_csi.h @@ -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); -- 2.34.1