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

[Description]
- For SubVP pipe split case we need to use a minimial transition
  when opening MPO video since we are transitioning from 4 pipes
  to 3 pipes where an OPP for a previous MPCC will change
- Also save and restore mall config when doing fast_validate in case
  there was a shallow copy of the dc->current_state

Reviewed-by: Jun Lei <jun....@amd.com>
Acked-by: Hamza Mahfooz <hamza.mahf...@amd.com>
Signed-off-by: Alvin Lee <alvin.l...@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c      | 36 ++++++++++
 .../drm/amd/display/dc/dcn32/dcn32_resource.c | 18 +++++
 .../drm/amd/display/dc/dcn32/dcn32_resource.h | 20 ++++++
 .../display/dc/dcn32/dcn32_resource_helpers.c | 71 +++++++++++++++++++
 4 files changed, 145 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 2584cb8f44e2..9b7c6bac4760 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3561,6 +3561,7 @@ static bool 
could_mpcc_tree_change_for_active_pipes(struct dc *dc,
 
        struct dc_stream_status *cur_stream_status = 
stream_get_status(dc->current_state, stream);
        bool force_minimal_pipe_splitting = false;
+       uint32_t i;
 
        *is_plane_addition = false;
 
@@ -3592,6 +3593,36 @@ static bool 
could_mpcc_tree_change_for_active_pipes(struct dc *dc,
                }
        }
 
+       /* For SubVP pipe split case when adding MPO video
+        * we need to add a minimal transition. In this case
+        * there will be 2 streams (1 main stream, 1 phantom
+        * stream).
+        */
+       if (cur_stream_status &&
+                       dc->current_state->stream_count == 2 &&
+                       stream->mall_stream_config.type == SUBVP_MAIN) {
+               bool is_pipe_split = false;
+
+               for (i = 0; i < dc->res_pool->pipe_count; i++) {
+                       if (dc->current_state->res_ctx.pipe_ctx[i].stream == 
stream &&
+                                       
(dc->current_state->res_ctx.pipe_ctx[i].bottom_pipe ||
+                                       
dc->current_state->res_ctx.pipe_ctx[i].next_odm_pipe)) {
+                               is_pipe_split = true;
+                               break;
+                       }
+               }
+
+               /* determine if minimal transition is required due to SubVP*/
+               if (surface_count > 0 && is_pipe_split) {
+                       if (cur_stream_status->plane_count > surface_count) {
+                               force_minimal_pipe_splitting = true;
+                       } else if (cur_stream_status->plane_count < 
surface_count) {
+                               force_minimal_pipe_splitting = true;
+                               *is_plane_addition = true;
+                       }
+               }
+       }
+
        return force_minimal_pipe_splitting;
 }
 
@@ -3601,6 +3632,7 @@ static bool commit_minimal_transition_state(struct dc *dc,
        struct dc_state *transition_context = dc_create_state(dc);
        enum pipe_split_policy tmp_mpc_policy;
        bool temp_dynamic_odm_policy;
+       bool temp_subvp_policy;
        enum dc_status ret = DC_ERROR_UNEXPECTED;
        unsigned int i, j;
 
@@ -3615,6 +3647,9 @@ static bool commit_minimal_transition_state(struct dc *dc,
        temp_dynamic_odm_policy = 
dc->debug.enable_single_display_2to1_odm_policy;
        dc->debug.enable_single_display_2to1_odm_policy = false;
 
+       temp_subvp_policy = dc->debug.force_disable_subvp;
+       dc->debug.force_disable_subvp = true;
+
        dc_resource_state_copy_construct(transition_base_context, 
transition_context);
 
        //commit minimal state
@@ -3643,6 +3678,7 @@ static bool commit_minimal_transition_state(struct dc *dc,
                dc->debug.pipe_split_policy = tmp_mpc_policy;
 
        dc->debug.enable_single_display_2to1_odm_policy = 
temp_dynamic_odm_policy;
+       dc->debug.force_disable_subvp = temp_subvp_policy;
 
        if (ret != DC_OK) {
                /*this should never happen*/
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c 
b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
index 05de97ea855f..752a4accb116 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
@@ -1798,14 +1798,32 @@ bool dcn32_validate_bandwidth(struct dc *dc,
        int vlevel = 0;
        int pipe_cnt = 0;
        display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * 
sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
+       struct mall_temp_config mall_temp_config;
        DC_LOGGER_INIT(dc->ctx->logger);
 
+       /* For fast validation, there are situations where a shallow copy of
+        * of the dc->current_state is created for the validation. In this case
+        * we want to save and restore the mall config because we always
+        * teardown subvp at the beginning of validation (and don't attempt
+        * to add it back if it's fast validation). If we don't restore the
+        * subvp config in cases of fast validation + shallow copy of the
+        * dc->current_state, the dc->current_state will have a partially
+        * removed subvp state when we did not intend to remove it.
+        */
+       if (fast_validate) {
+               memset(&mall_temp_config, 0, sizeof(mall_temp_config));
+               dcn32_save_mall_state(dc, context, &mall_temp_config);
+       }
+
        BW_VAL_TRACE_COUNT();
 
        DC_FP_START();
        out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, 
&vlevel, fast_validate);
        DC_FP_END();
 
+       if (fast_validate)
+               dcn32_restore_mall_state(dc, context, &mall_temp_config);
+
        if (pipe_cnt == 0)
                goto validate_out;
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h 
b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
index a24f538bdc4c..f76120e67c16 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
@@ -45,6 +45,17 @@
 extern struct _vcs_dpi_ip_params_st dcn3_2_ip;
 extern struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc;
 
+/* Temp struct used to save and restore MALL config
+ * during validation.
+ *
+ * TODO: Move MALL config into dc_state instead of stream struct
+ * to avoid needing to save/restore.
+ */
+struct mall_temp_config {
+       struct mall_stream_config mall_stream_config[MAX_PIPES];
+       bool is_phantom_plane[MAX_PIPES];
+};
+
 struct dcn32_resource_pool {
        struct resource_pool base;
 };
@@ -122,6 +133,15 @@ void dcn32_determine_det_override(struct dc *dc,
 
 void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context,
        display_e2e_pipe_params_st *pipes);
+
+void dcn32_save_mall_state(struct dc *dc,
+               struct dc_state *context,
+               struct mall_temp_config *temp_config);
+
+void dcn32_restore_mall_state(struct dc *dc,
+               struct dc_state *context,
+               struct mall_temp_config *temp_config);
+
 /* definitions for run time init of reg offsets */
 
 /* CLK SRC */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c 
b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
index 7f318ced5dee..d51d0c40ae5b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
@@ -380,3 +380,74 @@ void dcn32_set_det_allocations(struct dc *dc, struct 
dc_state *context,
        } else
                dcn32_determine_det_override(dc, context, pipes);
 }
+
+/**
+ * 
*******************************************************************************************
+ * dcn32_save_mall_state: Save MALL (SubVP) state for fast validation cases
+ *
+ * This function saves the MALL (SubVP) case for fast validation cases. For 
fast validation,
+ * there are situations where a shallow copy of the dc->current_state is 
created for the
+ * validation. In this case we want to save and restore the mall config 
because we always
+ * teardown subvp at the beginning of validation (and don't attempt to add it 
back if it's
+ * fast validation). If we don't restore the subvp config in cases of fast 
validation +
+ * shallow copy of the dc->current_state, the dc->current_state will have a 
partially
+ * removed subvp state when we did not intend to remove it.
+ *
+ * NOTE: This function ONLY works if the streams are not moved to a different 
pipe in the
+ *       validation. We don't expect this to happen in fast_validation=1 cases.
+ *
+ * @param [in]: dc: Current DC state
+ * @param [in]: context: New DC state to be programmed
+ * @param [out]: temp_config: struct used to cache the existing MALL state
+ *
+ * @return: void
+ *
+ * 
*******************************************************************************************
+ */
+void dcn32_save_mall_state(struct dc *dc,
+               struct dc_state *context,
+               struct mall_temp_config *temp_config)
+{
+       uint32_t i;
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+               if (pipe->stream)
+                       temp_config->mall_stream_config[i] = 
pipe->stream->mall_stream_config;
+
+               if (pipe->plane_state)
+                       temp_config->is_phantom_plane[i] = 
pipe->plane_state->is_phantom;
+       }
+}
+
+/**
+ * 
*******************************************************************************************
+ * dcn32_restore_mall_state: Restore MALL (SubVP) state for fast validation 
cases
+ *
+ * Restore the MALL state based on the previously saved state from 
dcn32_save_mall_state
+ *
+ * @param [in]: dc: Current DC state
+ * @param [in/out]: context: New DC state to be programmed, restore MALL state 
into here
+ * @param [in]: temp_config: struct that has the cached MALL state
+ *
+ * @return: void
+ *
+ * 
*******************************************************************************************
+ */
+void dcn32_restore_mall_state(struct dc *dc,
+               struct dc_state *context,
+               struct mall_temp_config *temp_config)
+{
+       uint32_t i;
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+               if (pipe->stream)
+                       pipe->stream->mall_stream_config = 
temp_config->mall_stream_config[i];
+
+               if (pipe->plane_state)
+                       pipe->plane_state->is_phantom = 
temp_config->is_phantom_plane[i];
+       }
+}
-- 
2.37.2

Reply via email to