Message ID | 20230816145741.1472721-7-abel.vesa@linaro.org (mailing list archive) |
---|---|
State | Handled Elsewhere, archived |
Headers | show |
Series | PM: domains: Add control for switching back and forth to HW control | expand |
On 16.08.2023 16:57, Abel Vesa wrote: > From: Jagadeesh Kona <quic_jkona@quicinc.com> > > This change demonstrates the use of dev_pm_genpd_set_hwmode API from > video driver to switch the video mvs0 gdsc to SW/HW modes at runtime > based on requirement. > > This change adds a new boolean array member vcodec_pmdomains_hwctrl in > venus_resources structure to indicate if GDSC's have HW control support > or not. This data is used in vcodec_control_v4() to check if GDSC has > support to switch to HW control mode and then call dev_pm_genpd_set_hwmode > to switch the GDSC mode. > > Signed-off-by: Jagadeesh Kona <quic_jkona@quicinc.com> > Signed-off-by: Abel Vesa <abel.vesa@linaro.org> > --- [...] > static int vcodec_control_v4(struct venus_core *core, u32 coreid, bool enable) > { > - void __iomem *ctrl, *stat; > - u32 val; > - int ret; > - > - if (IS_V6(core)) { > - ctrl = core->wrapper_base + WRAPPER_CORE_POWER_CONTROL_V6; > - stat = core->wrapper_base + WRAPPER_CORE_POWER_STATUS_V6; > - } else 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 { > - ctrl = core->wrapper_base + WRAPPER_VCODEC1_MMCC_POWER_CONTROL; > - stat = core->wrapper_base + WRAPPER_VCODEC1_MMCC_POWER_STATUS; > - } > - > - if (enable) { > - writel(0, ctrl); > - > - ret = readl_poll_timeout(stat, val, val & BIT(1), 1, 100); > - if (ret) > - return ret; > - } else { > - writel(1, ctrl); This removal cries for better explanation. Has the venus hw been setting some registers that alter the GDSC's state? Or the hardware's expectations of the GDSC state? Konrad
On 16.08.2023 19:58, Konrad Dybcio wrote: > On 16.08.2023 16:57, Abel Vesa wrote: >> From: Jagadeesh Kona <quic_jkona@quicinc.com> >> >> This change demonstrates the use of dev_pm_genpd_set_hwmode API from >> video driver to switch the video mvs0 gdsc to SW/HW modes at runtime >> based on requirement. >> >> This change adds a new boolean array member vcodec_pmdomains_hwctrl in >> venus_resources structure to indicate if GDSC's have HW control support >> or not. This data is used in vcodec_control_v4() to check if GDSC has >> support to switch to HW control mode and then call dev_pm_genpd_set_hwmode >> to switch the GDSC mode. >> >> Signed-off-by: Jagadeesh Kona <quic_jkona@quicinc.com> >> Signed-off-by: Abel Vesa <abel.vesa@linaro.org> >> --- > [...] > >> static int vcodec_control_v4(struct venus_core *core, u32 coreid, bool enable) >> { >> - void __iomem *ctrl, *stat; >> - u32 val; >> - int ret; >> - >> - if (IS_V6(core)) { >> - ctrl = core->wrapper_base + WRAPPER_CORE_POWER_CONTROL_V6; >> - stat = core->wrapper_base + WRAPPER_CORE_POWER_STATUS_V6; >> - } else 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 { >> - ctrl = core->wrapper_base + WRAPPER_VCODEC1_MMCC_POWER_CONTROL; >> - stat = core->wrapper_base + WRAPPER_VCODEC1_MMCC_POWER_STATUS; >> - } >> - >> - if (enable) { >> - writel(0, ctrl); >> - >> - ret = readl_poll_timeout(stat, val, val & BIT(1), 1, 100); >> - if (ret) >> - return ret; >> - } else { >> - writel(1, ctrl); > This removal cries for better explanation. > > Has the venus hw been setting some registers that alter the GDSC's state? > Or the hardware's expectations of the GDSC state? Clearly can't read the commit message Acked-by: Konrad Dybcio <konrad.dybcio@linaro.org> Konrad
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 054b8e74ba4f..8145062ab6f7 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -706,6 +706,7 @@ static const struct venus_resources sdm845_res_v2 = { .vcodec1_clks = { "vcodec1_core", "vcodec1_bus" }, .vcodec_clks_num = 2, .vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" }, + .vcodec_pmdomains_hwctrl = { false, true, true }, .vcodec_pmdomains_num = 3, .opp_pmdomain = (const char *[]) { "cx", NULL }, .vcodec_num = 2, @@ -755,6 +756,7 @@ static const struct venus_resources sc7180_res = { .vcodec0_clks = { "vcodec0_core", "vcodec0_bus" }, .vcodec_clks_num = 2, .vcodec_pmdomains = { "venus", "vcodec0" }, + .vcodec_pmdomains_hwctrl = { false, true }, .vcodec_pmdomains_num = 2, .opp_pmdomain = (const char *[]) { "cx", NULL }, .vcodec_num = 1, @@ -812,6 +814,7 @@ static const struct venus_resources sm8250_res = { .vcodec0_clks = { "vcodec0_core" }, .vcodec_clks_num = 1, .vcodec_pmdomains = { "venus", "vcodec0" }, + .vcodec_pmdomains_hwctrl = { false, true }, .vcodec_pmdomains_num = 2, .opp_pmdomain = (const char *[]) { "mx", NULL }, .vcodec_num = 1, @@ -871,6 +874,7 @@ static const struct venus_resources sc7280_res = { .vcodec0_clks = {"vcodec_core", "vcodec_bus"}, .vcodec_clks_num = 2, .vcodec_pmdomains = { "venus", "vcodec0" }, + .vcodec_pmdomains_hwctrl = { false, true }, .vcodec_pmdomains_num = 2, .opp_pmdomain = (const char *[]) { "cx", NULL }, .vcodec_num = 1, diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 4a633261ece4..6d591ecad482 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -73,6 +73,7 @@ struct venus_resources { const char * const vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX]; unsigned int vcodec_clks_num; const char * const vcodec_pmdomains[VIDC_PMDOMAINS_NUM_MAX]; + bool vcodec_pmdomains_hwctrl[VIDC_PMDOMAINS_NUM_MAX]; unsigned int vcodec_pmdomains_num; const char **opp_pmdomain; unsigned int vcodec_num; diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c index 48c9084bb4db..c53eef23c793 100644 --- a/drivers/media/platform/qcom/venus/pm_helpers.c +++ b/drivers/media/platform/qcom/venus/pm_helpers.c @@ -408,35 +408,28 @@ static const struct venus_pm_ops pm_ops_v3 = { static int vcodec_control_v4(struct venus_core *core, u32 coreid, bool enable) { - void __iomem *ctrl, *stat; - u32 val; - int ret; - - if (IS_V6(core)) { - ctrl = core->wrapper_base + WRAPPER_CORE_POWER_CONTROL_V6; - stat = core->wrapper_base + WRAPPER_CORE_POWER_STATUS_V6; - } else 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 { - ctrl = core->wrapper_base + WRAPPER_VCODEC1_MMCC_POWER_CONTROL; - stat = core->wrapper_base + WRAPPER_VCODEC1_MMCC_POWER_STATUS; - } - - if (enable) { - writel(0, ctrl); - - ret = readl_poll_timeout(stat, val, val & BIT(1), 1, 100); - if (ret) - return ret; - } else { - writel(1, ctrl); + int i, ret = 0; + struct device *dev = core->dev; + const struct venus_resources *res = core->res; - ret = readl_poll_timeout(stat, val, !(val & BIT(1)), 1, 100); - if (ret) - return ret; + for (i = 0; i < res->vcodec_pmdomains_num; i++) { + if (res->vcodec_pmdomains_hwctrl[i]) { + + if (!core->pmdomains[i]) + return -ENODEV; + + /* + * enable( true ), switch the gdsc to SW mode + * enable( false), switch the gdsc to HW mode + */ + ret = dev_pm_genpd_set_hwmode(core->pmdomains[i], !enable); + if (ret) { + dev_err(dev, "Failed to switch power-domain:%d to %s mode\n", + i, enable ? "SW" : "HW"); + return ret; + } + } } - return 0; }