These patches add DVFS support for DPU and DSI. Where posted earlier as part of a series with multiple different drivers [1] I have split them into specific driver changes in order to avoid confusion on dependencies. Also added the corresponding device tree changes for sdm845 and sc7180 platforms.
These patches have no other dependency and will need to be merged in via the MSM DRM tree.
DT patches will need to land via the msm tree.
[1] https://lkml.org/lkml/2020/6/15/535
Rajendra Nayak (4): drm/msm/dpu: Use OPP API to set clk/perf state drm/msm: dsi: Use OPP API to set clk/perf state arm64: dts: sdm845: Add DSI and MDP OPP tables and power-domains arm64: dts: sc7180: Add DSI and MDP OPP tables and power-domains
arch/arm64/boot/dts/qcom/sc7180.dtsi | 49 ++++++++++++++++++++++ arch/arm64/boot/dts/qcom/sdm845.dtsi | 59 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 3 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 26 +++++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 ++ drivers/gpu/drm/msm/dsi/dsi.h | 2 + drivers/gpu/drm/msm/dsi/dsi_cfg.c | 4 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 58 ++++++++++++++++++++++++++ 8 files changed, 201 insertions(+), 4 deletions(-)
On some qualcomm platforms DPU needs to express a performance state requirement on a power domain depending on the clock rates. Use OPP table from DT to register with OPP framework and use dev_pm_opp_set_rate() to set the clk/perf state.
Signed-off-by: Rajendra Nayak rnayak@codeaurora.org Reviewed-by: Rob Clark robdclark@chromium.org Reviewed-by: Matthias Kaehlcke mka@chromium.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 3 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 26 +++++++++++++++++++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 ++++ 3 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 7c230f7..b36919d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -7,6 +7,7 @@ #include <linux/debugfs.h> #include <linux/errno.h> #include <linux/mutex.h> +#include <linux/pm_opp.h> #include <linux/sort.h> #include <linux/clk.h> #include <linux/bitmap.h> @@ -218,7 +219,7 @@ static int _dpu_core_perf_set_core_clk_rate(struct dpu_kms *kms, u64 rate) rate = core_clk->max_rate;
core_clk->rate = rate; - return msm_dss_clk_set_rate(core_clk, 1); + return dev_pm_opp_set_rate(&kms->pdev->dev, core_clk->rate); }
static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index b8615d4..0bc8ec4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -10,6 +10,7 @@ #include <linux/debugfs.h> #include <linux/dma-buf.h> #include <linux/of_irq.h> +#include <linux/pm_opp.h>
#include <drm/drm_crtc.h> #include <drm/drm_file.h> @@ -1025,11 +1026,23 @@ static int dpu_bind(struct device *dev, struct device *master, void *data) if (!dpu_kms) return -ENOMEM;
+ dpu_kms->opp_table = dev_pm_opp_set_clkname(dev, "core"); + if (IS_ERR(dpu_kms->opp_table)) + return PTR_ERR(dpu_kms->opp_table); + /* OPP table is optional */ + ret = dev_pm_opp_of_add_table(dev); + if (!ret) { + dpu_kms->has_opp_table = true; + } else if (ret != -ENODEV) { + dev_err(dev, "invalid OPP table in device tree\n"); + return ret; + } + mp = &dpu_kms->mp; ret = msm_dss_parse_clock(pdev, mp); if (ret) { DPU_ERROR("failed to parse clocks, ret=%d\n", ret); - return ret; + goto err; }
platform_set_drvdata(pdev, dpu_kms); @@ -1043,6 +1056,11 @@ static int dpu_bind(struct device *dev, struct device *master, void *data)
priv->kms = &dpu_kms->base; return ret; +err: + if (dpu_kms->has_opp_table) + dev_pm_opp_of_remove_table(dev); + dev_pm_opp_put_clkname(dpu_kms->opp_table); + return ret; }
static void dpu_unbind(struct device *dev, struct device *master, void *data) @@ -1057,6 +1075,10 @@ static void dpu_unbind(struct device *dev, struct device *master, void *data)
if (dpu_kms->rpm_enabled) pm_runtime_disable(&pdev->dev); + + if (dpu_kms->has_opp_table) + dev_pm_opp_of_remove_table(dev); + dev_pm_opp_put_clkname(dpu_kms->opp_table); }
static const struct component_ops dpu_ops = { @@ -1082,6 +1104,8 @@ static int __maybe_unused dpu_runtime_suspend(struct device *dev) struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); struct dss_module_power *mp = &dpu_kms->mp;
+ /* Drop the performance state vote */ + dev_pm_opp_set_rate(dev, 0); rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false); if (rc) DPU_ERROR("clock disable failed rc:%d\n", rc); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index a3b122b..7400cd7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -128,6 +128,10 @@ struct dpu_kms {
struct platform_device *pdev; bool rpm_enabled; + + struct opp_table *opp_table; + bool has_opp_table; + struct dss_module_power mp;
/* reference count bandwidth requests, so we know when we can
On SDM845 DSI needs to express a perforamnce state requirement on a power domain depending on the clock rates. Use OPP table from DT to register with OPP framework and use dev_pm_opp_set_rate() to set the clk/perf state.
Signed-off-by: Rajendra Nayak rnayak@codeaurora.org --- drivers/gpu/drm/msm/dsi/dsi.h | 2 ++ drivers/gpu/drm/msm/dsi/dsi_cfg.c | 4 +-- drivers/gpu/drm/msm/dsi/dsi_host.c | 58 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 4de771d..ba7583c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -180,10 +180,12 @@ int msm_dsi_runtime_suspend(struct device *dev); int msm_dsi_runtime_resume(struct device *dev); int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host); int dsi_link_clk_set_rate_v2(struct msm_dsi_host *msm_host); +int dsi_link_clk_set_rate_6g_v2(struct msm_dsi_host *msm_host); int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host); int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host); void dsi_link_clk_disable_6g(struct msm_dsi_host *msm_host); void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host); +void dsi_link_clk_disable_6g_v2(struct msm_dsi_host *msm_host); int dsi_tx_buf_alloc_6g(struct msm_dsi_host *msm_host, int size); int dsi_tx_buf_alloc_v2(struct msm_dsi_host *msm_host, int size); void *dsi_tx_buf_get_6g(struct msm_dsi_host *msm_host); diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index 813d69d..773c4fe 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -210,9 +210,9 @@ static const struct msm_dsi_host_cfg_ops msm_dsi_6g_host_ops = { };
static const struct msm_dsi_host_cfg_ops msm_dsi_6g_v2_host_ops = { - .link_clk_set_rate = dsi_link_clk_set_rate_6g, + .link_clk_set_rate = dsi_link_clk_set_rate_6g_v2, .link_clk_enable = dsi_link_clk_enable_6g, - .link_clk_disable = dsi_link_clk_disable_6g, + .link_clk_disable = dsi_link_clk_disable_6g_v2, .clk_init_ver = dsi_clk_init_6g_v2, .tx_buf_alloc = dsi_tx_buf_alloc_6g, .tx_buf_get = dsi_tx_buf_get_6g, diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 11ae5b8..890531c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -14,6 +14,7 @@ #include <linux/of_graph.h> #include <linux/of_irq.h> #include <linux/pinctrl/consumer.h> +#include <linux/pm_opp.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/spinlock.h> @@ -111,6 +112,9 @@ struct msm_dsi_host { struct clk *pixel_clk_src; struct clk *byte_intf_clk;
+ struct opp_table *opp_table; + bool has_opp_table; + u32 byte_clk_rate; u32 pixel_clk_rate; u32 esc_clk_rate; @@ -537,6 +541,38 @@ int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host) return 0; }
+int dsi_link_clk_set_rate_6g_v2(struct msm_dsi_host *msm_host) +{ + int ret; + struct device *dev = &msm_host->pdev->dev; + + DBG("Set clk rates: pclk=%d, byteclk=%d", + msm_host->mode->clock, msm_host->byte_clk_rate); + + ret = dev_pm_opp_set_rate(dev, msm_host->byte_clk_rate); + if (ret) { + pr_err("%s: dev_pm_opp_set_rate failed %d\n", __func__, ret); + return ret; + } + + ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate); + if (ret) { + pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret); + return ret; + } + + if (msm_host->byte_intf_clk) { + ret = clk_set_rate(msm_host->byte_intf_clk, + msm_host->byte_clk_rate / 2); + if (ret) { + pr_err("%s: Failed to set rate byte intf clk, %d\n", + __func__, ret); + return ret; + } + } + + return 0; +}
int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host) { @@ -665,6 +701,13 @@ void dsi_link_clk_disable_6g(struct msm_dsi_host *msm_host) clk_disable_unprepare(msm_host->byte_clk); }
+void dsi_link_clk_disable_6g_v2(struct msm_dsi_host *msm_host) +{ + /* Drop the performance state vote */ + dev_pm_opp_set_rate(&msm_host->pdev->dev, 0); + dsi_link_clk_disable_6g(msm_host); +} + void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host) { clk_disable_unprepare(msm_host->pixel_clk); @@ -1879,6 +1922,18 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) goto fail; }
+ msm_host->opp_table = dev_pm_opp_set_clkname(&pdev->dev, "byte"); + if (IS_ERR(msm_host->opp_table)) + return PTR_ERR(msm_host->opp_table); + /* OPP table is optional */ + ret = dev_pm_opp_of_add_table(&pdev->dev); + if (!ret) { + msm_host->has_opp_table = true; + } else if (ret != -ENODEV) { + dev_err(&pdev->dev, "invalid OPP table in device tree\n"); + return ret; + } + init_completion(&msm_host->dma_comp); init_completion(&msm_host->video_comp); mutex_init(&msm_host->dev_mutex); @@ -1914,6 +1969,9 @@ void msm_dsi_host_destroy(struct mipi_dsi_host *host) mutex_destroy(&msm_host->cmd_mutex); mutex_destroy(&msm_host->dev_mutex);
+ if (msm_host->has_opp_table) + dev_pm_opp_of_remove_table(&msm_host->pdev->dev); + dev_pm_opp_put_clkname(msm_host->opp_table); pm_runtime_disable(&msm_host->pdev->dev); }
On Tue, Jun 30, 2020 at 05:26:14PM +0530, Rajendra Nayak wrote:
On SDM845 DSI needs to express a perforamnce state
nit: performance
requirement on a power domain depending on the clock rates. Use OPP table from DT to register with OPP framework and use dev_pm_opp_set_rate() to set the clk/perf state.
Signed-off-by: Rajendra Nayak rnayak@codeaurora.org
drivers/gpu/drm/msm/dsi/dsi.h | 2 ++ drivers/gpu/drm/msm/dsi/dsi_cfg.c | 4 +-- drivers/gpu/drm/msm/dsi/dsi_host.c | 58 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 4de771d..ba7583c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -180,10 +180,12 @@ int msm_dsi_runtime_suspend(struct device *dev); int msm_dsi_runtime_resume(struct device *dev); int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host); int dsi_link_clk_set_rate_v2(struct msm_dsi_host *msm_host); +int dsi_link_clk_set_rate_6g_v2(struct msm_dsi_host *msm_host); int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host); int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host); void dsi_link_clk_disable_6g(struct msm_dsi_host *msm_host); void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host); +void dsi_link_clk_disable_6g_v2(struct msm_dsi_host *msm_host); int dsi_tx_buf_alloc_6g(struct msm_dsi_host *msm_host, int size); int dsi_tx_buf_alloc_v2(struct msm_dsi_host *msm_host, int size); void *dsi_tx_buf_get_6g(struct msm_dsi_host *msm_host); diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index 813d69d..773c4fe 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -210,9 +210,9 @@ static const struct msm_dsi_host_cfg_ops msm_dsi_6g_host_ops = { };
static const struct msm_dsi_host_cfg_ops msm_dsi_6g_v2_host_ops = {
- .link_clk_set_rate = dsi_link_clk_set_rate_6g,
- .link_clk_set_rate = dsi_link_clk_set_rate_6g_v2, .link_clk_enable = dsi_link_clk_enable_6g,
- .link_clk_disable = dsi_link_clk_disable_6g,
- .link_clk_disable = dsi_link_clk_disable_6g_v2, .clk_init_ver = dsi_clk_init_6g_v2, .tx_buf_alloc = dsi_tx_buf_alloc_6g, .tx_buf_get = dsi_tx_buf_get_6g,
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 11ae5b8..890531c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -14,6 +14,7 @@ #include <linux/of_graph.h> #include <linux/of_irq.h> #include <linux/pinctrl/consumer.h> +#include <linux/pm_opp.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/spinlock.h> @@ -111,6 +112,9 @@ struct msm_dsi_host { struct clk *pixel_clk_src; struct clk *byte_intf_clk;
- struct opp_table *opp_table;
- bool has_opp_table;
- u32 byte_clk_rate; u32 pixel_clk_rate; u32 esc_clk_rate;
@@ -537,6 +541,38 @@ int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host) return 0; }
+int dsi_link_clk_set_rate_6g_v2(struct msm_dsi_host *msm_host) +{
- int ret;
- struct device *dev = &msm_host->pdev->dev;
- DBG("Set clk rates: pclk=%d, byteclk=%d",
msm_host->mode->clock, msm_host->byte_clk_rate);
- ret = dev_pm_opp_set_rate(dev, msm_host->byte_clk_rate);
- if (ret) {
pr_err("%s: dev_pm_opp_set_rate failed %d\n", __func__, ret);
return ret;
- }
- ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate);
- if (ret) {
pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret);
return ret;
- }
- if (msm_host->byte_intf_clk) {
ret = clk_set_rate(msm_host->byte_intf_clk,
msm_host->byte_clk_rate / 2);
if (ret) {
pr_err("%s: Failed to set rate byte intf clk, %d\n",
__func__, ret);
return ret;
}
- }
- return 0;
+}
xThis function is essentially the same as dsi_link_clk_set_rate_6g(), except for the use of dev_pm_opp_set_rate() instead of clk_set_rate().
IIUC dev_pm_opp_set_rate() just calls clk_set_rate() if the device has no OPP table. If that's correct you could just call dev_pm_opp_set_rate() in dsi_link_clk_set_rate_6g().
/* * For IO devices which require an OPP on some platforms/SoCs * while just needing to scale the clock on some others * we look for empty OPP tables with just a clock handle and * scale only the clk. This makes dev_pm_opp_set_rate() * equivalent to a clk_set_rate() */ if (!_get_opp_count(opp_table)) { ret = _generic_set_opp_clk_only(dev, clk, freq); goto put_opp_table; }
https://elixir.bootlin.com/linux/v5.7.6/source/drivers/opp/core.c#L855
int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host) { @@ -665,6 +701,13 @@ void dsi_link_clk_disable_6g(struct msm_dsi_host *msm_host) clk_disable_unprepare(msm_host->byte_clk); }
+void dsi_link_clk_disable_6g_v2(struct msm_dsi_host *msm_host) +{
- /* Drop the performance state vote */
- dev_pm_opp_set_rate(&msm_host->pdev->dev, 0);
Couldn't you just do this in dsi_link_clk_disable_6g() ?
- dsi_link_clk_disable_6g(msm_host);
+}
On 7/1/2020 9:57 PM, Matthias Kaehlcke wrote:
On Tue, Jun 30, 2020 at 05:26:14PM +0530, Rajendra Nayak wrote:
On SDM845 DSI needs to express a perforamnce state
nit: performance
requirement on a power domain depending on the clock rates. Use OPP table from DT to register with OPP framework and use dev_pm_opp_set_rate() to set the clk/perf state.
Signed-off-by: Rajendra Nayak rnayak@codeaurora.org
drivers/gpu/drm/msm/dsi/dsi.h | 2 ++ drivers/gpu/drm/msm/dsi/dsi_cfg.c | 4 +-- drivers/gpu/drm/msm/dsi/dsi_host.c | 58 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 4de771d..ba7583c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -180,10 +180,12 @@ int msm_dsi_runtime_suspend(struct device *dev); int msm_dsi_runtime_resume(struct device *dev); int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host); int dsi_link_clk_set_rate_v2(struct msm_dsi_host *msm_host); +int dsi_link_clk_set_rate_6g_v2(struct msm_dsi_host *msm_host); int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host); int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host); void dsi_link_clk_disable_6g(struct msm_dsi_host *msm_host); void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host); +void dsi_link_clk_disable_6g_v2(struct msm_dsi_host *msm_host); int dsi_tx_buf_alloc_6g(struct msm_dsi_host *msm_host, int size); int dsi_tx_buf_alloc_v2(struct msm_dsi_host *msm_host, int size); void *dsi_tx_buf_get_6g(struct msm_dsi_host *msm_host); diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index 813d69d..773c4fe 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -210,9 +210,9 @@ static const struct msm_dsi_host_cfg_ops msm_dsi_6g_host_ops = { };
static const struct msm_dsi_host_cfg_ops msm_dsi_6g_v2_host_ops = {
- .link_clk_set_rate = dsi_link_clk_set_rate_6g,
- .link_clk_set_rate = dsi_link_clk_set_rate_6g_v2, .link_clk_enable = dsi_link_clk_enable_6g,
- .link_clk_disable = dsi_link_clk_disable_6g,
- .link_clk_disable = dsi_link_clk_disable_6g_v2, .clk_init_ver = dsi_clk_init_6g_v2, .tx_buf_alloc = dsi_tx_buf_alloc_6g, .tx_buf_get = dsi_tx_buf_get_6g,
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 11ae5b8..890531c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -14,6 +14,7 @@ #include <linux/of_graph.h> #include <linux/of_irq.h> #include <linux/pinctrl/consumer.h> +#include <linux/pm_opp.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/spinlock.h> @@ -111,6 +112,9 @@ struct msm_dsi_host { struct clk *pixel_clk_src; struct clk *byte_intf_clk;
- struct opp_table *opp_table;
- bool has_opp_table;
- u32 byte_clk_rate; u32 pixel_clk_rate; u32 esc_clk_rate;
@@ -537,6 +541,38 @@ int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host) return 0; }
+int dsi_link_clk_set_rate_6g_v2(struct msm_dsi_host *msm_host) +{
- int ret;
- struct device *dev = &msm_host->pdev->dev;
- DBG("Set clk rates: pclk=%d, byteclk=%d",
msm_host->mode->clock, msm_host->byte_clk_rate);
- ret = dev_pm_opp_set_rate(dev, msm_host->byte_clk_rate);
- if (ret) {
pr_err("%s: dev_pm_opp_set_rate failed %d\n", __func__, ret);
return ret;
- }
- ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate);
- if (ret) {
pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret);
return ret;
- }
- if (msm_host->byte_intf_clk) {
ret = clk_set_rate(msm_host->byte_intf_clk,
msm_host->byte_clk_rate / 2);
if (ret) {
pr_err("%s: Failed to set rate byte intf clk, %d\n",
__func__, ret);
return ret;
}
- }
- return 0;
+}
xThis function is essentially the same as dsi_link_clk_set_rate_6g(), except for the use of dev_pm_opp_set_rate() instead of clk_set_rate().
IIUC dev_pm_opp_set_rate() just calls clk_set_rate() if the device has no OPP table. If that's correct you could just call dev_pm_opp_set_rate() in dsi_link_clk_set_rate_6g().
/* * For IO devices which require an OPP on some platforms/SoCs * while just needing to scale the clock on some others * we look for empty OPP tables with just a clock handle and * scale only the clk. This makes dev_pm_opp_set_rate()
- equivalent to a clk_set_rate()
*/ if (!_get_opp_count(opp_table)) { ret = _generic_set_opp_clk_only(dev, clk, freq); goto put_opp_table; }
ah, thats right, I think I had this code from before that support got added to dev_pm_opp_set_rate() and I just did not update this driver to make use of it. Thanks for catching it, I will fix it up and repost soon.
https://elixir.bootlin.com/linux/v5.7.6/source/drivers/opp/core.c#L855
int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host) { @@ -665,6 +701,13 @@ void dsi_link_clk_disable_6g(struct msm_dsi_host *msm_host) clk_disable_unprepare(msm_host->byte_clk); }
+void dsi_link_clk_disable_6g_v2(struct msm_dsi_host *msm_host) +{
- /* Drop the performance state vote */
- dev_pm_opp_set_rate(&msm_host->pdev->dev, 0);
Couldn't you just do this in dsi_link_clk_disable_6g() ?
yes, looks like I can, I'll get rid of both of these additional functions.
thanks, Rajendra
Add the OPP tables for DSI and MDP based on the perf state/clk requirements, and add the power-domains property to specify the scalable power domain.
Signed-off-by: Rajendra Nayak rnayak@codeaurora.org --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 8eb5a31..b6afeb2 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -3296,6 +3296,35 @@ #power-domain-cells = <1>; };
+ dsi_opp_table: dsi-opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmhpd_opp_min_svs>; + }; + + opp-180000000 { + opp-hz = /bits/ 64 <180000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-275000000 { + opp-hz = /bits/ 64 <275000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-328580000 { + opp-hz = /bits/ 64 <328580000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-358000000 { + opp-hz = /bits/ 64 <358000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + mdss: mdss@ae00000 { compatible = "qcom,sdm845-mdss"; reg = <0 0x0ae00000 0 0x1000>; @@ -3340,6 +3369,8 @@ <&dispcc DISP_CC_MDSS_VSYNC_CLK>; assigned-clock-rates = <300000000>, <19200000>; + operating-points-v2 = <&mdp_opp_table>; + power-domains = <&rpmhpd SDM845_CX>;
interrupt-parent = <&mdss>; interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; @@ -3364,6 +3395,30 @@ }; }; }; + + mdp_opp_table: mdp-opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmhpd_opp_min_svs>; + }; + + opp-171428571 { + opp-hz = /bits/ 64 <171428571>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-344000000 { + opp-hz = /bits/ 64 <344000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-430000000 { + opp-hz = /bits/ 64 <430000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; };
dsi0: dsi@ae94000 { @@ -3386,6 +3441,8 @@ "core", "iface", "bus"; + operating-points-v2 = <&dsi_opp_table>; + power-domains = <&rpmhpd SDM845_CX>;
phys = <&dsi0_phy>; phy-names = "dsi"; @@ -3450,6 +3507,8 @@ "core", "iface", "bus"; + operating-points-v2 = <&dsi_opp_table>; + power-domains = <&rpmhpd SDM845_CX>;
phys = <&dsi1_phy>; phy-names = "dsi";
On Tue, Jun 30, 2020 at 05:26:15PM +0530, Rajendra Nayak wrote:
Add the OPP tables for DSI and MDP based on the perf state/clk requirements, and add the power-domains property to specify the scalable power domain.
Signed-off-by: Rajendra Nayak rnayak@codeaurora.org
arch/arm64/boot/dts/qcom/sdm845.dtsi | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 8eb5a31..b6afeb2 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -3296,6 +3296,35 @@ #power-domain-cells = <1>; };
dsi_opp_table: dsi-opp-table {
compatible = "operating-points-v2";
opp-19200000 {
opp-hz = /bits/ 64 <19200000>;
required-opps = <&rpmhpd_opp_min_svs>;
};
opp-180000000 {
opp-hz = /bits/ 64 <180000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
opp-275000000 {
opp-hz = /bits/ 64 <275000000>;
required-opps = <&rpmhpd_opp_svs>;
};
opp-328580000 {
opp-hz = /bits/ 64 <328580000>;
required-opps = <&rpmhpd_opp_svs_l1>;
};
opp-358000000 {
opp-hz = /bits/ 64 <358000000>;
required-opps = <&rpmhpd_opp_nom>;
};
};
I still don't like the shared OPP tables to be positioned inmidst of the device nodes, but it seems we currently don't have a better convention.
mdss: mdss@ae00000 { compatible = "qcom,sdm845-mdss"; reg = <0 0x0ae00000 0 0x1000>;
@@ -3340,6 +3369,8 @@ <&dispcc DISP_CC_MDSS_VSYNC_CLK>; assigned-clock-rates = <300000000>, <19200000>;
operating-points-v2 = <&mdp_opp_table>;
power-domains = <&rpmhpd SDM845_CX>; interrupt-parent = <&mdss>; interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
@@ -3364,6 +3395,30 @@ }; }; };
mdp_opp_table: mdp-opp-table {
compatible = "operating-points-v2";
opp-19200000 {
opp-hz = /bits/ 64 <19200000>;
required-opps = <&rpmhpd_opp_min_svs>;
};
opp-171428571 {
opp-hz = /bits/ 64 <171428571>;
required-opps = <&rpmhpd_opp_low_svs>;
};
opp-344000000 {
opp-hz = /bits/ 64 <344000000>;
required-opps = <&rpmhpd_opp_svs_l1>;
};
opp-430000000 {
opp-hz = /bits/ 64 <430000000>;
required-opps = <&rpmhpd_opp_nom>;
};
}; }; dsi0: dsi@ae94000 {
@@ -3386,6 +3441,8 @@ "core", "iface", "bus";
operating-points-v2 = <&dsi_opp_table>;
power-domains = <&rpmhpd SDM845_CX>; phys = <&dsi0_phy>; phy-names = "dsi";
@@ -3450,6 +3507,8 @@ "core", "iface", "bus";
operating-points-v2 = <&dsi_opp_table>;
power-domains = <&rpmhpd SDM845_CX>; phys = <&dsi1_phy>; phy-names = "dsi";
Reviewed-by: Matthias Kaehlcke mka@chromium.org
Add the OPP tables for DSI and MDP based on the perf state/clk requirements, and add the power-domains property to specify the scalable power domain.
Signed-off-by: Rajendra Nayak rnayak@codeaurora.org --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 49 ++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index ad57df2..3430c33f 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -2482,6 +2482,8 @@ <19200000>, <19200000>, <19200000>; + operating-points-v2 = <&mdp_opp_table>; + power-domains = <&rpmhpd SC7180_CX>;
interrupt-parent = <&mdss>; interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; @@ -2499,6 +2501,31 @@ }; }; }; + + mdp_opp_table: mdp-opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-345000000 { + opp-hz = /bits/ 64 <345000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-460000000 { + opp-hz = /bits/ 64 <460000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + };
dsi0: dsi@ae94000 { @@ -2522,6 +2549,9 @@ "iface", "bus";
+ operating-points-v2 = <&dsi_opp_table>; + power-domains = <&rpmhpd SC7180_CX>; + phys = <&dsi_phy>; phy-names = "dsi";
@@ -2547,6 +2577,25 @@ }; }; }; + + dsi_opp_table: dsi-opp-table { + compatible = "operating-points-v2"; + + opp-187500000 { + opp-hz = /bits/ 64 <187500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-358000000 { + opp-hz = /bits/ 64 <358000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; };
dsi_phy: dsi-phy@ae94400 {
On Tue, Jun 30, 2020 at 05:26:16PM +0530, Rajendra Nayak wrote:
Add the OPP tables for DSI and MDP based on the perf state/clk requirements, and add the power-domains property to specify the scalable power domain.
Signed-off-by: Rajendra Nayak rnayak@codeaurora.org
Reviewed-by: Matthias Kaehlcke mka@chromium.org
dri-devel@lists.freedesktop.org