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

drm/amd/display: Fix issue with dynamic bpp change for DCN3x

Why:
Screen sometimes would have artifacts or blink once at the time when bpp
is dynamically changed.

How:
1. Changed to update PPS infopacket in frame mode instead of immediate mode
since other updates for bpp change are double-buffered.
2. Changed double-buffering enablement programming for DCN30 as advised by
ASIC team

Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Bing Guo <Bing.Guo@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Guo, Bing and committed by
Alex Deucher
253a5591 808643ea

+204 -97
+2 -2
drivers/gpu/drm/amd/display/dc/core/dc_link.c
··· 3554 3554 3555 3555 /* Set DPS PPS SDP (AKA "info frames") */ 3556 3556 if (pipe_ctx->stream->timing.flags.DSC) { 3557 - dp_set_dsc_pps_sdp(pipe_ctx, true); 3557 + dp_set_dsc_pps_sdp(pipe_ctx, true, true); 3558 3558 } 3559 3559 3560 3560 /* Allocate Payload */ ··· 3803 3803 if (dc_is_dp_signal(pipe_ctx->stream->signal) || 3804 3804 dc_is_virtual_signal(pipe_ctx->stream->signal)) { 3805 3805 dp_set_dsc_on_rx(pipe_ctx, true); 3806 - dp_set_dsc_pps_sdp(pipe_ctx, true); 3806 + dp_set_dsc_pps_sdp(pipe_ctx, true, true); 3807 3807 } 3808 3808 } 3809 3809
+2 -1
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
··· 292 292 293 293 static void enc2_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, 294 294 bool enable, 295 - uint8_t *dsc_packed_pps) 295 + uint8_t *dsc_packed_pps, 296 + bool immediate_update) 296 297 { 297 298 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 298 299
+12 -6
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c
··· 77 77 enc1->base.vpg->funcs->update_generic_info_packet( 78 78 enc1->base.vpg, 79 79 packet_index, 80 - info_packet); 80 + info_packet, 81 + true); 81 82 82 83 /* enable transmission of packet(s) - 83 84 * packet transmission begins on the next frame */ ··· 336 335 337 336 static void enc3_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, 338 337 bool enable, 339 - uint8_t *dsc_packed_pps) 338 + uint8_t *dsc_packed_pps, 339 + bool immediate_update) 340 340 { 341 341 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 342 342 ··· 367 365 enc1->base.vpg->funcs->update_generic_info_packet( 368 366 enc1->base.vpg, 369 367 11 + i, 370 - &pps_sdp); 368 + &pps_sdp, 369 + immediate_update); 371 370 } 372 371 373 372 /* SW should make sure VBID[6] update line number is bigger ··· 432 429 enc->vpg->funcs->update_generic_info_packet( 433 430 enc->vpg, 434 431 0, /* packetIndex */ 435 - &info_frame->vsc); 432 + &info_frame->vsc, 433 + true); 436 434 } 437 435 if (info_frame->spd.valid) { 438 436 enc->vpg->funcs->update_generic_info_packet( 439 437 enc->vpg, 440 438 2, /* packetIndex */ 441 - &info_frame->spd); 439 + &info_frame->spd, 440 + true); 442 441 } 443 442 if (info_frame->hdrsmd.valid) { 444 443 enc->vpg->funcs->update_generic_info_packet( 445 444 enc->vpg, 446 445 3, /* packetIndex */ 447 - &info_frame->hdrsmd); 446 + &info_frame->hdrsmd, 447 + true); 448 448 } 449 449 /* packetIndex 4 is used for send immediate sdp message, and please 450 450 * use other packetIndex (such as 5,6) for other info packet
+12 -5
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
··· 73 73 OTG_H_BLANK_END, &h_blank_end); 74 74 75 75 REG_UPDATE_2(OTG_GLOBAL_CONTROL1, 76 - MASTER_UPDATE_LOCK_DB_START_Y, v_blank_start, 77 - MASTER_UPDATE_LOCK_DB_END_Y, v_blank_end); 76 + MASTER_UPDATE_LOCK_DB_START_Y, v_blank_start - 1, 77 + MASTER_UPDATE_LOCK_DB_END_Y, v_blank_start); 78 78 REG_UPDATE_2(OTG_GLOBAL_CONTROL4, 79 - DIG_UPDATE_POSITION_X, 20, 80 - DIG_UPDATE_POSITION_Y, v_blank_start); 79 + DIG_UPDATE_POSITION_X, h_blank_start - 180 - 1, 80 + DIG_UPDATE_POSITION_Y, v_blank_start - 1); 81 + // there is a DIG_UPDATE_VCOUNT_MODE and it is 0. 82 + 81 83 REG_UPDATE_3(OTG_GLOBAL_CONTROL0, 82 84 MASTER_UPDATE_LOCK_DB_START_X, h_blank_start - 200 - 1, 83 - MASTER_UPDATE_LOCK_DB_END_X, h_blank_end, 85 + MASTER_UPDATE_LOCK_DB_END_X, h_blank_start - 180, 84 86 MASTER_UPDATE_LOCK_DB_EN, 1); 85 87 REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1); 88 + 89 + REG_SET_3(OTG_VUPDATE_KEEPOUT, 0, 90 + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0, 91 + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, 100, 92 + OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); 86 93 } 87 94 88 95 void optc3_lock_doublebuffer_disable(struct timing_generator *optc)
+134 -64
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c
··· 46 46 void vpg3_update_generic_info_packet( 47 47 struct vpg *vpg, 48 48 uint32_t packet_index, 49 - const struct dc_info_packet *info_packet) 49 + const struct dc_info_packet *info_packet, 50 + bool immediate_update) 50 51 { 51 52 struct dcn30_vpg *vpg3 = DCN30_VPG_FROM_VPG(vpg); 52 53 uint32_t i; ··· 107 106 /* atomically update double-buffered GENERIC0 registers in immediate mode 108 107 * (update at next block_update when block_update_lock == 0). 109 108 */ 110 - switch (packet_index) { 111 - case 0: 112 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 113 - VPG_GENERIC0_IMMEDIATE_UPDATE, 1); 114 - break; 115 - case 1: 116 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 117 - VPG_GENERIC1_IMMEDIATE_UPDATE, 1); 118 - break; 119 - case 2: 120 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 121 - VPG_GENERIC2_IMMEDIATE_UPDATE, 1); 122 - break; 123 - case 3: 124 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 125 - VPG_GENERIC3_IMMEDIATE_UPDATE, 1); 126 - break; 127 - case 4: 128 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 129 - VPG_GENERIC4_IMMEDIATE_UPDATE, 1); 130 - break; 131 - case 5: 132 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 133 - VPG_GENERIC5_IMMEDIATE_UPDATE, 1); 134 - break; 135 - case 6: 136 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 137 - VPG_GENERIC6_IMMEDIATE_UPDATE, 1); 138 - break; 139 - case 7: 140 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 141 - VPG_GENERIC7_IMMEDIATE_UPDATE, 1); 142 - break; 143 - case 8: 144 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 145 - VPG_GENERIC8_IMMEDIATE_UPDATE, 1); 146 - break; 147 - case 9: 148 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 149 - VPG_GENERIC9_IMMEDIATE_UPDATE, 1); 150 - break; 151 - case 10: 152 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 153 - VPG_GENERIC10_IMMEDIATE_UPDATE, 1); 154 - break; 155 - case 11: 156 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 157 - VPG_GENERIC11_IMMEDIATE_UPDATE, 1); 158 - break; 159 - case 12: 160 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 161 - VPG_GENERIC12_IMMEDIATE_UPDATE, 1); 162 - break; 163 - case 13: 164 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 165 - VPG_GENERIC13_IMMEDIATE_UPDATE, 1); 166 - break; 167 - case 14: 168 - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 169 - VPG_GENERIC14_IMMEDIATE_UPDATE, 1); 170 - break; 171 - default: 172 - break; 109 + if (immediate_update) { 110 + switch (packet_index) { 111 + case 0: 112 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 113 + VPG_GENERIC0_IMMEDIATE_UPDATE, 1); 114 + break; 115 + case 1: 116 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 117 + VPG_GENERIC1_IMMEDIATE_UPDATE, 1); 118 + break; 119 + case 2: 120 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 121 + VPG_GENERIC2_IMMEDIATE_UPDATE, 1); 122 + break; 123 + case 3: 124 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 125 + VPG_GENERIC3_IMMEDIATE_UPDATE, 1); 126 + break; 127 + case 4: 128 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 129 + VPG_GENERIC4_IMMEDIATE_UPDATE, 1); 130 + break; 131 + case 5: 132 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 133 + VPG_GENERIC5_IMMEDIATE_UPDATE, 1); 134 + break; 135 + case 6: 136 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 137 + VPG_GENERIC6_IMMEDIATE_UPDATE, 1); 138 + break; 139 + case 7: 140 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 141 + VPG_GENERIC7_IMMEDIATE_UPDATE, 1); 142 + break; 143 + case 8: 144 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 145 + VPG_GENERIC8_IMMEDIATE_UPDATE, 1); 146 + break; 147 + case 9: 148 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 149 + VPG_GENERIC9_IMMEDIATE_UPDATE, 1); 150 + break; 151 + case 10: 152 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 153 + VPG_GENERIC10_IMMEDIATE_UPDATE, 1); 154 + break; 155 + case 11: 156 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 157 + VPG_GENERIC11_IMMEDIATE_UPDATE, 1); 158 + break; 159 + case 12: 160 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 161 + VPG_GENERIC12_IMMEDIATE_UPDATE, 1); 162 + break; 163 + case 13: 164 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 165 + VPG_GENERIC13_IMMEDIATE_UPDATE, 1); 166 + break; 167 + case 14: 168 + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, 169 + VPG_GENERIC14_IMMEDIATE_UPDATE, 1); 170 + break; 171 + default: 172 + break; 173 + } 174 + } else { 175 + switch (packet_index) { 176 + case 0: 177 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 178 + VPG_GENERIC0_FRAME_UPDATE, 1); 179 + break; 180 + case 1: 181 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 182 + VPG_GENERIC1_FRAME_UPDATE, 1); 183 + break; 184 + case 2: 185 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 186 + VPG_GENERIC2_FRAME_UPDATE, 1); 187 + break; 188 + case 3: 189 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 190 + VPG_GENERIC3_FRAME_UPDATE, 1); 191 + break; 192 + case 4: 193 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 194 + VPG_GENERIC4_FRAME_UPDATE, 1); 195 + break; 196 + case 5: 197 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 198 + VPG_GENERIC5_FRAME_UPDATE, 1); 199 + break; 200 + case 6: 201 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 202 + VPG_GENERIC6_FRAME_UPDATE, 1); 203 + break; 204 + case 7: 205 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 206 + VPG_GENERIC7_FRAME_UPDATE, 1); 207 + break; 208 + case 8: 209 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 210 + VPG_GENERIC8_FRAME_UPDATE, 1); 211 + break; 212 + case 9: 213 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 214 + VPG_GENERIC9_FRAME_UPDATE, 1); 215 + break; 216 + case 10: 217 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 218 + VPG_GENERIC10_FRAME_UPDATE, 1); 219 + break; 220 + case 11: 221 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 222 + VPG_GENERIC11_FRAME_UPDATE, 1); 223 + break; 224 + case 12: 225 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 226 + VPG_GENERIC12_FRAME_UPDATE, 1); 227 + break; 228 + case 13: 229 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 230 + VPG_GENERIC13_FRAME_UPDATE, 1); 231 + break; 232 + case 14: 233 + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, 234 + VPG_GENERIC14_FRAME_UPDATE, 1); 235 + break; 236 + 237 + default: 238 + break; 239 + } 240 + 173 241 } 174 242 } 175 243
+4 -2
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h
··· 138 138 void (*update_generic_info_packet)( 139 139 struct vpg *vpg, 140 140 uint32_t packet_index, 141 - const struct dc_info_packet *info_packet); 141 + const struct dc_info_packet *info_packet, 142 + bool immediate_update); 142 143 143 144 void (*vpg_poweron)( 144 145 struct vpg *vpg); ··· 164 163 void vpg3_update_generic_info_packet( 165 164 struct vpg *vpg, 166 165 uint32_t packet_index, 167 - const struct dc_info_packet *info_packet); 166 + const struct dc_info_packet *info_packet, 167 + bool immediate_update); 168 168 169 169 void vpg3_construct(struct dcn30_vpg *vpg3, 170 170 struct dc_context *ctx,
+10 -5
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c
··· 442 442 enc->vpg->funcs->update_generic_info_packet( 443 443 enc->vpg, 444 444 0, /* packetIndex */ 445 - &info_frame->vsc); 445 + &info_frame->vsc, 446 + true); 446 447 sdp_stream_enable = true; 447 448 } 448 449 if (info_frame->spd.valid) { 449 450 enc->vpg->funcs->update_generic_info_packet( 450 451 enc->vpg, 451 452 2, /* packetIndex */ 452 - &info_frame->spd); 453 + &info_frame->spd, 454 + true); 453 455 sdp_stream_enable = true; 454 456 } 455 457 if (info_frame->hdrsmd.valid) { 456 458 enc->vpg->funcs->update_generic_info_packet( 457 459 enc->vpg, 458 460 3, /* packetIndex */ 459 - &info_frame->hdrsmd); 461 + &info_frame->hdrsmd, 462 + true); 460 463 sdp_stream_enable = true; 461 464 } 462 465 /* enable/disable transmission of packet(s). ··· 523 520 static void dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet( 524 521 struct hpo_dp_stream_encoder *enc, 525 522 bool enable, 526 - uint8_t *dsc_packed_pps) 523 + uint8_t *dsc_packed_pps, 524 + bool immediate_update) 527 525 { 528 526 struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); 529 527 ··· 548 544 enc3->base.vpg->funcs->update_generic_info_packet( 549 545 enc3->base.vpg, 550 546 11 + i, 551 - &pps_sdp); 547 + &pps_sdp, 548 + immediate_update); 552 549 } 553 550 554 551 /* SW should make sure VBID[6] update line number is bigger
+4 -2
drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
··· 229 229 230 230 void (*dp_set_dsc_pps_info_packet)(struct stream_encoder *enc, 231 231 bool enable, 232 - uint8_t *dsc_packed_pps); 232 + uint8_t *dsc_packed_pps, 233 + bool immediate_update); 233 234 234 235 void (*set_dynamic_metadata)(struct stream_encoder *enc, 235 236 bool enable, ··· 299 298 void (*dp_set_dsc_pps_info_packet)( 300 299 struct hpo_dp_stream_encoder *enc, 301 300 bool enable, 302 - uint8_t *dsc_packed_pps); 301 + uint8_t *dsc_packed_pps, 302 + bool immediate_update); 303 303 304 304 void (*map_stream_to_link)( 305 305 struct hpo_dp_stream_encoder *enc,
+2 -1
drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c
··· 104 104 static void virtual_stream_encoder_set_dsc_pps_info_packet( 105 105 struct stream_encoder *enc, 106 106 bool enable, 107 - uint8_t *dsc_packed_pps) 107 + uint8_t *dsc_packed_pps, 108 + bool immediate_update) 108 109 {} 109 110 110 111 static const struct stream_encoder_funcs virtual_str_enc_funcs = {