summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/core/dc.c
diff options
context:
space:
mode:
authorWenjing Liu <wenjing.liu@amd.com>2024-02-20 14:54:46 -0500
committerAlex Deucher <alexander.deucher@amd.com>2024-03-20 13:38:13 -0400
commitb04c21abe21ff56f7a4da8a53c2779575192ffaf (patch)
tree8925fa21d26e0798937d77b835ef98a16b28aafb /drivers/gpu/drm/amd/display/dc/core/dc.c
parent0ba7ad7e42ea9d38c39d98137af3ad6a18f2ee8f (diff)
drm/amd/display: skip forcing odm in minimal transition
[why] In minial transitions state, ODM combine shouldn't be forced as it will make transition non seamless. The force ODM debug option is to control the end result not the intermediate transition. So we can temporarily disable ODM forcing when committing minimal transition state. [how] Backup stream ODM forcing option and clear it in minimal transition state. Once minimal transition state is released, we will restore the original debug option back. Reviewed-by: Samson Tam <samson.tam@amd.com> Acked-by: Wayne Lin <wayne.lin@amd.com> Signed-off-by: Wenjing Liu <wenjing.liu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core/dc.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c97
1 files changed, 65 insertions, 32 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 6a65aa623e8a..0757207e7179 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -4158,55 +4158,88 @@ struct pipe_split_policy_backup {
bool dynamic_odm_policy;
bool subvp_policy;
enum pipe_split_policy mpc_policy;
+ char force_odm[MAX_PIPES];
};
-static void release_minimal_transition_state(struct dc *dc,
- struct dc_state *context, struct pipe_split_policy_backup *policy)
+static void backup_and_set_minimal_pipe_split_policy(struct dc *dc,
+ struct dc_state *context,
+ struct pipe_split_policy_backup *policy)
{
- dc_state_release(context);
- /* restore previous pipe split and odm policy */
+ int i;
+
+ if (!dc->config.is_vmin_only_asic) {
+ policy->mpc_policy = dc->debug.pipe_split_policy;
+ dc->debug.pipe_split_policy = MPC_SPLIT_AVOID;
+ }
+ policy->dynamic_odm_policy = dc->debug.enable_single_display_2to1_odm_policy;
+ dc->debug.enable_single_display_2to1_odm_policy = false;
+ policy->subvp_policy = dc->debug.force_disable_subvp;
+ dc->debug.force_disable_subvp = true;
+ for (i = 0; i < context->stream_count; i++) {
+ policy->force_odm[i] = context->streams[i]->debug.force_odm_combine_segments;
+ context->streams[i]->debug.force_odm_combine_segments = 0;
+ }
+}
+
+static void restore_minimal_pipe_split_policy(struct dc *dc,
+ struct dc_state *context,
+ struct pipe_split_policy_backup *policy)
+{
+ uint8_t i;
+
if (!dc->config.is_vmin_only_asic)
dc->debug.pipe_split_policy = policy->mpc_policy;
- dc->debug.enable_single_display_2to1_odm_policy = policy->dynamic_odm_policy;
+ dc->debug.enable_single_display_2to1_odm_policy =
+ policy->dynamic_odm_policy;
dc->debug.force_disable_subvp = policy->subvp_policy;
+ for (i = 0; i < context->stream_count; i++)
+ context->streams[i]->debug.force_odm_combine_segments = policy->force_odm[i];
+}
+
+static void release_minimal_transition_state(struct dc *dc,
+ struct dc_state *minimal_transition_context,
+ struct dc_state *base_context,
+ struct pipe_split_policy_backup *policy)
+{
+ restore_minimal_pipe_split_policy(dc, base_context, policy);
+ dc_state_release(minimal_transition_context);
+ /* restore previous pipe split and odm policy */
+}
+
+static void force_vsync_flip_in_minimal_transition_context(struct dc_state *context)
+{
+ uint8_t i;
+ int j;
+ struct dc_stream_status *stream_status;
+
+ for (i = 0; i < context->stream_count; i++) {
+ stream_status = &context->stream_status[i];
+
+ for (j = 0; j < stream_status->plane_count; j++)
+ stream_status->plane_states[j]->flip_immediate = false;
+ }
}
static struct dc_state *create_minimal_transition_state(struct dc *dc,
struct dc_state *base_context, struct pipe_split_policy_backup *policy)
{
struct dc_state *minimal_transition_context = NULL;
- unsigned int i, j;
minimal_transition_context = dc_state_create_copy(base_context);
if (!minimal_transition_context)
return NULL;
- if (!dc->config.is_vmin_only_asic) {
- policy->mpc_policy = dc->debug.pipe_split_policy;
- dc->debug.pipe_split_policy = MPC_SPLIT_AVOID;
- }
- policy->dynamic_odm_policy = dc->debug.enable_single_display_2to1_odm_policy;
- dc->debug.enable_single_display_2to1_odm_policy = false;
- policy->subvp_policy = dc->debug.force_disable_subvp;
- dc->debug.force_disable_subvp = true;
-
+ backup_and_set_minimal_pipe_split_policy(dc, base_context, policy);
/* commit minimal state */
if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context, false)) {
- for (i = 0; i < minimal_transition_context->stream_count; i++) {
- struct dc_stream_status *stream_status = &minimal_transition_context->stream_status[i];
-
- for (j = 0; j < stream_status->plane_count; j++) {
- struct dc_plane_state *plane_state = stream_status->plane_states[j];
-
- /* force vsync flip when reconfiguring pipes to prevent underflow
- * and corruption
- */
- plane_state->flip_immediate = false;
- }
- }
+ /* prevent underflow and corruption when reconfiguring pipes */
+ force_vsync_flip_in_minimal_transition_context(minimal_transition_context);
} else {
- /* this should never happen */
- release_minimal_transition_state(dc, minimal_transition_context, policy);
+ /*
+ * This should never happen, minimal transition state should
+ * always be validated first before adding pipe split features.
+ */
+ release_minimal_transition_state(dc, minimal_transition_context, base_context, policy);
BREAK_TO_DEBUGGER();
minimal_transition_context = NULL;
}
@@ -4293,7 +4326,7 @@ static bool commit_minimal_transition_based_on_new_context(struct dc *dc,
success = true;
}
release_minimal_transition_state(
- dc, intermediate_context, &policy);
+ dc, intermediate_context, new_context, &policy);
}
return success;
}
@@ -4339,7 +4372,7 @@ static bool commit_minimal_transition_based_on_current_context(struct dc *dc,
success = true;
}
release_minimal_transition_state(dc, intermediate_context,
- &policy);
+ dc->current_state, &policy);
}
/*
* Restore stream and plane states back to the values associated with
@@ -4466,7 +4499,7 @@ static bool commit_minimal_transition_state(struct dc *dc,
transition_base_context, &policy);
if (transition_context) {
ret = dc_commit_state_no_check(dc, transition_context);
- release_minimal_transition_state(dc, transition_context, &policy);
+ release_minimal_transition_state(dc, transition_context, transition_base_context, &policy);
}
if (ret != DC_OK) {