media: venus: pm_helpers: add compatibility for dev_pm_genpd_set_hwmode on V4

There are two ways to switch GDSC mode. One is to write the POWER_CONTROL
register and the other is to use dev_pm_genpd_set_hwmode(). However, they
rely on different clock driver flags. dev_pm_genpd_set_hwmode() depends on
the HW_CTRL_TRIGGER flag and POWER_CONTROL register depends on the HW_CTRL
flag.

By default, the dev_pm_genpd_set_hwmode() is used to switch the GDSC mode.
If it fails and dev_pm_genpd_set_hwmode() returns -EOPNOTSUPP, it means
that the clock driver uses the HW_CTRL flag. At this time, the GDSC mode
is switched to write the POWER_CONTROL register.

Clock driver is using HW_CTRL_TRIGGER flag with V6. So hwmode_dev is
always true on using V6 platform. Conversely, if hwmode_dev is false, this
platform must be not using V6. Therefore, replace IS_V6 in poweroff_coreid
with hwmode_dev. Also, with HW_CTRL_TRIGGER flag, the vcodec gdsc gets
enabled in SW mode by default. Therefore, before disabling the GDSC, GDSC
should be switched to SW mode so that GDSC gets enabled in SW mode in the
next enable.

Signed-off-by: Renjiang Han <quic_renjiang@quicinc.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
[bod: added media prefix]
Signed-off-by: Bryan O'Donoghue <bod@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
This commit is contained in:
Renjiang Han 2025-02-18 16:03:20 +05:30 committed by Hans Verkuil
parent b588898880
commit 14423fc3a4
2 changed files with 23 additions and 17 deletions

View File

@ -172,6 +172,7 @@ struct venus_format {
* @venus_ver: the venus firmware version
* @dump_core: a flag indicating that a core dump is required
* @ocs: OF changeset pointer
* @hwmode_dev: a flag indicating that HW_CTRL_TRIGGER is used in clock driver
*/
struct venus_core {
void __iomem *base;
@ -235,6 +236,7 @@ struct venus_core {
} venus_ver;
unsigned long dump_core;
struct of_changeset *ocs;
bool hwmode_dev;
};
struct vdec_controls {

View File

@ -412,9 +412,17 @@ static int vcodec_control_v4(struct venus_core *core, u32 coreid, bool enable)
u32 val;
int ret;
if (IS_V6(core))
return dev_pm_genpd_set_hwmode(core->pmdomains->pd_devs[coreid], !enable);
else if (coreid == VIDC_CORE_ID_1) {
ret = dev_pm_genpd_set_hwmode(core->pmdomains->pd_devs[coreid], !enable);
if (ret == -EOPNOTSUPP) {
core->hwmode_dev = false;
goto legacy;
}
core->hwmode_dev = true;
return ret;
legacy:
if (coreid == VIDC_CORE_ID_1) {
ctrl = core->wrapper_base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL;
stat = core->wrapper_base + WRAPPER_VCODEC0_MMCC_POWER_STATUS;
} else {
@ -450,7 +458,7 @@ static int poweroff_coreid(struct venus_core *core, unsigned int coreid_mask)
vcodec_clks_disable(core, core->vcodec0_clks);
if (!IS_V6(core)) {
if (!core->hwmode_dev) {
ret = vcodec_control_v4(core, VIDC_CORE_ID_1, false);
if (ret)
return ret;
@ -468,7 +476,7 @@ static int poweroff_coreid(struct venus_core *core, unsigned int coreid_mask)
vcodec_clks_disable(core, core->vcodec1_clks);
if (!IS_V6(core)) {
if (!core->hwmode_dev) {
ret = vcodec_control_v4(core, VIDC_CORE_ID_2, false);
if (ret)
return ret;
@ -491,11 +499,9 @@ static int poweron_coreid(struct venus_core *core, unsigned int coreid_mask)
if (ret < 0)
return ret;
if (!IS_V6(core)) {
ret = vcodec_control_v4(core, VIDC_CORE_ID_1, true);
if (ret)
return ret;
}
ret = vcodec_control_v4(core, VIDC_CORE_ID_1, true);
if (ret)
return ret;
ret = vcodec_clks_enable(core, core->vcodec0_clks);
if (ret)
@ -511,11 +517,9 @@ static int poweron_coreid(struct venus_core *core, unsigned int coreid_mask)
if (ret < 0)
return ret;
if (!IS_V6(core)) {
ret = vcodec_control_v4(core, VIDC_CORE_ID_2, true);
if (ret)
return ret;
}
ret = vcodec_control_v4(core, VIDC_CORE_ID_2, true);
if (ret)
return ret;
ret = vcodec_clks_enable(core, core->vcodec1_clks);
if (ret)
@ -811,7 +815,7 @@ static int vdec_power_v4(struct device *dev, int on)
else
vcodec_clks_disable(core, core->vcodec0_clks);
vcodec_control_v4(core, VIDC_CORE_ID_1, false);
ret = vcodec_control_v4(core, VIDC_CORE_ID_1, false);
return ret;
}
@ -856,7 +860,7 @@ static int venc_power_v4(struct device *dev, int on)
else
vcodec_clks_disable(core, core->vcodec1_clks);
vcodec_control_v4(core, VIDC_CORE_ID_2, false);
ret = vcodec_control_v4(core, VIDC_CORE_ID_2, false);
return ret;
}