[Freedreno] [PATCH v2] drm/msm/dp: add opp_table corner voting support base on dp_ink_clk rate
khsieh at codeaurora.org
khsieh at codeaurora.org
Sat Oct 10 21:31:30 UTC 2020
On 2020-10-06 00:31, Rajendra Nayak wrote:
> On 10/4/2020 3:56 AM, Kuogee Hsieh wrote:
>> Set link rate by using OPP set rate api so that CX level will be set
>> accordingly based on the link rate.
>>
>> Changes in v2:
>> -- remove dev from dp_ctrl_put() parameters
>> -- address review comments
>
> This needs to go below '---' and should not be part of the
> change log.
>
>>
>> Signed-off-by: Kuogee Hsieh <khsieh at codeaurora.org>
>> ---
>> drivers/gpu/drm/msm/dp/dp_ctrl.c | 26 +++++++++++++++++
>> drivers/gpu/drm/msm/dp/dp_display.c | 2 +-
>> drivers/gpu/drm/msm/dp/dp_power.c | 44
>> ++++++++++++++++++++++++++---
>> drivers/gpu/drm/msm/dp/dp_power.h | 2 +-
>> 4 files changed, 68 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> b/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> index 2e3e1917351f..6eb9cdad1421 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> @@ -10,6 +10,7 @@
>> #include <linux/delay.h>
>> #include <linux/phy/phy.h>
>> #include <linux/phy/phy-dp.h>
>> +#include <linux/pm_opp.h>
>> #include <drm/drm_fixed.h>
>> #include <drm/drm_dp_helper.h>
>> #include <drm/drm_print.h>
>> @@ -76,6 +77,8 @@ struct dp_ctrl_private {
>> struct dp_parser *parser;
>> struct dp_catalog *catalog;
>> + struct opp_table *opp_table;
>> +
>> struct completion idle_comp;
>> struct completion video_comp;
>> };
>> @@ -1836,6 +1839,7 @@ struct dp_ctrl *dp_ctrl_get(struct device *dev,
>> struct dp_link *link,
>> struct dp_parser *parser)
>> {
>> struct dp_ctrl_private *ctrl;
>> + int ret;
>> if (!dev || !panel || !aux ||
>> !link || !catalog) {
>> @@ -1849,6 +1853,19 @@ struct dp_ctrl *dp_ctrl_get(struct device *dev,
>> struct dp_link *link,
>> return ERR_PTR(-ENOMEM);
>> }
>> + ctrl->opp_table = dev_pm_opp_set_clkname(dev, "ctrl_link");
>> + if (IS_ERR(ctrl->opp_table)) {
>> + dev_err(dev, "invalid DP OPP table in device tree\n");
>
> You do this regardless of an OPP table in DT, so for starters the error
> message is wrong. Secondly this can return you a -EPROBE_DEFER if the
> clock driver isn't ready yet.
> So the ideal thing to do here, is return a PTR_ERR(ctrl->opp_table)
>
>> + ctrl->opp_table = NULL;
>> + } else {
>> + /* OPP table is optional */
>> + ret = dev_pm_opp_of_add_table(dev);
>> + if (ret && ret != -ENODEV) {
>> + dev_pm_opp_put_clkname(ctrl->opp_table);
>> + ctrl->opp_table = NULL;
>> + }
>> + }
>> +
>> init_completion(&ctrl->idle_comp);
>> init_completion(&ctrl->video_comp);
>> @@ -1866,4 +1883,13 @@ struct dp_ctrl *dp_ctrl_get(struct device
>> *dev, struct dp_link *link,
>> void dp_ctrl_put(struct dp_ctrl *dp_ctrl)
>> {
>> + struct dp_ctrl_private *ctrl;
>> +
>> + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
>> +
>> + if (ctrl->opp_table) {
>> + dev_pm_opp_of_remove_table(ctrl->dev);
>> + dev_pm_opp_put_clkname(ctrl->opp_table);
>> + ctrl->opp_table = NULL;
>> + }
>> }
>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
>> b/drivers/gpu/drm/msm/dp/dp_display.c
>> index e175aa3fd3a9..269f83550b46 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>> @@ -698,7 +698,7 @@ static int dp_init_sub_modules(struct
>> dp_display_private *dp)
>> goto error;
>> }
>> - dp->power = dp_power_get(dp->parser);
>> + dp->power = dp_power_get(dev, dp->parser);
>> if (IS_ERR(dp->power)) {
>> rc = PTR_ERR(dp->power);
>> DRM_ERROR("failed to initialize power, rc = %d\n", rc);
>> diff --git a/drivers/gpu/drm/msm/dp/dp_power.c
>> b/drivers/gpu/drm/msm/dp/dp_power.c
>> index 17c1fc6a2d44..9c4ea00a5f2a 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_power.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_power.c
>> @@ -8,12 +8,14 @@
>> #include <linux/clk.h>
>> #include <linux/clk-provider.h>
>> #include <linux/regulator/consumer.h>
>> +#include <linux/pm_opp.h>
>> #include "dp_power.h"
>> #include "msm_drv.h"
>> struct dp_power_private {
>> struct dp_parser *parser;
>> struct platform_device *pdev;
>> + struct device *dev;
>> struct clk *link_clk_src;
>> struct clk *pixel_provider;
>> struct clk *link_provider;
>> @@ -148,18 +150,51 @@ static int dp_power_clk_deinit(struct
>> dp_power_private *power)
>> return 0;
>> }
>> +static int dp_power_clk_set_link_rate(struct dp_power_private
>> *power,
>> + struct dss_clk *clk_arry, int num_clk, int enable)
>> +{
>> + u32 rate;
>> + int i, rc = 0;
>> +
>> + for (i = 0; i < num_clk; i++) {
>> + if (clk_arry[i].clk) {
>> + if (clk_arry[i].type == DSS_CLK_PCLK) {
>> + if (enable)
>> + rate = clk_arry[i].rate;
>> + else
>> + rate = 0;
>> +
>> + rc = dev_pm_opp_set_rate(power->dev, rate);
>
> I am not sure how this is expected to work when you have multiple link
> clocks,
> since you can only associate one of them with the OPP table which ends
> up
> getting scaled when you do a dev_pm_opp_set_rate()
> Do you really have platforms which will have multiple link clocks?
this clk_arry[] contains two entries, dp_link_clk and dp_link_intf_clk.
only dp_link_clk with DSS_CLK_PCLK type, hence only dp_link_clk use
dev_pm_opp_set_rate()
to set link rate.
>
>> + if (rc)
>> + break;
>> + }
>> +
>> + }
>> + }
>> + return rc;
>> +}
>> +
>> static int dp_power_clk_set_rate(struct dp_power_private *power,
>> enum dp_pm_type module, bool enable)
>> {
>> int rc = 0;
>> struct dss_module_power *mp = &power->parser->mp[module];
>> - if (enable) {
>> - rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk);
>> + if (module == DP_CTRL_PM) {
>> + rc = dp_power_clk_set_link_rate(power, mp->clk_config, mp->num_clk,
>> enable);
>> if (rc) {
>> - DRM_ERROR("failed to set clks rate.\n");
>> + DRM_ERROR("failed to set link clks rate\n");
>> return rc;
>> }
>> + } else {
>> +
>
> extra blank line
>
>> + if (enable) {
>> + rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk);
>> + if (rc) {
>> + DRM_ERROR("failed to set clks rate\n");
>> + return rc;
>> + }
>> + }
>> }
>> rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
>> @@ -349,7 +384,7 @@ int dp_power_deinit(struct dp_power *dp_power)
>> return 0;
>> }
>> -struct dp_power *dp_power_get(struct dp_parser *parser)
>> +struct dp_power *dp_power_get(struct device *dev, struct dp_parser
>> *parser)
>> {
>> struct dp_power_private *power;
>> struct dp_power *dp_power;
>> @@ -365,6 +400,7 @@ struct dp_power *dp_power_get(struct dp_parser
>> *parser)
>> power->parser = parser;
>> power->pdev = parser->pdev;
>> + power->dev = dev;
>> dp_power = &power->dp_power;
>> diff --git a/drivers/gpu/drm/msm/dp/dp_power.h
>> b/drivers/gpu/drm/msm/dp/dp_power.h
>> index 76743d755833..7d0327bbc0d5 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_power.h
>> +++ b/drivers/gpu/drm/msm/dp/dp_power.h
>> @@ -102,6 +102,6 @@ void dp_power_client_deinit(struct dp_power
>> *power);
>> * methods to be called by the client to configure the power related
>> * modueles.
>> */
>> -struct dp_power *dp_power_get(struct dp_parser *parser);
>> +struct dp_power *dp_power_get(struct device *dev, struct dp_parser
>> *parser);
>> #endif /* _DP_POWER_H_ */
>>
>> base-commit: d1ea914925856d397b0b3241428f20b945e31434
>
> ??
More information about the Freedreno
mailing list