diff options
| author | Dominik Kaszewski <dominik.kaszewski@amd.com> | 2025-11-26 15:00:44 +0300 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2026-01-06 00:59:58 +0300 |
| commit | 5ad5b0b7845c973bdec30ea8d486add9cdfdc543 (patch) | |
| tree | c141078c699a5bd7ad47ad06f20f75a3f4868df3 | |
| parent | fd3fece04db80c8877361bf4c9f59521ce457be0 (diff) | |
| download | linux-5ad5b0b7845c973bdec30ea8d486add9cdfdc543.tar.xz | |
drm/amd/display: Fix and reenable UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL
[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 <nicholas.kazlauskas@amd.com>
Signed-off-by: Dominik Kaszewski <dominik.kaszewski@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
| -rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc.c | 80 |
1 files 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: |
