[PATCH v5 6/8] media: qcom: venus: add power domain enable logic for Venus cores

From: Erikas Bitovtas

Date: Thu May 07 2026 - 04:43:18 EST


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 <xerikasxx@xxxxxxxxx>
---
drivers/media/platform/qcom/venus/pm_helpers.c | 149 ++++++++++++++++++++++++-
1 file changed, 145 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c
index f0269524ac70..5ed7cbef8149 100644
--- a/drivers/media/platform/qcom/venus/pm_helpers.c
+++ b/drivers/media/platform/qcom/venus/pm_helpers.c
@@ -297,10 +297,31 @@ static int load_scale_v1(struct venus_inst *inst)
return ret;
}

+static int vcodec_domains_get_v1(struct venus_core *core)
+{
+ struct device *dev = core->dev;
+ const struct venus_resources *res = core->res;
+ const struct dev_pm_domain_attach_data vcodec_data = {
+ .pd_names = res->vcodec_pmdomains,
+ .num_pd_names = res->vcodec_pmdomains_num,
+ .pd_flags = PD_FLAG_NO_DEV_LINK,
+ };
+
+ if (!res->vcodec_pmdomains)
+ return 0;
+
+ return dev_pm_domain_attach_list(dev, &vcodec_data,
+ &core->pmdomains);
+}
+
static int core_get_v1(struct venus_core *core)
{
int ret;

+ ret = vcodec_domains_get_v1(core);
+ if (ret < 0)
+ return ret;
+
ret = core_clks_get(core);
if (ret)
return ret;
@@ -319,12 +340,128 @@ static void core_put_v1(struct venus_core *core)
static int core_power_v1(struct venus_core *core, int on)
{
int ret = 0;
+ struct device *pd_dev = core->res->vcodec_pmdomains ?
+ core->pmdomains->pd_devs[0] : NULL;

- if (on == POWER_ON)
+ if (on == POWER_ON) {
+ if (pd_dev) {
+ ret = pm_runtime_resume_and_get(pd_dev);
+ if (ret)
+ return ret;
+ }
ret = core_clks_enable(core);
- else
+ if (ret) {
+ pm_runtime_put_sync(pd_dev);
+ return ret;
+ }
+ } else {
+ if (pd_dev)
+ pm_runtime_put_sync(pd_dev);
core_clks_disable(core);
+ }
+
+ return 0;
+}
+
+static int vcodec_domains_enable(struct venus_core *core)
+{
+ const struct venus_resources *res = core->res;
+ struct device *pd_dev;
+ int i = 1, ret;
+
+ if (!res->vcodec_pmdomains)
+ return 0;
+
+ for (; i < res->vcodec_pmdomains_num; i++) {
+ pd_dev = core->pmdomains->pd_devs[i];
+ ret = pm_runtime_resume_and_get(pd_dev);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+err:
+ while (i-- > 1)
+ pm_runtime_put_sync(core->pmdomains->pd_devs[i]);
+ return ret;
+}
+
+static void vcodec_domains_disable(struct venus_core *core)
+{
+ const struct venus_resources *res = core->res;
+ struct device *pd_dev;
+ int i = 1;
+
+ if (!res->vcodec_pmdomains)
+ return;
+
+ for (; i < res->vcodec_pmdomains_num; i++) {
+ pd_dev = core->pmdomains->pd_devs[i];
+ pm_runtime_put_sync(pd_dev);
+ }
+}
+
+static int vdec_get_v1(struct device *dev)
+{
+ struct venus_core *core = dev_get_drvdata(dev);
+
+ return vcodec_clks_get(core, core->dev, core->vcodec0_clks,
+ core->res->vcodec0_clks);
+}
+
+static int vdec_power_v1(struct device *dev, int on)
+{
+ struct venus_core *core = dev_get_drvdata(dev);
+ int ret;
+
+ if (on == POWER_ON) {
+ ret = vcodec_domains_enable(core);
+ if (ret)
+ return ret;
+
+ ret = vcodec_clks_enable(core, core->vcodec0_clks);
+ if (ret)
+ goto err;
+ } else {
+ vcodec_domains_disable(core);
+ vcodec_clks_disable(core, core->vcodec0_clks);
+ }
+
+ return 0;
+err:
+ vcodec_domains_disable(core);
+ return ret;
+}

+static int venc_get_v1(struct device *dev)
+{
+ struct venus_core *core = dev_get_drvdata(dev);
+
+ return vcodec_clks_get(core, core->dev, core->vcodec1_clks,
+ core->res->vcodec1_clks);
+}
+
+static int venc_power_v1(struct device *dev, int on)
+{
+ struct venus_core *core = dev_get_drvdata(dev);
+ int ret;
+
+ if (on == POWER_ON) {
+ ret = vcodec_domains_enable(core);
+ if (ret)
+ return ret;
+
+ ret = vcodec_clks_enable(core, core->vcodec1_clks);
+ if (ret)
+ goto err;
+ } else {
+ vcodec_domains_disable(core);
+ vcodec_clks_disable(core, core->vcodec1_clks);
+ }
+
+ return 0;
+err:
+ vcodec_domains_disable(core);
return ret;
}

@@ -332,6 +469,10 @@ static const struct venus_pm_ops pm_ops_v1 = {
.core_get = core_get_v1,
.core_put = core_put_v1,
.core_power = core_power_v1,
+ .vdec_get = vdec_get_v1,
+ .vdec_power = vdec_power_v1,
+ .venc_get = venc_get_v1,
+ .venc_power = venc_power_v1,
.load_scale = load_scale_v1,
};

@@ -875,7 +1016,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;
@@ -993,7 +1134,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.54.0