[AMD Official Use Only - AMD Internal Distribution Only] Hi Melissa,
Thank you for letting me know, I will look into this regression. Best regards, Dominik Kaszewski Senior Software Engineer SW - Display NPI -----Original Message----- From: Melissa Wen <[email protected]> Sent: Monday, January 12, 2026 12:44 PM To: Chen, Chen-Yu <[email protected]>; [email protected] Cc: Wentland, Harry <[email protected]>; Li, Sun peng (Leo) <[email protected]>; Pillai, Aurabindo <[email protected]>; Li, Roman <[email protected]>; Lin, Wayne <[email protected]>; Chung, ChiaHsuan (Tom) <[email protected]>; Zuo, Jerry <[email protected]>; Wheeler, Daniel <[email protected]>; Wu, Ray <[email protected]>; LIPSKI, IVAN <[email protected]>; Hung, Alex <[email protected]>; Kaszewski, Dominik <[email protected]>; Kazlauskas, Nicholas <[email protected]> Subject: Re: [PATCH 06/16] drm/amd/display: Fix and reenable UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL On 06/01/2026 09:18, Melissa Wen wrote: > Hi, > > This change reintroduce some glitches/screen corruption on DCN321 with > gamescope and a 4k@120Hz display, when transitioning from multiple > planes (primary + overlay, and pipe split) to single plane (no pipe > split). > We see small white artifacts near the cursor in its first appearance > on the screen after boot, and eventually a corrupted,colorful strip > appears in "fast" transitions between single plane -> multi-plane -> > single plane, for example, when moving the cursor (single plane), > click on the Steam menu (multi planes) and moving the cursor just > after (single plane). > > The problem was previously solved by commit 24ddca9a3af1 > ("drm/amd/display: Defer transitions from minimal state to final > state") [1] and reintroduced again by this patch here, i.e., I don't > see the issue if I revert this commit here in current asdn. > Also, the issue isn't reproducible if you disable SubVP. Just to reinforce that the situation I describe here affects this issue in a similar way: - https://gitlab.freedesktop.org/drm/amd/-/issues/3614 ("[DCN32/7900XTX] when VRR is active + an overlay plane is in use, using a hardware cursor in gamescope-session causes artifacts during transition out of scan-out") Melissa > > [1] https://gitlab.freedesktop.org/agd5f/linux/-/commit/24ddca9a3af1 > > Best Regards, > > Melissa > > On 16/12/2025 06:56, Chenyu Chen wrote: >> From: Dominik Kaszewski <[email protected]> >> >> [Why] >> Reenable new split implementation, previously partially reverted due >> to issues with ODM on high-bandwidth displays 4k144Hz, resulting in a >> corrupted gray screen. >> >> Minimal flows require two separate commits, with extra intermediate >> commit to enable seamless transitions, each followed by a swap. Since >> new design requires commit to be run in execute and swap in cleanup >> stage, an attempt was made to reorder them from CSCS >> (Commit-Swap-Commit-Swap) >> to CCSS (Commit-Commit-Swap-Swap). Not only is this not viable, but >> was implemented incorrectly as CCS, one swap missing. >> >> [How] >> * Change UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW/CURRENT to execute >> and cleanup one commit, then run UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS, >> which closely matches old implementation where minimal flows fall >> back to seamless. >> * Fix uninitialized variable error. >> >> Reviewed-by: Nicholas Kazlauskas <[email protected]> >> Signed-off-by: Dominik Kaszewski <[email protected]> >> Signed-off-by: Chenyu Chen <[email protected]> >> --- >> drivers/gpu/drm/amd/display/dc/core/dc.c | 80 >> ++++++++++++------------ >> 1 file changed, 39 insertions(+), 41 deletions(-) >> >> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c >> b/drivers/gpu/drm/amd/display/dc/core/dc.c >> index 1be5c1c15798..57f6a4c8afff 100644 >> --- a/drivers/gpu/drm/amd/display/dc/core/dc.c >> +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c >> @@ -784,7 +784,7 @@ bool dc_stream_get_crc(struct dc *dc, struct >> dc_stream_state *stream, uint8_t id >> uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) >> { >> int i; >> - struct pipe_ctx *pipe; >> + struct pipe_ctx *pipe = NULL; >> struct timing_generator *tg; >> dc_exit_ips_for_hw_access(dc); @@ -5437,35 +5437,23 @@ bool >> dc_update_planes_and_stream(struct dc *dc, >> struct dc_stream_state *stream, >> struct dc_stream_update *stream_update) >> { >> - bool ret = false; >> + struct dc_update_scratch_space *scratch = >> dc_update_planes_and_stream_init( >> + dc, >> + srf_updates, >> + surface_count, >> + stream, >> + stream_update >> + ); >> + bool more = true; >> - dc_exit_ips_for_hw_access(dc); >> - /* >> - * update planes and stream version 3 separates FULL and FAST >> updates >> - * to their own sequences. It aims to clean up frequent checks >> for >> - * update type resulting unnecessary branching in logic flow. It >> also >> - * adds a new commit minimal transition sequence, which detects >> the need >> - * for minimal transition based on the actual comparison of >> current and >> - * new states instead of "predicting" it based on per feature >> software >> - * policy.i.e could_mpcc_tree_change_for_active_pipes. The new >> commit >> - * minimal transition sequence is made universal to any power >> saving >> - * features that would use extra free pipes such as Dynamic >> ODM/MPC >> - * Combine, MPO or SubVp. Therefore there is no longer a need to >> - * specially handle compatibility problems with transitions >> among those >> - * features as they are now transparent to the new sequence. >> - */ >> - if (dc->ctx->dce_version >= DCN_VERSION_4_01 || >> dc->ctx->dce_version == DCN_VERSION_3_2 || >> - dc->ctx->dce_version == DCN_VERSION_3_21) >> - ret = update_planes_and_stream_v3(dc, srf_updates, >> - surface_count, stream, stream_update); >> - else >> - ret = update_planes_and_stream_v2(dc, srf_updates, >> - surface_count, stream, stream_update); >> - if (ret && (dc->ctx->dce_version >= DCN_VERSION_3_2 || >> - dc->ctx->dce_version == DCN_VERSION_3_01)) >> - clear_update_flags(srf_updates, surface_count, stream); >> + while (more) { >> + if (!dc_update_planes_and_stream_prepare(scratch)) >> + return false; >> - return ret; >> + dc_update_planes_and_stream_execute(scratch); >> + more = dc_update_planes_and_stream_cleanup(scratch); >> + } >> + return true; >> } >> void dc_commit_updates_for_stream(struct dc *dc, @@ -7241,7 >> +7229,7 @@ static bool update_planes_and_stream_cleanup_v2( >> return false; >> } >> -static void update_planes_and_stream_cleanup_v3_intermediate( >> +static void update_planes_and_stream_cleanup_v3_release_minimal( >> struct dc_update_scratch_space *scratch, >> bool backup >> ); >> @@ -7262,6 +7250,10 @@ static bool >> update_planes_and_stream_prepare_v3( >> struct dc_update_scratch_space *scratch >> ) >> { >> + if (scratch->flow == UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS) { >> + return true; >> + } >> + ASSERT(scratch->flow == UPDATE_V3_FLOW_INVALID); >> dc_exit_ips_for_hw_access(scratch->dc); >> if (!update_planes_and_stream_state( @@ -7327,11 +7319,11 @@ >> static bool update_planes_and_stream_prepare_v3( >> return true; >> } >> - update_planes_and_stream_cleanup_v3_intermediate(scratch, false); >> + update_planes_and_stream_cleanup_v3_release_minimal(scratch, >> + false); >> } >> - >> restore_planes_and_stream_state(&scratch->dc->scratch.current_state, >> scratch->stream); >> scratch->backup_context = scratch->dc->current_state; >> + >> restore_planes_and_stream_state(&scratch->dc->scratch.current_state, >> scratch->stream); >> dc_state_retain(scratch->backup_context); >> scratch->intermediate_context = >> create_minimal_transition_state( >> scratch->dc, >> @@ -7347,7 +7339,7 @@ static bool >> update_planes_and_stream_prepare_v3( >> return true; >> } >> - update_planes_and_stream_cleanup_v3_intermediate(scratch, true); >> + update_planes_and_stream_cleanup_v3_release_minimal(scratch, true); >> } >> scratch->flow = UPDATE_V3_FLOW_INVALID; @@ -7398,12 +7390,10 >> @@ static void update_planes_and_stream_execute_v3( >> case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW: >> update_planes_and_stream_execute_v3_commit(scratch, false, >> true); >> - update_planes_and_stream_execute_v3_commit(scratch, false, >> false); >> break; >> case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT: >> update_planes_and_stream_execute_v3_commit(scratch, true, >> true); >> - update_planes_and_stream_execute_v3_commit(scratch, false, >> false); >> break; >> case UPDATE_V3_FLOW_INVALID: >> @@ -7419,7 +7409,7 @@ static void >> update_planes_and_stream_cleanup_v3_new_context( >> swap_and_release_current_context(scratch->dc, >> scratch->new_context, scratch->stream); >> } >> -static void update_planes_and_stream_cleanup_v3_intermediate( >> +static void update_planes_and_stream_cleanup_v3_release_minimal( >> struct dc_update_scratch_space *scratch, >> bool backup >> ) >> @@ -7432,6 +7422,16 @@ static void >> update_planes_and_stream_cleanup_v3_intermediate( >> ); >> } >> +static void update_planes_and_stream_cleanup_v3_intermediate( >> + struct dc_update_scratch_space *scratch, >> + bool backup >> +) >> +{ >> + swap_and_release_current_context(scratch->dc, >> scratch->intermediate_context, scratch->stream); >> + dc_state_retain(scratch->dc->current_state); >> + update_planes_and_stream_cleanup_v3_release_minimal(scratch, >> +backup); } >> + >> static bool update_planes_and_stream_cleanup_v3( >> struct dc_update_scratch_space *scratch >> ) >> @@ -7448,17 +7448,15 @@ static bool >> update_planes_and_stream_cleanup_v3( >> case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW: >> update_planes_and_stream_cleanup_v3_intermediate(scratch, false); >> - update_planes_and_stream_cleanup_v3_new_context(scratch); >> - break; >> + scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS; >> + return true; >> case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT: >> - swap_and_release_current_context(scratch->dc, >> scratch->intermediate_context, scratch->stream); >> - dc_state_retain(scratch->dc->current_state); >> update_planes_and_stream_cleanup_v3_intermediate(scratch, true); >> dc_state_release(scratch->backup_context); >> restore_planes_and_stream_state(&scratch->dc->scratch.new_state, >> scratch->stream); >> - update_planes_and_stream_cleanup_v3_new_context(scratch); >> - break; >> + scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS; >> + return true; >> case UPDATE_V3_FLOW_INVALID: >> default: >
