@@ -991,6 +991,52 @@ void isp_sbl_disable(struct isp_device *isp, enum isp_sbl_resource res)
* Clock management
*/
+#define ISPCTRL_CLKS_MASK (ISPCTRL_H3A_CLK_EN | \
+ ISPCTRL_HIST_CLK_EN | \
+ ISPCTRL_RSZ_CLK_EN | \
+ (ISPCTRL_CCDC_CLK_EN | ISPCTRL_CCDC_RAM_EN) | \
+ (ISPCTRL_PREV_CLK_EN | ISPCTRL_PREV_RAM_EN))
+
+static void __isp_subclk_update(struct isp_device *isp)
+{
+ u32 clk = 0;
+
+ if (isp->subclk_resources & OMAP3_ISP_SUBCLK_H3A)
+ clk |= ISPCTRL_H3A_CLK_EN;
+
+ if (isp->subclk_resources & OMAP3_ISP_SUBCLK_HIST)
+ clk |= ISPCTRL_HIST_CLK_EN;
+
+ if (isp->subclk_resources & OMAP3_ISP_SUBCLK_RESIZER)
+ clk |= ISPCTRL_RSZ_CLK_EN;
+
+ /* NOTE: For CCDC & Preview submodules, we need to affect internal
+ * RAM aswell.
+ */
+ if (isp->subclk_resources & OMAP3_ISP_SUBCLK_CCDC)
+ clk |= ISPCTRL_CCDC_CLK_EN | ISPCTRL_CCDC_RAM_EN;
+
+ if (isp->subclk_resources & OMAP3_ISP_SUBCLK_PREVIEW)
+ clk |= ISPCTRL_PREV_CLK_EN | ISPCTRL_PREV_RAM_EN;
+
+ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
+ ISPCTRL_CLKS_MASK, clk);
+}
+
+void isp_subclk_enable(struct isp_device *isp, enum isp_subclk_resource res)
+{
+ isp->subclk_resources |= res;
+
+ __isp_subclk_update(isp);
+}
+
+void isp_subclk_disable(struct isp_device *isp, enum isp_subclk_resource res)
+{
+ isp->subclk_resources &= ~res;
+
+ __isp_subclk_update(isp);
+}
+
/*
* isp_enable_clocks - Enable ISP clocks
* @isp: OMAP3 ISP device
@@ -85,6 +85,14 @@ enum isp_sbl_resource {
OMAP3_ISP_SBL_RESIZER_WRITE = 0x200,
};
+enum isp_subclk_resource {
+ OMAP3_ISP_SUBCLK_CCDC = (1 << 0),
+ OMAP3_ISP_SUBCLK_H3A = (1 << 1),
+ OMAP3_ISP_SUBCLK_HIST = (1 << 2),
+ OMAP3_ISP_SUBCLK_PREVIEW = (1 << 3),
+ OMAP3_ISP_SUBCLK_RESIZER = (1 << 4),
+};
+
enum isp_interface_type {
ISP_INTERFACE_PARALLEL,
ISP_INTERFACE_CSI2A_PHY2,
@@ -262,6 +270,7 @@ struct isp_device {
struct isp_csiphy isp_csiphy2;
unsigned int sbl_resources;
+ unsigned int subclk_resources;
struct iommu *iommu;
};
@@ -294,6 +303,9 @@ void isp_print_status(struct isp_device *isp);
void isp_sbl_enable(struct isp_device *isp, enum isp_sbl_resource res);
void isp_sbl_disable(struct isp_device *isp, enum isp_sbl_resource res);
+void isp_subclk_enable(struct isp_device *isp, enum isp_subclk_resource res);
+void isp_subclk_disable(struct isp_device *isp, enum isp_subclk_resource res);
+
int omap3isp_register_entities(struct platform_device *pdev,
struct v4l2_device *v4l2_dev);
void omap3isp_unregister_entities(struct platform_device *pdev);
@@ -1687,8 +1687,7 @@ static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
if (enable == ISP_PIPELINE_STREAM_STOPPED)
return 0;
- isp_reg_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
- ISPCTRL_CCDC_RAM_EN | ISPCTRL_CCDC_CLK_EN);
+ isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_CCDC);
isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
ISPCCDC_CFG_VDLC);
@@ -1725,8 +1724,7 @@ static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
ret = ispccdc_disable(ccdc);
if (ccdc->output & CCDC_OUTPUT_MEMORY)
isp_sbl_disable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
- isp_reg_clr(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
- ISPCTRL_CCDC_CLK_EN | ISPCTRL_CCDC_RAM_EN);
+ isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_CCDC);
ccdc->underrun = 0;
break;
}
@@ -1648,8 +1648,7 @@ static int preview_set_stream(struct v4l2_subdev *sd, int enable)
if (enable == ISP_PIPELINE_STREAM_STOPPED)
return 0;
- isp_reg_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
- ISPCTRL_PREV_RAM_EN | ISPCTRL_PREV_CLK_EN);
+ isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
preview_configure(prev);
isppreview_print_status(prev);
}
@@ -1677,8 +1676,7 @@ static int preview_set_stream(struct v4l2_subdev *sd, int enable)
case ISP_PIPELINE_STREAM_STOPPED:
isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
- isp_reg_clr(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
- ISPCTRL_PREV_CLK_EN | ISPCTRL_PREV_RAM_EN);
+ isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
prev->underrun = 0;
break;
}
@@ -1120,8 +1120,7 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
if (enable != ISP_PIPELINE_STREAM_STOPPED &&
res->state == ISP_PIPELINE_STREAM_STOPPED) {
- isp_reg_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
- ISPCTRL_RSZ_CLK_EN);
+ isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_RESIZER);
resizer_configure(res);
ispresizer_print_status(res);
}
@@ -1146,8 +1145,7 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
case ISP_PIPELINE_STREAM_STOPPED:
isp_sbl_disable(isp, OMAP3_ISP_SBL_RESIZER_READ |
OMAP3_ISP_SBL_RESIZER_WRITE);
- isp_reg_clr(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
- ISPCTRL_RSZ_CLK_EN);
+ isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_RESIZER);
res->underrun = 0;
break;
}