Skip to content

Commit 04d9044

Browse files
Kalyan Thotarobclark
authored andcommitted
drm/msm/dpu: add support for clk and bw scaling for display
This change adds support to scale src clk and bandwidth as per composition requirements. Interconnect registration for bw has been moved to mdp device node from mdss to facilitate the scaling. Signed-off-by: Kalyan Thota <kalyan_t@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org>
1 parent 4259ff7 commit 04d9044

File tree

8 files changed

+228
-23
lines changed

8 files changed

+228
-23
lines changed

drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c

Lines changed: 89 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,73 @@ enum dpu_perf_mode {
2929
DPU_PERF_MODE_MAX
3030
};
3131

32+
/**
33+
* @_dpu_core_perf_calc_bw() - to calculate BW per crtc
34+
* @kms - pointer to the dpu_kms
35+
* @crtc - pointer to a crtc
36+
* Return: returns aggregated BW for all planes in crtc.
37+
*/
38+
static u64 _dpu_core_perf_calc_bw(struct dpu_kms *kms,
39+
struct drm_crtc *crtc)
40+
{
41+
struct drm_plane *plane;
42+
struct dpu_plane_state *pstate;
43+
u64 crtc_plane_bw = 0;
44+
u32 bw_factor;
45+
46+
drm_atomic_crtc_for_each_plane(plane, crtc) {
47+
pstate = to_dpu_plane_state(plane->state);
48+
49+
if (!pstate)
50+
continue;
51+
52+
crtc_plane_bw += pstate->plane_fetch_bw;
53+
}
54+
55+
bw_factor = kms->catalog->perf.bw_inefficiency_factor;
56+
if (bw_factor)
57+
crtc_plane_bw = mult_frac(crtc_plane_bw, bw_factor, 100);
58+
59+
return crtc_plane_bw;
60+
}
61+
62+
/**
63+
* _dpu_core_perf_calc_clk() - to calculate clock per crtc
64+
* @kms - pointer to the dpu_kms
65+
* @crtc - pointer to a crtc
66+
* @state - pointer to a crtc state
67+
* Return: returns max clk for all planes in crtc.
68+
*/
69+
static u64 _dpu_core_perf_calc_clk(struct dpu_kms *kms,
70+
struct drm_crtc *crtc, struct drm_crtc_state *state)
71+
{
72+
struct drm_plane *plane;
73+
struct dpu_plane_state *pstate;
74+
struct drm_display_mode *mode;
75+
u64 crtc_clk;
76+
u32 clk_factor;
77+
78+
mode = &state->adjusted_mode;
79+
80+
crtc_clk = mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode);
81+
82+
drm_atomic_crtc_for_each_plane(plane, crtc) {
83+
pstate = to_dpu_plane_state(plane->state);
84+
85+
if (!pstate)
86+
continue;
87+
88+
crtc_clk = max(pstate->plane_clk, crtc_clk);
89+
}
90+
91+
clk_factor = kms->catalog->perf.clk_inefficiency_factor;
92+
if (clk_factor)
93+
crtc_clk = mult_frac(crtc_clk, clk_factor, 100);
94+
95+
return crtc_clk;
96+
}
97+
98+
3299
static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)
33100
{
34101
struct msm_drm_private *priv;
@@ -67,19 +134,18 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms,
67134
dpu_cstate = to_dpu_crtc_state(state);
68135
memset(perf, 0, sizeof(struct dpu_core_perf_params));
69136

70-
if (!dpu_cstate->bw_control) {
71-
perf->bw_ctl = kms->catalog->perf.max_bw_high *
72-
1000ULL;
73-
perf->max_per_pipe_ib = perf->bw_ctl;
74-
perf->core_clk_rate = kms->perf.max_core_clk_rate;
75-
} else if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) {
137+
if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) {
76138
perf->bw_ctl = 0;
77139
perf->max_per_pipe_ib = 0;
78140
perf->core_clk_rate = 0;
79141
} else if (kms->perf.perf_tune.mode == DPU_PERF_MODE_FIXED) {
80142
perf->bw_ctl = kms->perf.fix_core_ab_vote;
81143
perf->max_per_pipe_ib = kms->perf.fix_core_ib_vote;
82144
perf->core_clk_rate = kms->perf.fix_core_clk_rate;
145+
} else {
146+
perf->bw_ctl = _dpu_core_perf_calc_bw(kms, crtc);
147+
perf->max_per_pipe_ib = kms->catalog->perf.min_dram_ib;
148+
perf->core_clk_rate = _dpu_core_perf_calc_clk(kms, crtc, state);
83149
}
84150

85151
DPU_DEBUG(
@@ -132,11 +198,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
132198
DPU_DEBUG("crtc:%d bw:%llu ctrl:%d\n",
133199
tmp_crtc->base.id, tmp_cstate->new_perf.bw_ctl,
134200
tmp_cstate->bw_control);
135-
/*
136-
* For bw check only use the bw if the
137-
* atomic property has been already set
138-
*/
139-
if (tmp_cstate->bw_control)
201+
140202
bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl;
141203
}
142204

@@ -152,9 +214,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
152214

153215
DPU_DEBUG("final threshold bw limit = %d\n", threshold);
154216

155-
if (!dpu_cstate->bw_control) {
156-
DPU_DEBUG("bypass bandwidth check\n");
157-
} else if (!threshold) {
217+
if (!threshold) {
158218
DPU_ERROR("no bandwidth limits specified\n");
159219
return -E2BIG;
160220
} else if (bw > threshold) {
@@ -175,7 +235,8 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms,
175235
= dpu_crtc_get_client_type(crtc);
176236
struct drm_crtc *tmp_crtc;
177237
struct dpu_crtc_state *dpu_cstate;
178-
int ret = 0;
238+
int i, ret = 0;
239+
u64 avg_bw;
179240

180241
drm_for_each_crtc(tmp_crtc, crtc->dev) {
181242
if (tmp_crtc->enabled &&
@@ -186,10 +247,21 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms,
186247
perf.max_per_pipe_ib = max(perf.max_per_pipe_ib,
187248
dpu_cstate->new_perf.max_per_pipe_ib);
188249

189-
DPU_DEBUG("crtc=%d bw=%llu\n", tmp_crtc->base.id,
190-
dpu_cstate->new_perf.bw_ctl);
250+
perf.bw_ctl += dpu_cstate->new_perf.bw_ctl;
251+
252+
DPU_DEBUG("crtc=%d bw=%llu paths:%d\n",
253+
tmp_crtc->base.id,
254+
dpu_cstate->new_perf.bw_ctl, kms->num_paths);
191255
}
192256
}
257+
258+
avg_bw = kms->num_paths ?
259+
perf.bw_ctl / kms->num_paths : 0;
260+
261+
for (i = 0; i < kms->num_paths; i++)
262+
icc_set_bw(kms->path[i],
263+
Bps_to_icc(avg_bw), (perf.max_per_pipe_ib));
264+
193265
return ret;
194266
}
195267

drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,8 @@ static const struct dpu_perf_cfg sc7180_perf_data = {
541541
.max_bw_high = 5500000,
542542
.min_core_ib = 2400000,
543543
.min_llcc_ib = 800000,
544-
.min_dram_ib = 800000,
544+
.min_dram_ib = 1600000,
545+
.min_prefill_lines = 24,
545546
.danger_lut_tbl = {0xff, 0xffff, 0x0},
546547
.qos_lut_tbl = {
547548
{.nentry = ARRAY_SIZE(sc7180_qos_linear),
@@ -558,6 +559,8 @@ static const struct dpu_perf_cfg sc7180_perf_data = {
558559
{.rd_enable = 1, .wr_enable = 1},
559560
{.rd_enable = 1, .wr_enable = 0}
560561
},
562+
.clk_inefficiency_factor = 105,
563+
.bw_inefficiency_factor = 120,
561564
};
562565

563566
/*************************************************************

drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,8 @@ struct dpu_perf_cdp_cfg {
651651
* @downscaling_prefill_lines downscaling latency in lines
652652
* @amortizable_theshold minimum y position for traffic shaping prefill
653653
* @min_prefill_lines minimum pipeline latency in lines
654+
* @clk_inefficiency_factor DPU src clock inefficiency factor
655+
* @bw_inefficiency_factor DPU axi bus bw inefficiency factor
654656
* @safe_lut_tbl: LUT tables for safe signals
655657
* @danger_lut_tbl: LUT tables for danger signals
656658
* @qos_lut_tbl: LUT tables for QoS signals
@@ -675,6 +677,8 @@ struct dpu_perf_cfg {
675677
u32 downscaling_prefill_lines;
676678
u32 amortizable_threshold;
677679
u32 min_prefill_lines;
680+
u32 clk_inefficiency_factor;
681+
u32 bw_inefficiency_factor;
678682
u32 safe_lut_tbl[DPU_QOS_LUT_USAGE_MAX];
679683
u32 danger_lut_tbl[DPU_QOS_LUT_USAGE_MAX];
680684
struct dpu_qos_lut_tbl qos_lut_tbl[DPU_QOS_LUT_USAGE_MAX];

drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,28 @@ static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms)
303303
return 0;
304304
}
305305

306+
static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms)
307+
{
308+
struct icc_path *path0;
309+
struct icc_path *path1;
310+
struct drm_device *dev = dpu_kms->dev;
311+
312+
path0 = of_icc_get(dev->dev, "mdp0-mem");
313+
path1 = of_icc_get(dev->dev, "mdp1-mem");
314+
315+
if (IS_ERR_OR_NULL(path0))
316+
return PTR_ERR_OR_ZERO(path0);
317+
318+
dpu_kms->path[0] = path0;
319+
dpu_kms->num_paths = 1;
320+
321+
if (!IS_ERR_OR_NULL(path1)) {
322+
dpu_kms->path[1] = path1;
323+
dpu_kms->num_paths++;
324+
}
325+
return 0;
326+
}
327+
306328
static int dpu_kms_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
307329
{
308330
return dpu_crtc_vblank(crtc, true);
@@ -980,6 +1002,9 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
9801002

9811003
dpu_vbif_init_memtypes(dpu_kms);
9821004

1005+
if (of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss"))
1006+
dpu_kms_parse_data_bus_icc_path(dpu_kms);
1007+
9831008
pm_runtime_put_sync(&dpu_kms->pdev->dev);
9841009

9851010
return 0;
@@ -1085,7 +1110,7 @@ static int dpu_dev_remove(struct platform_device *pdev)
10851110

10861111
static int __maybe_unused dpu_runtime_suspend(struct device *dev)
10871112
{
1088-
int rc = -1;
1113+
int i, rc = -1;
10891114
struct platform_device *pdev = to_platform_device(dev);
10901115
struct dpu_kms *dpu_kms = platform_get_drvdata(pdev);
10911116
struct dss_module_power *mp = &dpu_kms->mp;
@@ -1094,6 +1119,9 @@ static int __maybe_unused dpu_runtime_suspend(struct device *dev)
10941119
if (rc)
10951120
DPU_ERROR("clock disable failed rc:%d\n", rc);
10961121

1122+
for (i = 0; i < dpu_kms->num_paths; i++)
1123+
icc_set_bw(dpu_kms->path[i], 0, 0);
1124+
10971125
return rc;
10981126
}
10991127

@@ -1105,8 +1133,15 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev)
11051133
struct drm_encoder *encoder;
11061134
struct drm_device *ddev;
11071135
struct dss_module_power *mp = &dpu_kms->mp;
1136+
int i;
11081137

11091138
ddev = dpu_kms->dev;
1139+
1140+
/* Min vote of BW is required before turning on AXI clk */
1141+
for (i = 0; i < dpu_kms->num_paths; i++)
1142+
icc_set_bw(dpu_kms->path[i], 0,
1143+
dpu_kms->catalog->perf.min_dram_ib);
1144+
11101145
rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
11111146
if (rc) {
11121147
DPU_ERROR("clock enable failed rc:%d\n", rc);

drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#ifndef __DPU_KMS_H__
99
#define __DPU_KMS_H__
1010

11+
#include <linux/interconnect.h>
12+
1113
#include <drm/drm_drv.h>
1214

1315
#include "msm_drv.h"
@@ -137,6 +139,8 @@ struct dpu_kms {
137139
* when disabled.
138140
*/
139141
atomic_t bandwidth_ref;
142+
struct icc_path *path[2];
143+
u32 num_paths;
140144
};
141145

142146
struct vsync_info {

drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include <linux/irqdesc.h>
99
#include <linux/irqchip/chained_irq.h>
1010
#include "dpu_kms.h"
11-
#include <linux/interconnect.h>
1211

1312
#define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
1413

@@ -315,9 +314,11 @@ int dpu_mdss_init(struct drm_device *dev)
315314
}
316315
dpu_mdss->mmio_len = resource_size(res);
317316

318-
ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss);
319-
if (ret)
320-
return ret;
317+
if (!of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss")) {
318+
ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss);
319+
if (ret)
320+
return ret;
321+
}
321322

322323
mp = &dpu_mdss->mp;
323324
ret = msm_dss_parse_clock(pdev, mp);

0 commit comments

Comments
 (0)