media: venus: core,pm: Add handling for resets
authorStanimir Varbanov <stanimir.varbanov@linaro.org>
Fri, 2 Apr 2021 10:06:25 +0000 (12:06 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Tue, 6 Apr 2021 13:18:25 +0000 (15:18 +0200)
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>
drivers/media/platform/qcom/venus/core.h
drivers/media/platform/qcom/venus/pm_helpers.c

index c0b8b83..4ccac00 100644 (file)
@@ -24,6 +24,7 @@
 #define VIDC_CLKS_NUM_MAX              4
 #define VIDC_VCODEC_CLKS_NUM_MAX       2
 #define VIDC_PMDOMAINS_NUM_MAX         3
+#define VIDC_RESETS_NUM_MAX            2
 
 extern int venus_fw_debug;
 
@@ -64,6 +65,8 @@ struct venus_resources {
        unsigned int vcodec_pmdomains_num;
        const char **opp_pmdomain;
        unsigned int vcodec_num;
+       const char * const resets[VIDC_RESETS_NUM_MAX];
+       unsigned int resets_num;
        enum hfi_version hfi_version;
        u32 max_load;
        unsigned int vmem_id;
@@ -130,6 +133,7 @@ struct venus_core {
        struct device *pmdomains[VIDC_PMDOMAINS_NUM_MAX];
        struct device_link *opp_dl_venus;
        struct device *opp_pmdomain;
+       struct reset_control *resets[VIDC_RESETS_NUM_MAX];
        struct video_device *vdev_dec;
        struct video_device *vdev_enc;
        struct v4l2_device v4l2_dev;
index 95b4d40..794c2d6 100644 (file)
@@ -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);
        }