[PATCH v5 3/5] media: venus: core: Add support for opp tables/perf voting

2020-07-29 Thread Rajendra Nayak
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 
Reviewed-by: Matthias Kaehlcke 
Acked-by: Stanimir Varbanov 
---
 drivers/media/platform/qcom/venus/core.c   |  2 +
 drivers/media/platform/qcom/venus/core.h   |  5 ++
 drivers/media/platform/qcom/venus/pm_helpers.c | 92 --
 3 files changed, 92 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/qcom/venus/core.c 
b/drivers/media/platform/qcom/venus/core.c
index bfcaba3..a3e98a5 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -525,6 +525,7 @@ static const struct venus_resources sdm845_res_v2 = {
.vcodec_clks_num = 2,
.vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" },
.vcodec_pmdomains_num = 3,
+   .opp_pmdomain = (const char *[]) { "cx", NULL },
.vcodec_num = 2,
.max_load = 3110400,/* 4096x2160@90 */
.hfi_version = HFI_VERSION_4XX,
@@ -570,6 +571,7 @@ static const struct venus_resources sc7180_res = {
.vcodec_clks_num = 2,
.vcodec_pmdomains = { "venus", "vcodec0" },
.vcodec_pmdomains_num = 2,
+   .opp_pmdomain = (const char *[]) { "cx", NULL },
.vcodec_num = 1,
.hfi_version = HFI_VERSION_4XX,
.vmem_id = VIDC_RESOURCE_NONE,
diff --git a/drivers/media/platform/qcom/venus/core.h 
b/drivers/media/platform/qcom/venus/core.h
index 7118612..b0cc544 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -62,6 +62,7 @@ struct venus_resources {
unsigned int vcodec_clks_num;
const char * const vcodec_pmdomains[VIDC_PMDOMAINS_NUM_MAX];
unsigned int vcodec_pmdomains_num;
+   const char **opp_pmdomain;
unsigned int vcodec_num;
enum hfi_version hfi_version;
u32 max_load;
@@ -145,8 +146,12 @@ struct venus_core {
struct clk *vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX];
struct icc_path *video_path;
struct icc_path *cpucfg_path;
+   struct opp_table *opp_table;
+   bool has_opp_table;
struct device_link *pd_dl_venus;
struct device *pmdomains[VIDC_PMDOMAINS_NUM_MAX];
+   struct device_link *opp_dl_venus;
+   struct device *opp_pmdomain;
struct video_device *vdev_dec;
struct video_device *vdev_enc;
struct v4l2_device v4l2_dev;
diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c 
b/drivers/media/platform/qcom/venus/pm_helpers.c
index abf9315..0308d20 100644
--- a/drivers/media/platform/qcom/venus/pm_helpers.c
+++ b/drivers/media/platform/qcom/venus/pm_helpers.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -66,10 +67,9 @@ static void core_clks_disable(struct venus_core *core)
 
 static int core_clks_set_rate(struct venus_core *core, unsigned long freq)
 {
-   struct clk *clk = core->clks[0];
int ret;
 
-   ret = clk_set_rate(clk, freq);
+   ret = dev_pm_opp_set_rate(core->dev, freq);
if (ret)
return ret;
 
@@ -740,13 +740,16 @@ static int venc_power_v4(struct device *dev, int on)
 
 static int vcodec_domains_get(struct device *dev)
 {
+   int ret;
+   struct opp_table *opp_table;
+   struct device **opp_virt_dev;
struct venus_core *core = dev_get_drvdata(dev);
const struct venus_resources *res = core->res;
struct device *pd;
unsigned int i;
 
if (!res->vcodec_pmdomains_num)
-   return -ENODEV;
+   goto skip_pmdomains;
 
for (i = 0; i < res->vcodec_pmdomains_num; i++) {
pd = dev_pm_domain_attach_by_name(dev,
@@ -763,7 +766,41 @@ static int vcodec_domains_get(struct device *dev)
if (!core->pd_dl_venus)
return -ENODEV;
 
+skip_pmdomains:
+   if (!core->has_opp_table)
+   return 0;
+
+   /* Attach the power domain for setting performance state */
+   opp_table = dev_pm_opp_attach_genpd(dev, res->opp_pmdomain, 
&opp_virt_dev);
+   if (IS_ERR(opp_table)) {
+   ret = PTR_ERR(opp_table);
+   goto opp_attach_err;
+   }
+
+   core->opp_pmdomain = *opp_virt_dev;
+   core->opp_dl_venus = device_link_add(dev, core->opp_pmdomain,
+DL_FLAG_RPM_ACTIVE |
+DL_FLAG_PM_RUNTIME |
+DL_FLAG_STATELESS);
+   if (!core->opp_dl_venus) {
+   ret = -ENODEV;
+   goto opp_dl_add_err;
+   }
+
return 0;
+
+opp_dl_add_err:
+   dev_pm_domain_detach(core->opp_pmdomain, true);
+opp_attach_err:
+   if (core->pd_dl_venus) {
+   device_link_del(core->pd_dl_venus);
+   

Re: [PATCH v5 3/5] media: venus: core: Add support for opp tables/perf voting

2020-07-29 Thread Bjorn Andersson
On Wed 29 Jul 00:16 PDT 2020, Rajendra Nayak wrote:

> 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 
> Reviewed-by: Matthias Kaehlcke 
> Acked-by: Stanimir Varbanov 

Reviewed-by: Bjorn Andersson 

Regards,
Bjorn

> ---
>  drivers/media/platform/qcom/venus/core.c   |  2 +
>  drivers/media/platform/qcom/venus/core.h   |  5 ++
>  drivers/media/platform/qcom/venus/pm_helpers.c | 92 
> --
>  3 files changed, 92 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/media/platform/qcom/venus/core.c 
> b/drivers/media/platform/qcom/venus/core.c
> index bfcaba3..a3e98a5 100644
> --- a/drivers/media/platform/qcom/venus/core.c
> +++ b/drivers/media/platform/qcom/venus/core.c
> @@ -525,6 +525,7 @@ static const struct venus_resources sdm845_res_v2 = {
>   .vcodec_clks_num = 2,
>   .vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" },
>   .vcodec_pmdomains_num = 3,
> + .opp_pmdomain = (const char *[]) { "cx", NULL },
>   .vcodec_num = 2,
>   .max_load = 3110400,/* 4096x2160@90 */
>   .hfi_version = HFI_VERSION_4XX,
> @@ -570,6 +571,7 @@ static const struct venus_resources sc7180_res = {
>   .vcodec_clks_num = 2,
>   .vcodec_pmdomains = { "venus", "vcodec0" },
>   .vcodec_pmdomains_num = 2,
> + .opp_pmdomain = (const char *[]) { "cx", NULL },
>   .vcodec_num = 1,
>   .hfi_version = HFI_VERSION_4XX,
>   .vmem_id = VIDC_RESOURCE_NONE,
> diff --git a/drivers/media/platform/qcom/venus/core.h 
> b/drivers/media/platform/qcom/venus/core.h
> index 7118612..b0cc544 100644
> --- a/drivers/media/platform/qcom/venus/core.h
> +++ b/drivers/media/platform/qcom/venus/core.h
> @@ -62,6 +62,7 @@ struct venus_resources {
>   unsigned int vcodec_clks_num;
>   const char * const vcodec_pmdomains[VIDC_PMDOMAINS_NUM_MAX];
>   unsigned int vcodec_pmdomains_num;
> + const char **opp_pmdomain;
>   unsigned int vcodec_num;
>   enum hfi_version hfi_version;
>   u32 max_load;
> @@ -145,8 +146,12 @@ struct venus_core {
>   struct clk *vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX];
>   struct icc_path *video_path;
>   struct icc_path *cpucfg_path;
> + struct opp_table *opp_table;
> + bool has_opp_table;
>   struct device_link *pd_dl_venus;
>   struct device *pmdomains[VIDC_PMDOMAINS_NUM_MAX];
> + struct device_link *opp_dl_venus;
> + struct device *opp_pmdomain;
>   struct video_device *vdev_dec;
>   struct video_device *vdev_enc;
>   struct v4l2_device v4l2_dev;
> diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c 
> b/drivers/media/platform/qcom/venus/pm_helpers.c
> index abf9315..0308d20 100644
> --- a/drivers/media/platform/qcom/venus/pm_helpers.c
> +++ b/drivers/media/platform/qcom/venus/pm_helpers.c
> @@ -9,6 +9,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -66,10 +67,9 @@ static void core_clks_disable(struct venus_core *core)
>  
>  static int core_clks_set_rate(struct venus_core *core, unsigned long freq)
>  {
> - struct clk *clk = core->clks[0];
>   int ret;
>  
> - ret = clk_set_rate(clk, freq);
> + ret = dev_pm_opp_set_rate(core->dev, freq);
>   if (ret)
>   return ret;
>  
> @@ -740,13 +740,16 @@ static int venc_power_v4(struct device *dev, int on)
>  
>  static int vcodec_domains_get(struct device *dev)
>  {
> + int ret;
> + struct opp_table *opp_table;
> + struct device **opp_virt_dev;
>   struct venus_core *core = dev_get_drvdata(dev);
>   const struct venus_resources *res = core->res;
>   struct device *pd;
>   unsigned int i;
>  
>   if (!res->vcodec_pmdomains_num)
> - return -ENODEV;
> + goto skip_pmdomains;
>  
>   for (i = 0; i < res->vcodec_pmdomains_num; i++) {
>   pd = dev_pm_domain_attach_by_name(dev,
> @@ -763,7 +766,41 @@ static int vcodec_domains_get(struct device *dev)
>   if (!core->pd_dl_venus)
>   return -ENODEV;
>  
> +skip_pmdomains:
> + if (!core->has_opp_table)
> + return 0;
> +
> + /* Attach the power domain for setting performance state */
> + opp_table = dev_pm_opp_attach_genpd(dev, res->opp_pmdomain, 
> &opp_virt_dev);
> + if (IS_ERR(opp_table)) {
> + ret = PTR_ERR(opp_table);
> + goto opp_attach_err;
> + }
> +
> + core->opp_pmdomain = *opp_virt_dev;
> + core->opp_dl_venus = device_link_add(dev, core->opp_pmdomain,
> +  DL_FLAG_RPM_ACTIVE |
> +  DL_FLAG_PM_RUNTIME |
> +  DL_FLAG_STATELESS);
> + if (!core->opp_dl_venus) {
> + ret = -ENODEV;
> + goto opp_dl_add_err;
> +