Commit 3e20c345 authored by Sylwester Nawrocki's avatar Sylwester Nawrocki Committed by Mauro Carvalho Chehab

[media] s5p-fimc: Ensure CAMCLK clock can be enabled by FIMC-LITE devices

In configurations where FIMC-LITE is used to capture image signal
from an external sensor only we need to ensure one of FIMC devices
is in active power state and the "fimc" gate clock is enabled.
Otherwise the CAMCLK clock output signal will be masked off
preventing an external sensor's operation.
This affect processing pipelines like:
 - sensor -> FIMC-LITE -> memory
 - sensor -> MIPI-CSIS -> FIMC-LITE -> memory
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 88fa8311
...@@ -509,7 +509,6 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) ...@@ -509,7 +509,6 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
{ {
struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data; struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data;
struct device_node *of_node = fmd->pdev->dev.of_node; struct device_node *of_node = fmd->pdev->dev.of_node;
struct fimc_dev *fd = NULL;
int num_clients = 0; int num_clients = 0;
int ret, i; int ret, i;
...@@ -517,13 +516,10 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) ...@@ -517,13 +516,10 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
* Runtime resume one of the FIMC entities to make sure * Runtime resume one of the FIMC entities to make sure
* the sclk_cam clocks are not globally disabled. * the sclk_cam clocks are not globally disabled.
*/ */
for (i = 0; !fd && i < ARRAY_SIZE(fmd->fimc); i++) if (!fmd->pmf)
if (fmd->fimc[i])
fd = fmd->fimc[i];
if (!fd)
return -ENXIO; return -ENXIO;
ret = pm_runtime_get_sync(&fd->pdev->dev); ret = pm_runtime_get_sync(fmd->pmf);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -557,7 +553,7 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) ...@@ -557,7 +553,7 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
} }
} }
pm_runtime_put(&fd->pdev->dev); pm_runtime_put(fmd->pmf);
return ret; return ret;
} }
...@@ -602,6 +598,8 @@ static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc) ...@@ -602,6 +598,8 @@ static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc)
ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
if (!ret) { if (!ret) {
if (!fmd->pmf && fimc->pdev)
fmd->pmf = &fimc->pdev->dev;
fmd->fimc[fimc->id] = fimc; fmd->fimc[fimc->id] = fimc;
fimc->vid_cap.user_subdev_api = fmd->user_subdev_api; fimc->vid_cap.user_subdev_api = fmd->user_subdev_api;
} else { } else {
...@@ -1085,7 +1083,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, ...@@ -1085,7 +1083,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
struct fimc_camclk_info *camclk; struct fimc_camclk_info *camclk;
int ret = 0; int ret = 0;
if (WARN_ON(pdata->clk_id >= FIMC_MAX_CAMCLKS) || fmd == NULL) if (WARN_ON(pdata->clk_id >= FIMC_MAX_CAMCLKS) || !fmd || !fmd->pmf)
return -EINVAL; return -EINVAL;
camclk = &fmd->camclk[pdata->clk_id]; camclk = &fmd->camclk[pdata->clk_id];
...@@ -1101,6 +1099,9 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, ...@@ -1101,6 +1099,9 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
if (camclk->use_count++ == 0) { if (camclk->use_count++ == 0) {
clk_set_rate(camclk->clock, pdata->clk_frequency); clk_set_rate(camclk->clock, pdata->clk_frequency);
camclk->frequency = pdata->clk_frequency; camclk->frequency = pdata->clk_frequency;
ret = pm_runtime_get_sync(fmd->pmf);
if (ret < 0)
return ret;
ret = clk_enable(camclk->clock); ret = clk_enable(camclk->clock);
dbg("Enabled camclk %d: f: %lu", pdata->clk_id, dbg("Enabled camclk %d: f: %lu", pdata->clk_id,
clk_get_rate(camclk->clock)); clk_get_rate(camclk->clock));
...@@ -1113,6 +1114,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, ...@@ -1113,6 +1114,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
if (--camclk->use_count == 0) { if (--camclk->use_count == 0) {
clk_disable(camclk->clock); clk_disable(camclk->clock);
pm_runtime_put(fmd->pmf);
dbg("Disabled camclk %d", pdata->clk_id); dbg("Disabled camclk %d", pdata->clk_id);
} }
return ret; return ret;
......
...@@ -81,6 +81,7 @@ struct fimc_sensor_info { ...@@ -81,6 +81,7 @@ struct fimc_sensor_info {
* @camclk: external sensor clock information * @camclk: external sensor clock information
* @fimc: array of registered fimc devices * @fimc: array of registered fimc devices
* @use_isp: set to true when FIMC-IS subsystem is used * @use_isp: set to true when FIMC-IS subsystem is used
* @pmf: handle to the CAMCLK clock control FIMC helper device
* @media_dev: top level media device * @media_dev: top level media device
* @v4l2_dev: top level v4l2_device holding up the subdevs * @v4l2_dev: top level v4l2_device holding up the subdevs
* @pdev: platform device this media device is hooked up into * @pdev: platform device this media device is hooked up into
...@@ -99,6 +100,7 @@ struct fimc_md { ...@@ -99,6 +100,7 @@ struct fimc_md {
struct fimc_lite *fimc_lite[FIMC_LITE_MAX_DEVS]; struct fimc_lite *fimc_lite[FIMC_LITE_MAX_DEVS];
struct fimc_dev *fimc[FIMC_MAX_DEVS]; struct fimc_dev *fimc[FIMC_MAX_DEVS];
bool use_isp; bool use_isp;
struct device *pmf;
struct media_device media_dev; struct media_device media_dev;
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
struct platform_device *pdev; struct platform_device *pdev;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment