[media] exynos4-is: Ensure fimc-is clocks are not enabled until properly configured

Use clk_prepare_enable/clk_unprepare_disable instead of preparing the
clocks during the driver initalization and then using just clk_disable/
clk_enable. The clock framework doesn't guarantee a clock will not get
enabled during e.g. clk_set_parent if clk_prepare has been called on it.
So we ensure clk_prepare() is called only when it is safe to enable
the clocks, i.e. the parent clocks and the clocks' frequencies are set.
It must be ensured the FIMC-IS clocks have proper frequencies before they
are enabled, otherwise the whole system will hang.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyunmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Sylwester Nawrocki 2013-05-31 08:40:36 -03:00 committed by Mauro Carvalho Chehab
parent 3cf138a639
commit b4155d7d5b
1 changed files with 3 additions and 10 deletions

View File

@ -71,7 +71,6 @@ static void fimc_is_put_clocks(struct fimc_is *is)
for (i = 0; i < ISS_CLKS_MAX; i++) { for (i = 0; i < ISS_CLKS_MAX; i++) {
if (IS_ERR(is->clocks[i])) if (IS_ERR(is->clocks[i]))
continue; continue;
clk_unprepare(is->clocks[i]);
clk_put(is->clocks[i]); clk_put(is->clocks[i]);
is->clocks[i] = ERR_PTR(-EINVAL); is->clocks[i] = ERR_PTR(-EINVAL);
} }
@ -90,12 +89,6 @@ static int fimc_is_get_clocks(struct fimc_is *is)
ret = PTR_ERR(is->clocks[i]); ret = PTR_ERR(is->clocks[i]);
goto err; goto err;
} }
ret = clk_prepare(is->clocks[i]);
if (ret < 0) {
clk_put(is->clocks[i]);
is->clocks[i] = ERR_PTR(-EINVAL);
goto err;
}
} }
return 0; return 0;
@ -103,7 +96,7 @@ static int fimc_is_get_clocks(struct fimc_is *is)
fimc_is_put_clocks(is); fimc_is_put_clocks(is);
dev_err(&is->pdev->dev, "failed to get clock: %s\n", dev_err(&is->pdev->dev, "failed to get clock: %s\n",
fimc_is_clocks[i]); fimc_is_clocks[i]);
return -ENXIO; return ret;
} }
static int fimc_is_setup_clocks(struct fimc_is *is) static int fimc_is_setup_clocks(struct fimc_is *is)
@ -144,7 +137,7 @@ int fimc_is_enable_clocks(struct fimc_is *is)
for (i = 0; i < ISS_GATE_CLKS_MAX; i++) { for (i = 0; i < ISS_GATE_CLKS_MAX; i++) {
if (IS_ERR(is->clocks[i])) if (IS_ERR(is->clocks[i]))
continue; continue;
ret = clk_enable(is->clocks[i]); ret = clk_prepare_enable(is->clocks[i]);
if (ret < 0) { if (ret < 0) {
dev_err(&is->pdev->dev, "clock %s enable failed\n", dev_err(&is->pdev->dev, "clock %s enable failed\n",
fimc_is_clocks[i]); fimc_is_clocks[i]);
@ -163,7 +156,7 @@ void fimc_is_disable_clocks(struct fimc_is *is)
for (i = 0; i < ISS_GATE_CLKS_MAX; i++) { for (i = 0; i < ISS_GATE_CLKS_MAX; i++) {
if (!IS_ERR(is->clocks[i])) { if (!IS_ERR(is->clocks[i])) {
clk_disable(is->clocks[i]); clk_disable_unprepare(is->clocks[i]);
pr_debug("disabled clock: %s\n", fimc_is_clocks[i]); pr_debug("disabled clock: %s\n", fimc_is_clocks[i]);
} }
} }