From: Alvin Lee <alvin.l...@amd.com>

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....@amd.com>
Acked-by: Rodrigo Siqueira <rodrigo.sique...@amd.com>
Signed-off-by: Alvin Lee <alvin.l...@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c      | 146 +++++++-----------
 .../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 {
-- 
2.43.0

Reply via email to