summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/core/dc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core/dc.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c191
1 files changed, 84 insertions, 107 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 040b5c2a5..d68c83e40 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -411,12 +411,9 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
* avoid conflicting with firmware updates.
*/
if (dc->ctx->dce_version > DCE_VERSION_MAX)
- if (dc->optimized_required)
+ if (dc->optimized_required || dc->wm_optimized_required)
return false;
- if (!memcmp(&stream->adjust, adjust, sizeof(*adjust)))
- return true;
-
dc_exit_ips_for_hw_access(dc);
stream->adjust.v_total_max = adjust->v_total_max;
@@ -2091,7 +2088,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);
/**
@@ -2157,7 +2154,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)
@@ -2312,6 +2309,7 @@ void dc_post_update_surfaces_to_stream(struct dc *dc)
}
dc->optimized_required = false;
+ dc->wm_optimized_required = false;
}
bool dc_set_generic_gpio_for_stereo(bool enable,
@@ -2512,6 +2510,10 @@ static enum surface_update_type get_scaling_info_update_type(
/* Changing clip size of a large surface may result in MPC slice count change */
update_flags->bits.bandwidth_change = 1;
+ if (u->scaling_info->clip_rect.width != u->surface->clip_rect.width ||
+ u->scaling_info->clip_rect.height != u->surface->clip_rect.height)
+ update_flags->bits.clip_size_change = 1;
+
if (u->scaling_info->src_rect.x != u->surface->src_rect.x
|| u->scaling_info->src_rect.y != u->surface->src_rect.y
|| u->scaling_info->clip_rect.x != u->surface->clip_rect.x
@@ -2525,7 +2527,8 @@ static enum surface_update_type get_scaling_info_update_type(
|| update_flags->bits.scaling_change)
return UPDATE_TYPE_FULL;
- if (update_flags->bits.position_change)
+ if (update_flags->bits.position_change ||
+ update_flags->bits.clip_size_change)
return UPDATE_TYPE_MED;
return UPDATE_TYPE_FAST;
@@ -2734,6 +2737,8 @@ enum surface_update_type dc_check_update_surfaces_for_stream(
} else if (memcmp(&dc->current_state->bw_ctx.bw.dcn.clk, &dc->clk_mgr->clks, offsetof(struct dc_clocks, prev_p_state_change_support)) != 0) {
dc->optimized_required = true;
}
+
+ dc->optimized_required |= dc->wm_optimized_required;
}
return type;
@@ -2941,6 +2946,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
if (update->vrr_active_fixed)
stream->vrr_active_fixed = *update->vrr_active_fixed;
+ if (update->crtc_timing_adjust)
+ stream->adjust = *update->crtc_timing_adjust;
+
if (update->dpms_off)
stream->dpms_off = *update->dpms_off;
@@ -3000,8 +3008,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;
@@ -3010,12 +3018,21 @@ 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;
+ if (stream->out_transfer_func)
+ 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;
@@ -3024,8 +3041,17 @@ 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;
+ if (stream->out_transfer_func)
+ *stream->out_transfer_func = scratch->out_transfer_func;
}
static bool update_planes_and_stream_state(struct dc *dc,
@@ -3051,7 +3077,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);
@@ -3151,7 +3177,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;
@@ -3594,6 +3620,17 @@ static void commit_planes_for_stream(struct dc *dc,
if (update_type == UPDATE_TYPE_FULL)
wait_for_outstanding_hw_updates(dc, context);
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (pipe->stream && pipe->plane_state) {
+ set_p_state_switch_method(dc, context, pipe);
+
+ if (dc->debug.visual_confirm)
+ dc_update_visual_confirm_color(dc, context, pipe);
+ }
+ }
+
if (update_type == UPDATE_TYPE_FULL) {
dc_allow_idle_optimizations(dc, false);
@@ -3628,17 +3665,6 @@ static void commit_planes_for_stream(struct dc *dc,
}
}
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
-
- if (pipe->stream && pipe->plane_state) {
- set_p_state_switch_method(dc, context, pipe);
-
- if (dc->debug.visual_confirm)
- dc_update_visual_confirm_color(dc, context, pipe);
- }
- }
-
if (stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) {
struct pipe_ctx *mpcc_pipe;
struct pipe_ctx *odm_pipe;
@@ -4099,7 +4125,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)
{
@@ -4108,12 +4150,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) {
@@ -4130,7 +4166,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) {
@@ -4143,7 +4179,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);
@@ -4151,7 +4187,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
@@ -4168,7 +4204,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;
@@ -4380,7 +4416,8 @@ static bool full_update_required(struct dc *dc,
stream_update->mst_bw_update ||
stream_update->func_shaper ||
stream_update->lut3d_func ||
- stream_update->pending_test_pattern))
+ stream_update->pending_test_pattern ||
+ stream_update->crtc_timing_adjust))
return true;
if (stream) {
@@ -4405,53 +4442,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,
@@ -4484,7 +4474,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(
@@ -4499,32 +4489,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,