diff options
author | Alvin Lee <alvin.lee2@amd.com> | 2024-02-07 22:00:10 +0300 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2024-02-22 18:24:05 +0300 |
commit | d2dea1f1403854d921986217420617d5913a51c9 (patch) | |
tree | 9c36867ca4fcfab5adcb14c8a7270593e15cf46a /drivers | |
parent | 7d1e9d0369e4d45738d4b905c3ec92f76d7f91e6 (diff) | |
download | linux-d2dea1f1403854d921986217420617d5913a51c9.tar.xz |
drm/amd/display: Generalize new minimal transition path
Previously the new minimal transition path was only used for windowed
MPO + ODM for plane scaling updates. However, we want to generalize the
transition for all cases whenever a non-seamless transition is detected
(such as for MPO -> SubVP + MPC).
To make this change we add pointers in the plane state, stream, and
pointers in the stream state to the dc_scratch state and backup and
restore these so the minimal transition can take place successfully.
Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
Acked-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc.c | 146 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/inc/core_types.h | 31 |
2 files changed, 77 insertions, 100 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4d5194293dbd..5211c1c0f3c0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2032,7 +2032,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c return result; } -static bool commit_minimal_transition_state(struct dc *dc, +static bool commit_minimal_transition_state_legacy(struct dc *dc, struct dc_state *transition_base_context); /** @@ -2098,7 +2098,7 @@ enum dc_status dc_commit_streams(struct dc *dc, } if (handle_exit_odm2to1) - res = commit_minimal_transition_state(dc, dc->current_state); + res = commit_minimal_transition_state_legacy(dc, dc->current_state); context = dc_state_create_current_copy(dc); if (!context) @@ -2952,8 +2952,8 @@ static void copy_stream_update_to_stream(struct dc *dc, } } -static void backup_plane_states_for_stream( - struct dc_plane_state plane_states[MAX_SURFACE_NUM], +static void backup_planes_and_stream_state( + struct dc_scratch_space *scratch, struct dc_stream_state *stream) { int i; @@ -2962,12 +2962,20 @@ static void backup_plane_states_for_stream( if (!status) return; - for (i = 0; i < status->plane_count; i++) - plane_states[i] = *status->plane_states[i]; + for (i = 0; i < status->plane_count; i++) { + scratch->plane_states[i] = *status->plane_states[i]; + scratch->gamma_correction[i] = *status->plane_states[i]->gamma_correction; + scratch->in_transfer_func[i] = *status->plane_states[i]->in_transfer_func; + scratch->lut3d_func[i] = *status->plane_states[i]->lut3d_func; + scratch->in_shaper_func[i] = *status->plane_states[i]->in_shaper_func; + scratch->blend_tf[i] = *status->plane_states[i]->blend_tf; + } + scratch->stream_state = *stream; + scratch->out_transfer_func = *stream->out_transfer_func; } -static void restore_plane_states_for_stream( - struct dc_plane_state plane_states[MAX_SURFACE_NUM], +static void restore_planes_and_stream_state( + struct dc_scratch_space *scratch, struct dc_stream_state *stream) { int i; @@ -2976,8 +2984,16 @@ static void restore_plane_states_for_stream( if (!status) return; - for (i = 0; i < status->plane_count; i++) - *status->plane_states[i] = plane_states[i]; + for (i = 0; i < status->plane_count; i++) { + *status->plane_states[i] = scratch->plane_states[i]; + *status->plane_states[i]->gamma_correction = scratch->gamma_correction[i]; + *status->plane_states[i]->in_transfer_func = scratch->in_transfer_func[i]; + *status->plane_states[i]->lut3d_func = scratch->lut3d_func[i]; + *status->plane_states[i]->in_shaper_func = scratch->in_shaper_func[i]; + *status->plane_states[i]->blend_tf = scratch->blend_tf[i]; + } + *stream = scratch->stream_state; + *stream->out_transfer_func = scratch->out_transfer_func; } static bool update_planes_and_stream_state(struct dc *dc, @@ -3003,7 +3019,7 @@ static bool update_planes_and_stream_state(struct dc *dc, } context = dc->current_state; - backup_plane_states_for_stream(dc->current_state->scratch.plane_states, stream); + backup_planes_and_stream_state(&dc->current_state->scratch, stream); update_type = dc_check_update_surfaces_for_stream( dc, srf_updates, surface_count, stream_update, stream_status); @@ -3103,7 +3119,7 @@ static bool update_planes_and_stream_state(struct dc *dc, *new_context = context; *new_update_type = update_type; - backup_plane_states_for_stream(context->scratch.plane_states, stream); + backup_planes_and_stream_state(&context->scratch, stream); return true; @@ -4047,7 +4063,23 @@ static struct dc_state *create_minimal_transition_state(struct dc *dc, return minimal_transition_context; } -static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc, + +/** + * commit_minimal_transition_state - Commit a minimal state based on current or new context + * + * @dc: DC structure, used to get the current state + * @context: New context + * @stream: Stream getting the update for the flip + * + * The function takes in current state and new state and determine a minimal transition state + * as the intermediate step which could make the transition between current and new states + * seamless. If found, it will commit the minimal transition state and update current state to + * this minimal transition state and return true, if not, it will return false. + * + * Return: + * Return True if the minimal transition succeeded, false otherwise + */ +static bool commit_minimal_transition_state(struct dc *dc, struct dc_state *context, struct dc_stream_state *stream) { @@ -4056,12 +4088,6 @@ static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc, struct pipe_split_policy_backup policy; /* commit based on new context */ - /* Since all phantom pipes are removed in full validation, - * we have to save and restore the subvp/mall config when - * we do a minimal transition since the flags marking the - * pipe as subvp/phantom will be cleared (dc copy constructor - * creates a shallow copy). - */ minimal_transition_context = create_minimal_transition_state(dc, context, &policy); if (minimal_transition_context) { @@ -4078,7 +4104,7 @@ static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc, if (!success) { /* commit based on current context */ - restore_plane_states_for_stream(dc->current_state->scratch.plane_states, stream); + restore_planes_and_stream_state(&dc->current_state->scratch, stream); minimal_transition_context = create_minimal_transition_state(dc, dc->current_state, &policy); if (minimal_transition_context) { @@ -4091,7 +4117,7 @@ static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc, } release_minimal_transition_state(dc, minimal_transition_context, &policy); } - restore_plane_states_for_stream(context->scratch.plane_states, stream); + restore_planes_and_stream_state(&context->scratch, stream); } ASSERT(success); @@ -4099,7 +4125,7 @@ static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc, } /** - * commit_minimal_transition_state - Create a transition pipe split state + * commit_minimal_transition_state_legacy - Create a transition pipe split state * * @dc: Used to get the current state status * @transition_base_context: New transition state @@ -4116,7 +4142,7 @@ static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc, * Return: * Return false if something is wrong in the transition state. */ -static bool commit_minimal_transition_state(struct dc *dc, +static bool commit_minimal_transition_state_legacy(struct dc *dc, struct dc_state *transition_base_context) { struct dc_state *transition_context; @@ -4354,53 +4380,6 @@ static bool fast_update_only(struct dc *dc, && !full_update_required(dc, srf_updates, surface_count, stream_update, stream); } -static bool should_commit_minimal_transition_for_windowed_mpo_odm(struct dc *dc, - struct dc_stream_state *stream, - struct dc_state *context) -{ - struct pipe_ctx *cur_pipe, *new_pipe; - bool cur_is_odm_in_use, new_is_odm_in_use; - struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream); - struct dc_stream_status *new_stream_status = stream_get_status(context, stream); - - if (!dc->debug.enable_single_display_2to1_odm_policy || - !dc->config.enable_windowed_mpo_odm) - /* skip the check if windowed MPO ODM or dynamic ODM is turned - * off. - */ - return false; - - if (context == dc->current_state) - /* skip the check for fast update */ - return false; - - if (new_stream_status->plane_count != cur_stream_status->plane_count) - /* plane count changed, not a plane scaling update so not the - * case we are looking for - */ - return false; - - cur_pipe = resource_get_otg_master_for_stream(&dc->current_state->res_ctx, stream); - new_pipe = resource_get_otg_master_for_stream(&context->res_ctx, stream); - if (!cur_pipe || !new_pipe) - return false; - cur_is_odm_in_use = resource_get_odm_slice_count(cur_pipe) > 1; - new_is_odm_in_use = resource_get_odm_slice_count(new_pipe) > 1; - if (cur_is_odm_in_use == new_is_odm_in_use) - /* ODM state isn't changed, not the case we are looking for */ - return false; - - if (dc->hwss.is_pipe_topology_transition_seamless && - dc->hwss.is_pipe_topology_transition_seamless( - dc, dc->current_state, context)) - /* transition can be achieved without the need for committing - * minimal transition state first - */ - return false; - - return true; -} - bool dc_update_planes_and_stream(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, struct dc_stream_state *stream, @@ -4433,7 +4412,7 @@ bool dc_update_planes_and_stream(struct dc *dc, /* on plane addition, minimal state is the current one */ if (force_minimal_pipe_splitting && is_plane_addition && - !commit_minimal_transition_state(dc, dc->current_state)) + !commit_minimal_transition_state_legacy(dc, dc->current_state)) return false; if (!update_planes_and_stream_state( @@ -4448,32 +4427,19 @@ bool dc_update_planes_and_stream(struct dc *dc, /* on plane removal, minimal state is the new one */ if (force_minimal_pipe_splitting && !is_plane_addition) { - /* Since all phantom pipes are removed in full validation, - * we have to save and restore the subvp/mall config when - * we do a minimal transition since the flags marking the - * pipe as subvp/phantom will be cleared (dc copy constructor - * creates a shallow copy). - */ - if (!commit_minimal_transition_state(dc, context)) { + if (!commit_minimal_transition_state_legacy(dc, context)) { dc_state_release(context); return false; } update_type = UPDATE_TYPE_FULL; } - /* when windowed MPO ODM is supported, we need to handle a special case - * where we can transition between ODM combine and MPC combine due to - * plane scaling update. This transition will require us to commit - * minimal transition state. The condition to trigger this update can't - * be predicted by could_mpcc_tree_change_for_active_pipes because we - * can only determine it after DML validation. Therefore we can't rely - * on the existing commit minimal transition state sequence. Instead - * we have to add additional handling here to handle this transition - * with its own special sequence. - */ - if (should_commit_minimal_transition_for_windowed_mpo_odm(dc, stream, context)) - commit_minimal_transition_state_for_windowed_mpo_odm(dc, + if (dc->hwss.is_pipe_topology_transition_seamless && + !dc->hwss.is_pipe_topology_transition_seamless( + dc, dc->current_state, context)) { + commit_minimal_transition_state(dc, context, stream); + } update_seamless_boot_flags(dc, context, surface_count, stream); if (is_fast_update_only && !dc->debug.enable_legacy_fast_update) { commit_planes_for_stream_fast(dc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 3a6bf77a6873..b1b72e688f74 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -522,6 +522,25 @@ struct dc_dmub_cmd { enum dm_dmub_wait_type wait_type; }; +struct dc_scratch_space { + /* used to temporarily backup plane states of a stream during + * dc update. The reason is that plane states are overwritten + * with surface updates in dc update. Once they are overwritten + * current state is no longer valid. We want to temporarily + * store current value in plane states so we can still recover + * a valid current state during dc update. + */ + struct dc_plane_state plane_states[MAX_SURFACE_NUM]; + struct dc_gamma gamma_correction[MAX_SURFACE_NUM]; + struct dc_transfer_func in_transfer_func[MAX_SURFACE_NUM]; + struct dc_3dlut lut3d_func[MAX_SURFACE_NUM]; + struct dc_transfer_func in_shaper_func[MAX_SURFACE_NUM]; + struct dc_transfer_func blend_tf[MAX_SURFACE_NUM]; + + struct dc_stream_state stream_state; + struct dc_transfer_func out_transfer_func; +}; + /** * struct dc_state - The full description of a state requested by users */ @@ -604,16 +623,8 @@ struct dc_state { unsigned int stutter_period_us; } perf_params; - struct { - /* used to temporarily backup plane states of a stream during - * dc update. The reason is that plane states are overwritten - * with surface updates in dc update. Once they are overwritten - * current state is no longer valid. We want to temporarily - * store current value in plane states so we can still recover - * a valid current state during dc update. - */ - struct dc_plane_state plane_states[MAX_SURFACE_NUM]; - } scratch; + + struct dc_scratch_space scratch; }; struct replay_context { |