Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: Defer GAMCOR and DSCL power down sequence to vupdate

[WHY]
Every other CM LUT power down sequence is deferred to next vupdate as
memory powerdown updates immediately while selecting LUTs is double
buffered. Previous update to defer LUT power down missed GAMCOR and
DSCL, causing some visible flicker when entering/exiting fullscreen
video playback.

[HOW]
Update dpp deferred update loop to check for valid DPPs in res_pool
instead of referencing dcn_ip which turns out to not be populated during
runtime. Move GAMCOR and DSCL powerdown to dpp deferred updates.

Reviewed-by: Haonan Wang <Haonan.Wang2@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com>
Signed-off-by: Michael Strauss <michael.strauss@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Michael Strauss and committed by
Alex Deucher
5fdccd5b 5ffb5267

+38 -6
+4 -2
drivers/gpu/drm/amd/display/dc/core/dc.c
··· 1897 1897 static void process_deferred_updates(struct dc *dc) 1898 1898 { 1899 1899 #ifdef CONFIG_DRM_AMD_DC_DCN 1900 - int i; 1900 + int i = 0; 1901 1901 1902 - if (dc->debug.enable_mem_low_power.bits.cm) 1902 + if (dc->debug.enable_mem_low_power.bits.cm) { 1903 + ASSERT(dc->dcn_ip->max_num_dpp); 1903 1904 for (i = 0; i < dc->dcn_ip->max_num_dpp; i++) 1904 1905 if (dc->res_pool->dpps[i]->funcs->dpp_deferred_update) 1905 1906 dc->res_pool->dpps[i]->funcs->dpp_deferred_update(dc->res_pool->dpps[i]); 1907 + } 1906 1908 #endif 1907 1909 } 1908 1910
+10 -2
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
··· 205 205 struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); 206 206 207 207 if (dpp->tf_regs->DSCL_MEM_PWR_CTRL) { 208 - REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, power_on ? 0 : 3); 209 - if (power_on) 208 + if (power_on) { 209 + REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 0); 210 210 REG_WAIT(DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, 0, 1, 5); 211 + } else { 212 + if (dpp->base.ctx->dc->debug.enable_mem_low_power.bits.dscl) { 213 + dpp->base.ctx->dc->optimized_required = true; 214 + dpp->base.deferred_reg_writes.bits.disable_dscl = true; 215 + } else { 216 + REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 3); 217 + } 218 + } 211 219 } 212 220 } 213 221
+14
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
··· 494 494 int bypass_state; 495 495 struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); 496 496 497 + if (dpp_base->deferred_reg_writes.bits.disable_dscl) { 498 + REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 3); 499 + dpp_base->deferred_reg_writes.bits.disable_dscl = false; 500 + } 501 + 502 + if (dpp_base->deferred_reg_writes.bits.disable_gamcor) { 503 + REG_GET(CM_GAMCOR_CONTROL, CM_GAMCOR_MODE_CURRENT, &bypass_state); 504 + if (bypass_state == 0) { // only program if bypass was latched 505 + REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, 3); 506 + } else 507 + ASSERT(0); // LUT select was updated again before vupdate 508 + dpp_base->deferred_reg_writes.bits.disable_gamcor = false; 509 + } 510 + 497 511 if (dpp_base->deferred_reg_writes.bits.disable_blnd_lut) { 498 512 REG_GET(CM_BLNDGAM_CONTROL, CM_BLNDGAM_MODE_CURRENT, &bypass_state); 499 513 if (bypass_state == 0) { // only program if bypass was latched
+6 -2
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c
··· 136 136 struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); 137 137 138 138 if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) { 139 - REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, power_on ? 0 : 3); 140 - if (power_on) 139 + if (power_on) { 140 + REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, 0); 141 141 REG_WAIT(CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, 0, 1, 5); 142 + } else { 143 + dpp_base->ctx->dc->optimized_required = true; 144 + dpp_base->deferred_reg_writes.bits.disable_gamcor = true; 145 + } 142 146 } else 143 147 REG_SET(CM_MEM_PWR_CTRL, 0, 144 148 GAMCOR_MEM_PWR_DIS, power_on == true ? 0:1);
+2
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
··· 2460 2460 2461 2461 dc->cap_funcs = cap_funcs; 2462 2462 2463 + dc->dcn_ip->max_num_dpp = dcn3_1_ip.max_num_dpp; 2464 + 2463 2465 DC_FP_END(); 2464 2466 2465 2467 return true;
+2
drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
··· 34 34 bool disable_blnd_lut:1; 35 35 bool disable_3dlut:1; 36 36 bool disable_shaper:1; 37 + bool disable_gamcor:1; 38 + bool disable_dscl:1; 37 39 } bits; 38 40 uint32_t raw; 39 41 };