mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-24 11:34:50 +08:00
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>
This commit is contained in:
parent
7d1e9d0369
commit
d2dea1f140
@ -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,
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user