diff options
author | Stanimir Varbanov <stanimir.varbanov@linaro.org> | 2021-04-02 13:06:25 +0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 2021-04-06 16:18:25 +0300 |
commit | 3bca43585e2216611c766c2108ac476b7dd9e3a8 (patch) | |
tree | dc7774d7e2cb211fcd32a80d158d6d4db03988a3 /drivers/media/platform/qcom/venus/pm_helpers.c | |
parent | daba0a10c585b3736142d8f7ff81590b1ec1da7e (diff) | |
download | linux-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.c | 60 |
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); } |