Attach power domains for vdec and venc cores and power them up if a vdec or venc session is started.
Signed-off-by: Erikas Bitovtas <[email protected]> --- drivers/media/platform/qcom/venus/pm_helpers.c | 121 ++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c index cc21a4762188..713812421c44 100644 --- a/drivers/media/platform/qcom/venus/pm_helpers.c +++ b/drivers/media/platform/qcom/venus/pm_helpers.c @@ -246,6 +246,94 @@ static int load_scale_bw(struct venus_core *core) return icc_set_bw(core->video_path, total_avg, total_peak); } +static int vcodec_domains_get_v1(struct venus_core *core, struct device *dev, + struct dev_pm_domain_list **pmdomains, + const char **pmdomain_names, + unsigned int pmdomains_num) +{ + int ret; + struct dev_pm_domain_attach_data vcodec_data = { + .pd_names = pmdomain_names, + .num_pd_names = pmdomains_num, + .pd_flags = PD_FLAG_NO_DEV_LINK, + }; + + if (!pmdomain_names) + return 0; + + ret = devm_pm_domain_attach_list(dev, &vcodec_data, pmdomains); + return ret; +} + +static int vdec_domains_attach(struct venus_core *core) +{ + struct device *dev = core->dev_dec; + const struct venus_resources *res = core->res; + + return vcodec_domains_get_v1(core, dev, &core->vcodec0_pmdomains, + res->vcodec0_pmdomains, + res->vcodec0_pmdomains_num); +} + +static int venc_domains_attach(struct venus_core *core) +{ + struct device *dev = core->dev_enc; + const struct venus_resources *res = core->res; + + return vcodec_domains_get_v1(core, dev, &core->vcodec1_pmdomains, + res->vcodec1_pmdomains, + res->vcodec1_pmdomains_num); +} + +static int vcodec_domains_enable_v1(struct venus_core *core, + struct dev_pm_domain_list *pmdomains, + unsigned int pmdomains_num) +{ + int i, ret; + + if (!pmdomains) + return 0; + + for (i = 0; i < pmdomains_num; i++) { + ret = pm_runtime_resume_and_get(pmdomains->pd_devs[i]); + if (ret) + goto err; + } + + return ret; + +err: + while (i--) + pm_runtime_put_sync(pmdomains->pd_devs[i]); + + return ret; +} + +static int vdec_domains_get(struct venus_core *core) +{ + const struct venus_resources *res = core->res; + + return vcodec_domains_enable_v1(core, core->vcodec0_pmdomains, + res->vcodec0_pmdomains_num); +} + +static int venc_domains_get(struct venus_core *core) +{ + const struct venus_resources *res = core->res; + + return vcodec_domains_enable_v1(core, core->vcodec1_pmdomains, + res->vcodec1_pmdomains_num); +} + +static void vcodec_domains_put_v1(struct dev_pm_domain_list *pmdomains, + unsigned int pmdomains_num) +{ + unsigned int i = pmdomains_num; + + while (i--) + pm_runtime_put_sync(pmdomains->pd_devs[i]); +} + static int load_scale_v1(struct venus_inst *inst) { struct venus_core *core = inst->core; @@ -331,6 +419,11 @@ static int core_power_v1(struct venus_core *core, int on) static int vdec_get_v1(struct device *dev) { struct venus_core *core = dev_get_drvdata(dev); + int ret; + + ret = vdec_domains_attach(core); + if (ret < 0) + return ret; return vcodec_clks_get(core, dev, core->vcodec0_clks, core->res->vcodec0_clks); @@ -339,8 +432,18 @@ static int vdec_get_v1(struct device *dev) static int vdec_power_v1(struct device *dev, int on) { struct venus_core *core = dev_get_drvdata(dev); + const struct venus_resources *res = core->res; int ret = 0; + if (on == POWER_ON) + ret = vdec_domains_get(core); + else + vcodec_domains_put_v1(core->vcodec0_pmdomains, + res->vcodec0_pmdomains_num); + + if (ret) + return ret; + if (on == POWER_ON) ret = vcodec_clks_enable(core, core->vcodec0_clks); else @@ -352,6 +455,11 @@ static int vdec_power_v1(struct device *dev, int on) static int venc_get_v1(struct device *dev) { struct venus_core *core = dev_get_drvdata(dev); + int ret; + + ret = venc_domains_attach(core); + if (ret < 0) + return ret; return vcodec_clks_get(core, dev, core->vcodec1_clks, core->res->vcodec1_clks); @@ -360,8 +468,17 @@ static int venc_get_v1(struct device *dev) static int venc_power_v1(struct device *dev, int on) { struct venus_core *core = dev_get_drvdata(dev); + const struct venus_resources *res = core->res; int ret = 0; + if (on == POWER_ON) + ret = venc_domains_get(core); + else + vcodec_domains_put_v1(core->vcodec1_pmdomains, + res->vcodec1_pmdomains_num); + if (ret) + return ret; + if (on == POWER_ON) ret = vcodec_clks_enable(core, core->vcodec1_clks); else @@ -905,7 +1022,7 @@ static int venc_power_v4(struct device *dev, int on) return ret; } -static int vcodec_domains_get(struct venus_core *core) +static int vcodec_domains_get_v4(struct venus_core *core) { int ret; struct device *dev = core->dev; @@ -1023,7 +1140,7 @@ static int core_get_v4(struct venus_core *core) if (ret) return ret; - ret = vcodec_domains_get(core); + ret = vcodec_domains_get_v4(core); if (ret) return ret; -- 2.53.0

