Skip to content

Commit 9a538b8

Browse files
Rajendra Nayakmchehab
Rajendra Nayak
authored andcommitted
media: venus: core: Add support for opp tables/perf voting
Add support to add OPP tables and perf voting on the OPP powerdomain. This is needed so venus votes on the corresponding performance state for the OPP powerdomain along with setting the core clock rate. Signed-off-by: Rajendra Nayak <[email protected]> Reviewed-by: Matthias Kaehlcke <[email protected]> Reviewed-by: Bjorn Andersson <[email protected]> Signed-off-by: Stanimir Varbanov <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent 98cd831 commit 9a538b8

File tree

3 files changed

+92
-7
lines changed

3 files changed

+92
-7
lines changed

drivers/media/platform/qcom/venus/core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ static const struct venus_resources sdm845_res_v2 = {
528528
.vcodec_clks_num = 2,
529529
.vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" },
530530
.vcodec_pmdomains_num = 3,
531+
.opp_pmdomain = (const char *[]) { "cx", NULL },
531532
.vcodec_num = 2,
532533
.max_load = 3110400, /* 4096x2160@90 */
533534
.hfi_version = HFI_VERSION_4XX,
@@ -573,6 +574,7 @@ static const struct venus_resources sc7180_res = {
573574
.vcodec_clks_num = 2,
574575
.vcodec_pmdomains = { "venus", "vcodec0" },
575576
.vcodec_pmdomains_num = 2,
577+
.opp_pmdomain = (const char *[]) { "cx", NULL },
576578
.vcodec_num = 1,
577579
.hfi_version = HFI_VERSION_4XX,
578580
.vmem_id = VIDC_RESOURCE_NONE,

drivers/media/platform/qcom/venus/core.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ struct venus_resources {
6262
unsigned int vcodec_clks_num;
6363
const char * const vcodec_pmdomains[VIDC_PMDOMAINS_NUM_MAX];
6464
unsigned int vcodec_pmdomains_num;
65+
const char **opp_pmdomain;
6566
unsigned int vcodec_num;
6667
enum hfi_version hfi_version;
6768
u32 max_load;
@@ -145,8 +146,12 @@ struct venus_core {
145146
struct clk *vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX];
146147
struct icc_path *video_path;
147148
struct icc_path *cpucfg_path;
149+
struct opp_table *opp_table;
150+
bool has_opp_table;
148151
struct device_link *pd_dl_venus;
149152
struct device *pmdomains[VIDC_PMDOMAINS_NUM_MAX];
153+
struct device_link *opp_dl_venus;
154+
struct device *opp_pmdomain;
150155
struct video_device *vdev_dec;
151156
struct video_device *vdev_enc;
152157
struct v4l2_device v4l2_dev;

drivers/media/platform/qcom/venus/pm_helpers.c

Lines changed: 85 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/iopoll.h>
1010
#include <linux/kernel.h>
1111
#include <linux/pm_domain.h>
12+
#include <linux/pm_opp.h>
1213
#include <linux/pm_runtime.h>
1314
#include <linux/types.h>
1415
#include <media/v4l2-mem2mem.h>
@@ -66,10 +67,9 @@ static void core_clks_disable(struct venus_core *core)
6667

6768
static int core_clks_set_rate(struct venus_core *core, unsigned long freq)
6869
{
69-
struct clk *clk = core->clks[0];
7070
int ret;
7171

72-
ret = clk_set_rate(clk, freq);
72+
ret = dev_pm_opp_set_rate(core->dev, freq);
7373
if (ret)
7474
return ret;
7575

@@ -744,13 +744,16 @@ static int venc_power_v4(struct device *dev, int on)
744744

745745
static int vcodec_domains_get(struct device *dev)
746746
{
747+
int ret;
748+
struct opp_table *opp_table;
749+
struct device **opp_virt_dev;
747750
struct venus_core *core = dev_get_drvdata(dev);
748751
const struct venus_resources *res = core->res;
749752
struct device *pd;
750753
unsigned int i;
751754

752755
if (!res->vcodec_pmdomains_num)
753-
return -ENODEV;
756+
goto skip_pmdomains;
754757

755758
for (i = 0; i < res->vcodec_pmdomains_num; i++) {
756759
pd = dev_pm_domain_attach_by_name(dev,
@@ -767,7 +770,41 @@ static int vcodec_domains_get(struct device *dev)
767770
if (!core->pd_dl_venus)
768771
return -ENODEV;
769772

773+
skip_pmdomains:
774+
if (!core->has_opp_table)
775+
return 0;
776+
777+
/* Attach the power domain for setting performance state */
778+
opp_table = dev_pm_opp_attach_genpd(dev, res->opp_pmdomain, &opp_virt_dev);
779+
if (IS_ERR(opp_table)) {
780+
ret = PTR_ERR(opp_table);
781+
goto opp_attach_err;
782+
}
783+
784+
core->opp_pmdomain = *opp_virt_dev;
785+
core->opp_dl_venus = device_link_add(dev, core->opp_pmdomain,
786+
DL_FLAG_RPM_ACTIVE |
787+
DL_FLAG_PM_RUNTIME |
788+
DL_FLAG_STATELESS);
789+
if (!core->opp_dl_venus) {
790+
ret = -ENODEV;
791+
goto opp_dl_add_err;
792+
}
793+
770794
return 0;
795+
796+
opp_dl_add_err:
797+
dev_pm_domain_detach(core->opp_pmdomain, true);
798+
opp_attach_err:
799+
if (core->pd_dl_venus) {
800+
device_link_del(core->pd_dl_venus);
801+
for (i = 0; i < res->vcodec_pmdomains_num; i++) {
802+
if (IS_ERR_OR_NULL(core->pmdomains[i]))
803+
continue;
804+
dev_pm_domain_detach(core->pmdomains[i], true);
805+
}
806+
}
807+
return ret;
771808
}
772809

773810
static void vcodec_domains_put(struct device *dev)
@@ -777,7 +814,7 @@ static void vcodec_domains_put(struct device *dev)
777814
unsigned int i;
778815

779816
if (!res->vcodec_pmdomains_num)
780-
return;
817+
goto skip_pmdomains;
781818

782819
if (core->pd_dl_venus)
783820
device_link_del(core->pd_dl_venus);
@@ -787,6 +824,15 @@ static void vcodec_domains_put(struct device *dev)
787824
continue;
788825
dev_pm_domain_detach(core->pmdomains[i], true);
789826
}
827+
828+
skip_pmdomains:
829+
if (!core->has_opp_table)
830+
return;
831+
832+
if (core->opp_dl_venus)
833+
device_link_del(core->opp_dl_venus);
834+
835+
dev_pm_domain_detach(core->opp_pmdomain, true);
790836
}
791837

792838
static int core_get_v4(struct device *dev)
@@ -815,30 +861,62 @@ static int core_get_v4(struct device *dev)
815861
if (legacy_binding)
816862
return 0;
817863

864+
core->opp_table = dev_pm_opp_set_clkname(dev, "core");
865+
if (IS_ERR(core->opp_table))
866+
return PTR_ERR(core->opp_table);
867+
868+
if (core->res->opp_pmdomain) {
869+
ret = dev_pm_opp_of_add_table(dev);
870+
if (!ret) {
871+
core->has_opp_table = true;
872+
} else if (ret != -ENODEV) {
873+
dev_err(dev, "invalid OPP table in device tree\n");
874+
dev_pm_opp_put_clkname(core->opp_table);
875+
return ret;
876+
}
877+
}
878+
818879
ret = vcodec_domains_get(dev);
819-
if (ret)
880+
if (ret) {
881+
if (core->has_opp_table)
882+
dev_pm_opp_of_remove_table(dev);
883+
dev_pm_opp_put_clkname(core->opp_table);
820884
return ret;
885+
}
821886

822887
return 0;
823888
}
824889

825890
static void core_put_v4(struct device *dev)
826891
{
892+
struct venus_core *core = dev_get_drvdata(dev);
893+
827894
if (legacy_binding)
828895
return;
829896

830897
vcodec_domains_put(dev);
898+
899+
if (core->has_opp_table)
900+
dev_pm_opp_of_remove_table(dev);
901+
if (core->opp_table)
902+
dev_pm_opp_put_clkname(core->opp_table);
903+
831904
}
832905

833906
static int core_power_v4(struct device *dev, int on)
834907
{
835908
struct venus_core *core = dev_get_drvdata(dev);
836909
int ret = 0;
837910

838-
if (on == POWER_ON)
911+
if (on == POWER_ON) {
839912
ret = core_clks_enable(core);
840-
else
913+
} else {
914+
/* Drop the performance state vote */
915+
if (core->opp_pmdomain)
916+
dev_pm_opp_set_rate(dev, 0);
917+
841918
core_clks_disable(core);
919+
}
842920

843921
return ret;
844922
}

0 commit comments

Comments
 (0)