Skip to content

Commit 70f0b05

Browse files
Ovidiu Buneaalexdeucher
authored andcommitted
drm/amd/display: Correct sequences and delays for DCN35 PG & RCG
[why] The current PG & RCG programming in driver has some gaps and incorrect sequences. [how] Added delays after ungating clocks to allow ramp up, increased polling to allow more time for power up, and removed the incorrect sequences. Cc: Mario Limonciello <mario.limonciello@amd.com> Cc: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Charlene Liu <charlene.liu@amd.com> Signed-off-by: Ovidiu Bunea <ovidiu.bunea@amd.com> Signed-off-by: Wayne Lin <wayne.lin@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (cherry picked from commit 1bde558) Cc: stable@vger.kernel.org
1 parent f5c3237 commit 70f0b05

File tree

7 files changed

+111
-164
lines changed

7 files changed

+111
-164
lines changed

drivers/gpu/drm/amd/display/dc/dc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,7 @@ struct dc_debug_options {
11451145
bool enable_hblank_borrow;
11461146
bool force_subvp_df_throttle;
11471147
uint32_t acpi_transition_bitmasks[MAX_PIPES];
1148+
bool enable_pg_cntl_debug_logs;
11481149
};
11491150

11501151

drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -133,30 +133,34 @@ enum dsc_clk_source {
133133
};
134134

135135

136-
static void dccg35_set_dsc_clk_rcg(struct dccg *dccg, int inst, bool enable)
136+
static void dccg35_set_dsc_clk_rcg(struct dccg *dccg, int inst, bool allow_rcg)
137137
{
138138
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
139139

140-
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc && enable)
140+
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc && allow_rcg)
141141
return;
142142

143143
switch (inst) {
144144
case 0:
145-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, enable ? 0 : 1);
145+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
146146
break;
147147
case 1:
148-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, enable ? 0 : 1);
148+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
149149
break;
150150
case 2:
151-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, enable ? 0 : 1);
151+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
152152
break;
153153
case 3:
154-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, enable ? 0 : 1);
154+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
155155
break;
156156
default:
157157
BREAK_TO_DEBUGGER();
158158
return;
159159
}
160+
161+
/* Wait for clock to ramp */
162+
if (!allow_rcg)
163+
udelay(10);
160164
}
161165

162166
static void dccg35_set_symclk32_se_rcg(
@@ -385,35 +389,34 @@ static void dccg35_set_dtbclk_p_rcg(struct dccg *dccg, int inst, bool enable)
385389
}
386390
}
387391

388-
static void dccg35_set_dppclk_rcg(struct dccg *dccg,
389-
int inst, bool enable)
392+
static void dccg35_set_dppclk_rcg(struct dccg *dccg, int inst, bool allow_rcg)
390393
{
391-
392394
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
393395

394-
395-
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp && enable)
396+
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp && allow_rcg)
396397
return;
397398

398399
switch (inst) {
399400
case 0:
400-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, enable ? 0 : 1);
401+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
401402
break;
402403
case 1:
403-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, enable ? 0 : 1);
404+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
404405
break;
405406
case 2:
406-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, enable ? 0 : 1);
407+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
407408
break;
408409
case 3:
409-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, enable ? 0 : 1);
410+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
410411
break;
411412
default:
412413
BREAK_TO_DEBUGGER();
413414
break;
414415
}
415-
//DC_LOG_DEBUG("%s: inst(%d) DPPCLK rcg_disable: %d\n", __func__, inst, enable ? 0 : 1);
416416

417+
/* Wait for clock to ramp */
418+
if (!allow_rcg)
419+
udelay(10);
417420
}
418421

419422
static void dccg35_set_dpstreamclk_rcg(
@@ -1177,32 +1180,34 @@ static void dccg35_update_dpp_dto(struct dccg *dccg, int dpp_inst,
11771180
}
11781181

11791182
static void dccg35_set_dppclk_root_clock_gating(struct dccg *dccg,
1180-
uint32_t dpp_inst, uint32_t enable)
1183+
uint32_t dpp_inst, uint32_t disallow_rcg)
11811184
{
11821185
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
11831186

1184-
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp)
1187+
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp && !disallow_rcg)
11851188
return;
11861189

11871190

11881191
switch (dpp_inst) {
11891192
case 0:
1190-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, enable);
1193+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, disallow_rcg);
11911194
break;
11921195
case 1:
1193-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, enable);
1196+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, disallow_rcg);
11941197
break;
11951198
case 2:
1196-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, enable);
1199+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, disallow_rcg);
11971200
break;
11981201
case 3:
1199-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, enable);
1202+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, disallow_rcg);
12001203
break;
12011204
default:
12021205
break;
12031206
}
1204-
//DC_LOG_DEBUG("%s: dpp_inst(%d) rcg: %d\n", __func__, dpp_inst, enable);
12051207

1208+
/* Wait for clock to ramp */
1209+
if (disallow_rcg)
1210+
udelay(10);
12061211
}
12071212

12081213
static void dccg35_get_pixel_rate_div(
@@ -1782,35 +1787,31 @@ static void dccg35_enable_dscclk(struct dccg *dccg, int inst)
17821787
//Disable DTO
17831788
switch (inst) {
17841789
case 0:
1785-
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
1786-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, 1);
1790+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, 1);
17871791

17881792
REG_UPDATE_2(DSCCLK0_DTO_PARAM,
17891793
DSCCLK0_DTO_PHASE, 0,
17901794
DSCCLK0_DTO_MODULO, 0);
17911795
REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1);
17921796
break;
17931797
case 1:
1794-
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
1795-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, 1);
1798+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, 1);
17961799

17971800
REG_UPDATE_2(DSCCLK1_DTO_PARAM,
17981801
DSCCLK1_DTO_PHASE, 0,
17991802
DSCCLK1_DTO_MODULO, 0);
18001803
REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1);
18011804
break;
18021805
case 2:
1803-
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
1804-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, 1);
1806+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, 1);
18051807

18061808
REG_UPDATE_2(DSCCLK2_DTO_PARAM,
18071809
DSCCLK2_DTO_PHASE, 0,
18081810
DSCCLK2_DTO_MODULO, 0);
18091811
REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1);
18101812
break;
18111813
case 3:
1812-
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
1813-
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, 1);
1814+
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, 1);
18141815

18151816
REG_UPDATE_2(DSCCLK3_DTO_PARAM,
18161817
DSCCLK3_DTO_PHASE, 0,
@@ -1821,6 +1822,9 @@ static void dccg35_enable_dscclk(struct dccg *dccg, int inst)
18211822
BREAK_TO_DEBUGGER();
18221823
return;
18231824
}
1825+
1826+
/* Wait for clock to ramp */
1827+
udelay(10);
18241828
}
18251829

18261830
static void dccg35_disable_dscclk(struct dccg *dccg,
@@ -1864,6 +1868,9 @@ static void dccg35_disable_dscclk(struct dccg *dccg,
18641868
default:
18651869
return;
18661870
}
1871+
1872+
/* Wait for clock ramp */
1873+
udelay(10);
18671874
}
18681875

18691876
static void dccg35_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
@@ -2349,10 +2356,7 @@ static void dccg35_disable_symclk_se_cb(
23492356

23502357
void dccg35_root_gate_disable_control(struct dccg *dccg, uint32_t pipe_idx, uint32_t disable_clock_gating)
23512358
{
2352-
2353-
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) {
2354-
dccg35_set_dppclk_root_clock_gating(dccg, pipe_idx, disable_clock_gating);
2355-
}
2359+
dccg35_set_dppclk_root_clock_gating(dccg, pipe_idx, disable_clock_gating);
23562360
}
23572361

23582362
static const struct dccg_funcs dccg35_funcs_new = {

drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c

Lines changed: 20 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ static void enable_memory_low_power(struct dc *dc)
113113
}
114114
#endif
115115

116+
static void print_pg_status(struct dc *dc, const char *debug_func, const char *debug_log)
117+
{
118+
if (dc->debug.enable_pg_cntl_debug_logs && dc->res_pool->pg_cntl) {
119+
if (dc->res_pool->pg_cntl->funcs->print_pg_status)
120+
dc->res_pool->pg_cntl->funcs->print_pg_status(dc->res_pool->pg_cntl, debug_func, debug_log);
121+
}
122+
}
123+
116124
void dcn35_set_dmu_fgcg(struct dce_hwseq *hws, bool enable)
117125
{
118126
REG_UPDATE_3(DMU_CLK_CNTL,
@@ -137,6 +145,8 @@ void dcn35_init_hw(struct dc *dc)
137145
uint32_t user_level = MAX_BACKLIGHT_LEVEL;
138146
int i;
139147

148+
print_pg_status(dc, __func__, ": start");
149+
140150
if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
141151
dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
142152

@@ -200,10 +210,7 @@ void dcn35_init_hw(struct dc *dc)
200210

201211
/* we want to turn off all dp displays before doing detection */
202212
dc->link_srv->blank_all_dp_displays(dc);
203-
/*
204-
if (hws->funcs.enable_power_gating_plane)
205-
hws->funcs.enable_power_gating_plane(dc->hwseq, true);
206-
*/
213+
207214
if (res_pool->hubbub && res_pool->hubbub->funcs->dchubbub_init)
208215
res_pool->hubbub->funcs->dchubbub_init(dc->res_pool->hubbub);
209216
/* If taking control over from VBIOS, we may want to optimize our first
@@ -236,6 +243,8 @@ void dcn35_init_hw(struct dc *dc)
236243
}
237244

238245
hws->funcs.init_pipes(dc, dc->current_state);
246+
print_pg_status(dc, __func__, ": after init_pipes");
247+
239248
if (dc->res_pool->hubbub->funcs->allow_self_refresh_control &&
240249
!dc->res_pool->hubbub->ctx->dc->debug.disable_stutter)
241250
dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
@@ -312,6 +321,7 @@ void dcn35_init_hw(struct dc *dc)
312321
if (dc->res_pool->pg_cntl->funcs->init_pg_status)
313322
dc->res_pool->pg_cntl->funcs->init_pg_status(dc->res_pool->pg_cntl);
314323
}
324+
print_pg_status(dc, __func__, ": after init_pg_status");
315325
}
316326

317327
static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
@@ -500,97 +510,6 @@ void dcn35_physymclk_root_clock_control(struct dce_hwseq *hws, unsigned int phy_
500510
}
501511
}
502512

503-
void dcn35_dsc_pg_control(
504-
struct dce_hwseq *hws,
505-
unsigned int dsc_inst,
506-
bool power_on)
507-
{
508-
uint32_t power_gate = power_on ? 0 : 1;
509-
uint32_t pwr_status = power_on ? 0 : 2;
510-
uint32_t org_ip_request_cntl = 0;
511-
512-
if (hws->ctx->dc->debug.disable_dsc_power_gate)
513-
return;
514-
if (hws->ctx->dc->debug.ignore_pg)
515-
return;
516-
REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
517-
if (org_ip_request_cntl == 0)
518-
REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
519-
520-
switch (dsc_inst) {
521-
case 0: /* DSC0 */
522-
REG_UPDATE(DOMAIN16_PG_CONFIG,
523-
DOMAIN_POWER_GATE, power_gate);
524-
525-
REG_WAIT(DOMAIN16_PG_STATUS,
526-
DOMAIN_PGFSM_PWR_STATUS, pwr_status,
527-
1, 1000);
528-
break;
529-
case 1: /* DSC1 */
530-
REG_UPDATE(DOMAIN17_PG_CONFIG,
531-
DOMAIN_POWER_GATE, power_gate);
532-
533-
REG_WAIT(DOMAIN17_PG_STATUS,
534-
DOMAIN_PGFSM_PWR_STATUS, pwr_status,
535-
1, 1000);
536-
break;
537-
case 2: /* DSC2 */
538-
REG_UPDATE(DOMAIN18_PG_CONFIG,
539-
DOMAIN_POWER_GATE, power_gate);
540-
541-
REG_WAIT(DOMAIN18_PG_STATUS,
542-
DOMAIN_PGFSM_PWR_STATUS, pwr_status,
543-
1, 1000);
544-
break;
545-
case 3: /* DSC3 */
546-
REG_UPDATE(DOMAIN19_PG_CONFIG,
547-
DOMAIN_POWER_GATE, power_gate);
548-
549-
REG_WAIT(DOMAIN19_PG_STATUS,
550-
DOMAIN_PGFSM_PWR_STATUS, pwr_status,
551-
1, 1000);
552-
break;
553-
default:
554-
BREAK_TO_DEBUGGER();
555-
break;
556-
}
557-
558-
if (org_ip_request_cntl == 0)
559-
REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
560-
}
561-
562-
void dcn35_enable_power_gating_plane(struct dce_hwseq *hws, bool enable)
563-
{
564-
bool force_on = true; /* disable power gating */
565-
uint32_t org_ip_request_cntl = 0;
566-
567-
if (hws->ctx->dc->debug.disable_hubp_power_gate)
568-
return;
569-
if (hws->ctx->dc->debug.ignore_pg)
570-
return;
571-
REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
572-
if (org_ip_request_cntl == 0)
573-
REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
574-
/* DCHUBP0/1/2/3/4/5 */
575-
REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
576-
REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
577-
/* DPP0/1/2/3/4/5 */
578-
REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
579-
REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
580-
581-
force_on = true; /* disable power gating */
582-
if (enable && !hws->ctx->dc->debug.disable_dsc_power_gate)
583-
force_on = false;
584-
585-
/* DCS0/1/2/3/4 */
586-
REG_UPDATE(DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
587-
REG_UPDATE(DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
588-
REG_UPDATE(DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
589-
REG_UPDATE(DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
590-
591-
592-
}
593-
594513
/* In headless boot cases, DIG may be turned
595514
* on which causes HW/SW discrepancies.
596515
* To avoid this, power down hardware on boot
@@ -1453,6 +1372,8 @@ void dcn35_prepare_bandwidth(
14531372
}
14541373

14551374
dcn20_prepare_bandwidth(dc, context);
1375+
1376+
print_pg_status(dc, __func__, ": after rcg and power up");
14561377
}
14571378

14581379
void dcn35_optimize_bandwidth(
@@ -1461,6 +1382,8 @@ void dcn35_optimize_bandwidth(
14611382
{
14621383
struct pg_block_update pg_update_state;
14631384

1385+
print_pg_status(dc, __func__, ": before rcg and power up");
1386+
14641387
dcn20_optimize_bandwidth(dc, context);
14651388

14661389
if (dc->hwss.calc_blocks_to_gate) {
@@ -1472,6 +1395,8 @@ void dcn35_optimize_bandwidth(
14721395
if (dc->hwss.root_clock_control)
14731396
dc->hwss.root_clock_control(dc, &pg_update_state, false);
14741397
}
1398+
1399+
print_pg_status(dc, __func__, ": after rcg and power up");
14751400
}
14761401

14771402
void dcn35_set_drr(struct pipe_ctx **pipe_ctx,

0 commit comments

Comments
 (0)