summaryrefslogtreecommitdiff
path: root/drivers/media
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2016-08-01 13:55:21 +0200
committerSeung-Woo Kim <sw0312.kim@samsung.com>2016-12-14 13:52:06 +0900
commit4f68f6337d58b19765359d86745598850265cea9 (patch)
treed78700113a674b3c344725f6ffeaf17f71b755e7 /drivers/media
parent2b86f450c476d93f4083e8b05cd256f96c6fd586 (diff)
media: s5p-mfc: use clock gating only on mfc v5 hardware
Software clock gating causes unpredicted behavior of newer MFC hardware, so use it only when working with v5 module. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Change-Id: I5a636b9c46b5e387da4d1c4f6dbb4adb583085e3
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc.c1
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_common.h2
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_pm.c23
3 files changed, 23 insertions, 3 deletions
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index a955eec71548..7af9facc85d4 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1340,6 +1340,7 @@ static struct s5p_mfc_variant mfc_drvdata_v5 = {
.fw_name[0] = "s5p-mfc.fw",
.clk_names = {"mfc", "sclk_mfc"},
.num_clocks = 2,
+ .use_clock_gating = true,
};
static struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 9ef00c485fb5..9a9d7332491e 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -200,6 +200,7 @@ struct s5p_mfc_pm {
const char **clk_names;
struct clk *clocks[MFC_MAX_CLOCKS];
int num_clocks;
+ bool use_clock_gating;
atomic_t power;
struct device *device;
@@ -239,6 +240,7 @@ struct s5p_mfc_variant {
char *fw_name[MFC_FW_MAX_VERSIONS];
const char *clk_names[MFC_MAX_CLOCKS];
int num_clocks;
+ bool use_clock_gating;
};
/**
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
index d21055e19a71..cdeed6731784 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
@@ -37,6 +37,7 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
pm->num_clocks = dev->variant->num_clocks;
pm->clk_names = dev->variant->clk_names;
+ pm->use_clock_gating = dev->variant->use_clock_gating;
/* clock control */
for (i = 0; i < pm->num_clocks; i++) {
@@ -73,6 +74,8 @@ int s5p_mfc_clock_on(void)
atomic_inc(&clk_ref);
mfc_debug(3, "+ %d\n", atomic_read(&clk_ref));
#endif
+ if (!pm->use_clock_gating)
+ return 0;
for (i = 0; i < pm->num_clocks; i++) {
ret = clk_enable(pm->clocks[i]);
@@ -92,6 +95,9 @@ void s5p_mfc_clock_off(void)
atomic_dec(&clk_ref);
mfc_debug(3, "- %d\n", atomic_read(&clk_ref));
#endif
+ if (!pm->use_clock_gating)
+ return;
+
for (i = pm->num_clocks - 1; i >= 0; i--)
clk_disable(pm->clocks[i]);
}
@@ -109,7 +115,11 @@ int s5p_mfc_power_on(void)
#endif
/* clock control */
for (i = 0; i < pm->num_clocks; i++) {
- ret = clk_prepare(pm->clocks[i]);
+ if (pm->use_clock_gating)
+ ret = clk_prepare(pm->clocks[i]);
+ else
+ ret = clk_prepare_enable(pm->clocks[i]);
+
if (ret < 0) {
mfc_err("clock prepare failed for clock: %s\n",
pm->clk_names[i]);
@@ -121,7 +131,10 @@ int s5p_mfc_power_on(void)
return 0;
err:
while (--i > 0)
- clk_unprepare(pm->clocks[i]);
+ if (pm->use_clock_gating)
+ clk_disable(pm->clocks[i]);
+ else
+ clk_disable_unprepare(pm->clocks[i]);
pm_runtime_put(pm->device);
return ret;
}
@@ -129,8 +142,12 @@ err:
int s5p_mfc_power_off(void)
{
int i;
+
for (i = 0; i < pm->num_clocks; i++)
- clk_unprepare(pm->clocks[i]);
+ if (pm->use_clock_gating)
+ clk_unprepare(pm->clocks[i]);
+ else
+ clk_disable_unprepare(pm->clocks[i]);
#ifdef CONFIG_PM
return pm_runtime_put_sync(pm->device);