drm/msm/dpu: add support for clk and bw scaling for display
Subsystems (6)
PATCH v3 1/3 drm/msm/dpu: add support for clk and bw scaling for display
Do not pick this patch as this patch was added by
mistake. This patch is already uploaded in the
patchwork link mentioned below.
https://patchwork.kernel.org/patch/11468783/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 106 +++++++++++++++++++++---- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 5 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 4 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 37 ++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 + drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 9 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 82 +++++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 4 + 8 files changed, 228 insertions(+), 23 deletions(-)
drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +89 -17
@@ -29,6 +29,73 @@ enum dpu_perf_mode {DPU_PERF_MODE_MAX }; +/** +* @_dpu_core_perf_calc_bw() - to calculate BW per crtc +* @kms - pointer to the dpu_kms +* @crtc - pointer to a crtc +* Return: returns aggregated BW for all planes in crtc. +*/ +static u64 _dpu_core_perf_calc_bw (struct dpu_kms *kms, +struct drm_crtc *crtc) +{ +struct drm_plane *plane; +struct dpu_plane_state *pstate; +u64 crtc_plane_bw =0 ; +u32 bw_factor; + +drm_atomic_crtc_for_each_plane (plane, crtc) { + pstate =to_dpu_plane_state (plane->state); + +if (!pstate) +continue ; + + crtc_plane_bw += pstate->plane_fetch_bw; + } + + bw_factor = kms->catalog->perf.bw_inefficiency_factor; +if (bw_factor) + crtc_plane_bw =mult_frac (crtc_plane_bw, bw_factor,100 ); + +return crtc_plane_bw; +} + +/** +* _dpu_core_perf_calc_clk() - to calculate clock per crtc +* @kms - pointer to the dpu_kms +* @crtc - pointer to a crtc +* @state - pointer to a crtc state +* Return: returns max clk for all planes in crtc. +*/ +static u64 _dpu_core_perf_calc_clk (struct dpu_kms *kms, +struct drm_crtc *crtc,struct drm_crtc_state *state) +{ +struct drm_plane *plane; +struct dpu_plane_state *pstate; +struct drm_display_mode *mode; +u64 crtc_clk; +u32 clk_factor; + + mode = &state->adjusted_mode; + + crtc_clk = mode->vtotal * mode->hdisplay *drm_mode_vrefresh (mode); + +drm_atomic_crtc_for_each_plane (plane, crtc) { + pstate =to_dpu_plane_state (plane->state); + +if (!pstate) +continue ; + + crtc_clk =max (pstate->plane_clk, crtc_clk); + } + + clk_factor = kms->catalog->perf.clk_inefficiency_factor; +if (clk_factor) + crtc_clk =mult_frac (crtc_clk, clk_factor,100 ); + +return crtc_clk; +} + +static struct dpu_kms *_dpu_crtc_get_kms (struct drm_crtc *crtc) {struct msm_drm_private *priv;
@@ -67,12 +134,7 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms, dpu_cstate =to_dpu_crtc_state (state);memset (perf,0 ,sizeof (struct dpu_core_perf_params )); -if (!dpu_cstate->bw_control) { - perf->bw_ctl = kms->catalog->perf.max_bw_high * -1000ULL ; - perf->max_per_pipe_ib = perf->bw_ctl; - perf->core_clk_rate = kms->perf.max_core_clk_rate; - }else if (kms->perf.perf_tune.mode ==DPU_PERF_MODE_MINIMUM ) { +if (kms->perf.perf_tune.mode ==DPU_PERF_MODE_MINIMUM ) { perf->bw_ctl =0 ; perf->max_per_pipe_ib =0 ; perf->core_clk_rate =0 ;
@@ -80,6 +142,10 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms, perf->bw_ctl = kms->perf.fix_core_ab_vote; perf->max_per_pipe_ib = kms->perf.fix_core_ib_vote; perf->core_clk_rate = kms->perf.fix_core_clk_rate; + }else { + perf->bw_ctl =_dpu_core_perf_calc_bw (kms, crtc); + perf->max_per_pipe_ib = kms->catalog->perf.min_dram_ib; + perf->core_clk_rate =_dpu_core_perf_calc_clk (kms, crtc, state); } DPU_DEBUG(
@@ -132,11 +198,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,DPU_DEBUG ("crtc:%d bw:%llu ctrl:%d\n" , tmp_crtc->base.id, tmp_cstate->new_perf.bw_ctl, tmp_cstate->bw_control); -/* -* For bw check only use the bw if the -* atomic property has been already set -*/ -if (tmp_cstate->bw_control) + bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl; }
@@ -152,9 +214,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,DPU_DEBUG ("final threshold bw limit = %d\n" , threshold); -if (!dpu_cstate->bw_control) { -DPU_DEBUG ("bypass bandwidth check\n" ); - }else if (!threshold) { +if (!threshold) {DPU_ERROR ("no bandwidth limits specified\n" );return -E2BIG ; }else if (bw > threshold) {
@@ -175,7 +235,8 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, =dpu_crtc_get_client_type (crtc);struct drm_crtc *tmp_crtc;struct dpu_crtc_state *dpu_cstate; -int ret =0 ; +int i, ret =0 ; +u64 avg_bw;drm_for_each_crtc (tmp_crtc, crtc->dev) { if (tmp_crtc->enabled &&
@@ -186,10 +247,21 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, perf.max_per_pipe_ib =max (perf.max_per_pipe_ib, dpu_cstate->new_perf.max_per_pipe_ib); -DPU_DEBUG ("crtc=%d bw=%llu\n" , tmp_crtc->base.id, - dpu_cstate->new_perf.bw_ctl); + perf.bw_ctl += dpu_cstate->new_perf.bw_ctl; + +DPU_DEBUG ("crtc=%d bw=%llu paths:%d\n" , + tmp_crtc->base.id, + dpu_cstate->new_perf.bw_ctl, kms->num_paths); } } + + avg_bw = kms->num_paths ? + perf.bw_ctl / kms->num_paths :0 ; + +for (i =0 ; i < kms->num_paths; i++) +icc_set_bw (kms->path[i], +Bps_to_icc (avg_bw), (perf.max_per_pipe_ib)); +return ret; }
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +4 -1
@@ -519,7 +519,8 @@ .max_bw_high = 5500000, .min_core_ib = 2400000, .min_llcc_ib = 800000, - .min_dram_ib = 800000, + .min_dram_ib = 1600000, + .min_prefill_lines = 24, .danger_lut_tbl = {0xff, 0xffff, 0x0}, .qos_lut_tbl = { {.nentry = ARRAY_SIZE(sc7180_qos_linear),
@@ -536,6 +537,8 @@ {.rd_enable = 1, .wr_enable = 1}, {.rd_enable = 1, .wr_enable = 0} }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, };/*************************************************************
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +4 -0
@@ -616,6 +616,8 @@ struct dpu_perf_cdp_cfg {* @downscaling_prefill_lines downscaling latency in lines * @amortizable_theshold minimum y position for traffic shaping prefill * @min_prefill_lines minimum pipeline latency in lines +* @clk_inefficiency_factor DPU src clock inefficiency factor +* @bw_inefficiency_factor DPU axi bus bw inefficiency factor * @safe_lut_tbl: LUT tables for safe signals * @danger_lut_tbl: LUT tables for danger signals * @qos_lut_tbl: LUT tables for QoS signals
@@ -640,6 +642,8 @@ struct dpu_perf_cfg {u32 downscaling_prefill_lines;u32 amortizable_threshold;u32 min_prefill_lines; +u32 clk_inefficiency_factor; +u32 bw_inefficiency_factor;u32 safe_lut_tbl[DPU_QOS_LUT_USAGE_MAX ];u32 danger_lut_tbl[DPU_QOS_LUT_USAGE_MAX ];struct dpu_qos_lut_tbl qos_lut_tbl[DPU_QOS_LUT_USAGE_MAX ];
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +36 -1
@@ -228,6 +228,28 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) }#endif +static int dpu_kms_parse_data_bus_icc_path (struct dpu_kms *dpu_kms) +{ +struct icc_path *path0; +struct icc_path *path1; +struct drm_device *dev = dpu_kms->dev; + + path0 =of_icc_get (dev->dev,"mdp0-mem" ); + path1 =of_icc_get (dev->dev,"mdp1-mem" ); + +if (IS_ERR_OR_NULL (path0)) +return PTR_ERR_OR_ZERO (path0); + + dpu_kms->path[0 ] = path0; + dpu_kms->num_paths =1 ; + +if (!IS_ERR_OR_NULL (path1)) { + dpu_kms->path[1 ] = path1; + dpu_kms->num_paths++; + } +return 0 ; +} +static int dpu_kms_enable_vblank (struct msm_kms *kms,struct drm_crtc *crtc) {return dpu_crtc_vblank (crtc, true);
@@ -910,6 +932,9 @@ static int dpu_kms_hw_init(struct msm_kms *kms)dpu_vbif_init_memtypes (dpu_kms); +if (of_device_is_compatible (dev->dev->of_node,"qcom,sc7180-mdss" )) +dpu_kms_parse_data_bus_icc_path (dpu_kms); +pm_runtime_put_sync (&dpu_kms->pdev->dev);return 0 ;
@@ -1015,7 +1040,7 @@ static int dpu_dev_remove(struct platform_device *pdev)static int __maybe_unused dpu_runtime_suspend (struct device *dev) { -int rc =-1 ; +int i, rc =-1 ;struct platform_device *pdev =to_platform_device (dev);struct dpu_kms *dpu_kms =platform_get_drvdata (pdev);struct drm_device *ddev;
@@ -1026,6 +1051,9 @@ static int __maybe_unused dpu_runtime_suspend(struct device *dev)if (rc)DPU_ERROR ("clock disable failed rc:%d\n" , rc); +for (i =0 ; i < dpu_kms->num_paths; i++) +icc_set_bw (dpu_kms->path[i],0 ,0 ); +return rc; }
@@ -1037,8 +1065,15 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev)struct drm_encoder *encoder;struct drm_device *ddev;struct dss_module_power *mp = &dpu_kms->mp; +int i; ddev = dpu_kms->dev; + +/* Min vote of BW is required before turning on AXI clk */ +for (i =0 ; i < dpu_kms->num_paths; i++) +icc_set_bw (dpu_kms->path[i],0 , + dpu_kms->catalog->perf.min_dram_ib); + rc =msm_dss_enable_clk (mp->clk_config, mp->num_clk, true);if (rc) {DPU_ERROR ("clock enable failed rc:%d\n" , rc);
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +4 -0
@@ -8,6 +8,8 @@#ifndef __DPU_KMS_H__#define __DPU_KMS_H__ +#include <linux/interconnect.h> +#include <drm/drm_drv.h> #include "msm_drv.h"
@@ -130,6 +132,8 @@ struct dpu_kms {* when disabled. */ atomic_t bandwidth_ref; +struct icc_path *path[2 ]; +u32 num_paths; };struct vsync_info {
drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c +5 -4
@@ -8,7 +8,6 @@#include <linux/irqdesc.h> #include <linux/irqchip/chained_irq.h> #include "dpu_kms.h" -#include <linux/interconnect.h> #define to_dpu_mdss (x) container_of(x, struct dpu_mdss, base)
@@ -315,9 +314,11 @@ int dpu_mdss_init(struct drm_device *dev) } dpu_mdss->mmio_len =resource_size (res); - ret =dpu_mdss_parse_data_bus_icc_path (dev, dpu_mdss); -if (ret) -return ret; +if (!of_device_is_compatible (dev->dev->of_node,"qcom,sc7180-mdss" )) { + ret =dpu_mdss_parse_data_bus_icc_path (dev, dpu_mdss); +if (ret) +return ret; + } mp = &dpu_mdss->mp; ret =msm_dss_parse_clock (pdev, mp);
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +82 -0
94 lines not on this page · raw message
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h +4 -0
@@ -25,6 +25,8 @@* @scaler3_cfg: configuration data for scaler3 * @pixel_ext: configuration data for pixel extensions * @cdp_cfg: CDP configuration +* @plane_fetch_bw: calculated BW per plane +* @plane_clk: calculated clk per plane */ struct dpu_plane_state {struct drm_plane_state base;
@@ -39,6 +41,8 @@ struct dpu_plane_state {struct dpu_hw_pixel_ext pixel_ext;struct dpu_hw_pipe_cdp_cfg cdp_cfg; +u64 plane_fetch_bw; +u64 plane_clk; };/**
Signature · 1 line
1.9.1
PATCH v3 2/3 arm64: dts: sc7180: add bus clock to mdp node for sc7180 target
Move the bus clock to mdp device node,in order to facilitate bus band width scaling on sc7180 target.
The parent device MDSS will not vote for bus bw, instead the vote will be triggered by mdp device node. Since a minimum vote is required to turn on bus clock, move the clock node to mdp device from where the votes are requested.
This patch has dependency on the below series
https://patchwork.kernel.org/patch/11468783/
--- arch/arm64/boot/dts/qcom/sc7180.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arm64/boot/dts/qcom/sc7180.dtsi +4 -4
@@ -1510,10 +1510,9 @@ power-domains = <&dispcc MDSS_GDSC>; clocks = <&gcc GCC_DISP_AHB_CLK>, - <&gcc GCC_DISP_HF_AXI_CLK>, <&dispcc DISP_CC_MDSS_AHB_CLK>, <&dispcc DISP_CC_MDSS_MDP_CLK>; - clock-names = "iface", "bus", "ahb", "core"; + clock-names = "iface", "ahb", "core"; assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>; assigned-clock-rates = <300000000>;
@@ -1536,12 +1535,13 @@ <0 0x0aeb0000 0 0x2008>; reg-names = "mdp", "vbif"; - clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + clocks = <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, <&dispcc DISP_CC_MDSS_ROT_CLK>, <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, <&dispcc DISP_CC_MDSS_MDP_CLK>, <&dispcc DISP_CC_MDSS_VSYNC_CLK>; - clock-names = "iface", "rot", "lut", "core", + clock-names = "bus", "iface", "rot", "lut", "core", "vsync"; assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>, <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
Signature · 1 line
1.9.1
PATCH v3 3/3 arm64: dts: sc7180: add interconnect bindings for display
In reply to Krishna ManikandanThis change adds the interconnect bindings to the MDSS node. This will establish Display to DDR path for bus bandwidth voting.
Changes in v2:
- Change in commit message(Matthias Kaehlcke)
Changes in v3:
- Updated commit message to include
reviewer's name in v2
--- arch/arm64/boot/dts/qcom/sc7180.dtsi | 3 +++ 1 file changed, 3 insertions(+)
arch/arm64/boot/dts/qcom/sc7180.dtsi +3 -0
@@ -1521,6 +1521,9 @@ interrupt-controller; #interrupt-cells = <1>; + interconnects = <&mmss_noc MASTER_MDP0 &mc_virt SLAVE_EBI1>; + interconnect-names = "mdp0-mem"; + iommus = <&apps_smmu 0x800 0x2>; #address-cells = <2>;
Signature · 1 line
1.9.1