Hey,

Just to let you know that I tested this commit: https://gitlab.freedesktop.org/agd5f/linux/-/commit/85c4669b1834 and the regression is solved.

Thanks,

Melissa

On 12/01/2026 10:58, Kaszewski, Dominik wrote:
[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:

Reply via email to