summaryrefslogtreecommitdiff
path: root/drivers/media/platform/qcom/venus/pm_helpers.c
diff options
context:
space:
mode:
authorStanimir Varbanov <stanimir.varbanov@linaro.org>2021-04-02 13:06:25 +0300
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>2021-04-06 16:18:25 +0300
commit3bca43585e2216611c766c2108ac476b7dd9e3a8 (patch)
treedc7774d7e2cb211fcd32a80d158d6d4db03988a3 /drivers/media/platform/qcom/venus/pm_helpers.c
parentdaba0a10c585b3736142d8f7ff81590b1ec1da7e (diff)
downloadlinux-3bca43585e2216611c766c2108ac476b7dd9e3a8.tar.xz
media: venus: core,pm: Add handling for resets
The Venus driver has to control two reset signals related to gcc video_axi0 and videocc mvs0c for v6. Add it. Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Diffstat (limited to 'drivers/media/platform/qcom/venus/pm_helpers.c')
-rw-r--r--drivers/media/platform/qcom/venus/pm_helpers.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c
index 95b4d40ff6a5..794c2d6f0543 100644
--- a/drivers/media/platform/qcom/venus/pm_helpers.c
+++ b/drivers/media/platform/qcom/venus/pm_helpers.c
@@ -11,6 +11,7 @@
#include <linux/pm_domain.h>
#include <linux/pm_opp.h>
#include <linux/pm_runtime.h>
+#include <linux/reset.h>
#include <linux/types.h>
#include <media/v4l2-mem2mem.h>
@@ -847,6 +848,52 @@ skip_pmdomains:
dev_pm_opp_detach_genpd(core->opp_table);
}
+static int core_resets_reset(struct venus_core *core)
+{
+ const struct venus_resources *res = core->res;
+ unsigned char i;
+ int ret;
+
+ if (!res->resets_num)
+ return 0;
+
+ for (i = 0; i < res->resets_num; i++) {
+ ret = reset_control_assert(core->resets[i]);
+ if (ret)
+ goto err;
+
+ usleep_range(150, 250);
+ ret = reset_control_deassert(core->resets[i]);
+ if (ret)
+ goto err;
+ }
+
+err:
+ return ret;
+}
+
+static int core_resets_get(struct venus_core *core)
+{
+ struct device *dev = core->dev;
+ const struct venus_resources *res = core->res;
+ unsigned char i;
+ int ret;
+
+ if (!res->resets_num)
+ return 0;
+
+ for (i = 0; i < res->resets_num; i++) {
+ core->resets[i] =
+ devm_reset_control_get_exclusive(dev, res->resets[i]);
+ if (IS_ERR(core->resets[i])) {
+ ret = PTR_ERR(core->resets[i]);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static int core_get_v4(struct venus_core *core)
{
struct device *dev = core->dev;
@@ -870,6 +917,10 @@ static int core_get_v4(struct venus_core *core)
if (ret)
return ret;
+ ret = core_resets_get(core);
+ if (ret)
+ return ret;
+
if (legacy_binding)
return 0;
@@ -929,6 +980,13 @@ static int core_power_v4(struct venus_core *core, int on)
}
}
+ ret = core_resets_reset(core);
+ if (ret) {
+ if (pmctrl)
+ pm_runtime_put_sync(pmctrl);
+ return ret;
+ }
+
ret = core_clks_enable(core);
if (ret < 0 && pmctrl)
pm_runtime_put_sync(pmctrl);
@@ -939,6 +997,8 @@ static int core_power_v4(struct venus_core *core, int on)
core_clks_disable(core);
+ ret = core_resets_reset(core);
+
if (pmctrl)
pm_runtime_put_sync(pmctrl);
}