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

[Why & How]
If we find that DML requires pipe split, run through
DML again because the DET allocation per pipe must
be re-assigned.

Reviewed-by: Dmytro Laktyushkin <dmytro.laktyush...@amd.com>
Acked-by: Wayne Lin <wayne....@amd.com>
Signed-off-by: Alvin Lee <alvin.l...@amd.com>
---
 .../drm/amd/display/dc/dcn32/dcn32_resource.c | 26 +-----
 .../drm/amd/display/dc/dcn32/dcn32_resource.h |  9 +-
 .../display/dc/dcn32/dcn32_resource_helpers.c | 89 ++++++++++++-------
 .../drm/amd/display/dc/dml/dcn32/dcn32_fpu.c  | 14 ++-
 .../drm/amd/display/dc/dml/dcn32/dcn32_fpu.h  |  5 --
 5 files changed, 76 insertions(+), 67 deletions(-)

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 dad174a52449..55198c3878b6 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
@@ -1837,12 +1837,6 @@ bool dcn32_validate_bandwidth(struct dc *dc,
        return out;
 }
 
-
-static bool is_dual_plane(enum surface_pixel_format format)
-{
-       return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == 
SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA;
-}
-
 int dcn32_populate_dml_pipes_from_context(
        struct dc *dc, struct dc_state *context,
        display_e2e_pipe_params_st *pipes,
@@ -1852,7 +1846,6 @@ int dcn32_populate_dml_pipes_from_context(
        struct resource_context *res_ctx = &context->res_ctx;
        struct pipe_ctx *pipe;
        bool subvp_in_use = false;
-       uint8_t is_pipe_split_expected[MAX_PIPES] = {0};
        int plane_count = 0;
        struct dc_crtc_timing *timing;
 
@@ -1940,11 +1933,6 @@ int dcn32_populate_dml_pipes_from_context(
                if (pipe->stream && !pipe->prev_odm_pipe &&
                                (!pipe->top_pipe || pipe->top_pipe->plane_state 
!= pipe->plane_state))
                        ++plane_count;
-
-               DC_FP_START();
-               is_pipe_split_expected[i] = dcn32_predict_pipe_split(context, 
&pipes[pipe_cnt]);
-               DC_FP_END();
-
                pipe_cnt++;
        }
 
@@ -1952,19 +1940,7 @@ int dcn32_populate_dml_pipes_from_context(
         * the DET available for each pipe). Use the DET override input to 
maintain our driver
         * policy.
         */
-       if (pipe_cnt == 1 && !is_pipe_split_expected[0]) {
-               pipes[0].pipe.src.det_size_override = DCN3_2_MAX_DET_SIZE;
-               if (pipe->plane_state && !dc->debug.disable_z9_mpc) {
-                       if (!is_dual_plane(pipe->plane_state->format)) {
-                               pipes[0].pipe.src.det_size_override = 
DCN3_2_DEFAULT_DET_SIZE;
-                               pipes[0].pipe.src.unbounded_req_mode = true;
-                               if (pipe->plane_state->src_rect.width >= 5120 &&
-                                       pipe->plane_state->src_rect.height >= 
2880)
-                                       pipes[0].pipe.src.det_size_override = 
320; // 5K or higher
-                       }
-               }
-       } else
-               dcn32_determine_det_override(dc, context, pipes, 
is_pipe_split_expected);
+       dcn32_set_det_allocations(dc, context, pipes);
 
        // In general cases we want to keep the dram clock change requirement
        // (prefer configs that support MCLK switch). Only override to false
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 1039df3f9565..40e9211eec1e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
@@ -28,6 +28,10 @@
 
 #include "core_types.h"
 
+#define DCN3_2_DEFAULT_DET_SIZE 256
+#define DCN3_2_MAX_DET_SIZE 1152
+#define DCN3_2_MIN_DET_SIZE 128
+#define DCN3_2_MIN_COMPBUF_SIZE_KB 128
 #define DCN3_2_DET_SEG_SIZE 64
 #define DCN3_2_MALL_MBLK_SIZE_BYTES 65536 // 64 * 1024
 #define DCN3_2_MBLK_WIDTH 128
@@ -111,9 +115,10 @@ struct pipe_ctx 
*dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
 
 void dcn32_determine_det_override(struct dc *dc,
                struct dc_state *context,
-               display_e2e_pipe_params_st *pipes,
-               uint8_t *is_pipe_split_expected);
+               display_e2e_pipe_params_st *pipes);
 
+void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context,
+       display_e2e_pipe_params_st *pipes);
 /* 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 160aefaac173..46ba6eee69ea 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
@@ -28,6 +28,11 @@
 #include "dcn20/dcn20_resource.h"
 #include "dml/dcn32/display_mode_vba_util_32.h"
 
+static bool is_dual_plane(enum surface_pixel_format format)
+{
+       return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == 
SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA;
+}
+
 /**
  * 
********************************************************************************************
  * dcn32_helper_calculate_num_ways_for_subvp: Calculate number of ways needed 
for SubVP
@@ -239,22 +244,17 @@ bool dcn32_mpo_in_use(struct dc_state *context)
  * If there is a plane that's driven by more than 1 pipe (i.e. pipe split), 
then the
  * number of DET for that given plane will be split among the pipes driving 
that plane.
  *
- * The pipe split prediction (is_pipe_split_expected) has to work 100% of the 
time in
- * order for this function to work properly.
  *
  * High level algorithm:
  * 1. Split total DET among number of streams
  * 2. For each stream, split DET among the planes
- * 3. For each plane, check if pipe split is expected. If yes, split the DET 
for that plane
- *    among the number of splits we expect (i.e. 2 [2:1] or 4 [4:1])
- *    - NOTE: Make sure not to double count the pipe splits (i.e. the pipes 
could
- *            already be split in the context).
+ * 3. For each plane, check if there is a pipe split. If yes, split the DET 
allocation
+ *    among those pipes.
  * 4. Assign the DET override to the DML pipes.
  *
  * @param [in]: dc: Current DC state
  * @param [in]: context: New DC state to be programmed
  * @param [in]: pipes: Array of DML pipes
- * @param [in]: is_pipe_split_expected: Array indicating pipe split prediction 
for each pipe
  *
  * @return: void
  *
@@ -262,16 +262,13 @@ bool dcn32_mpo_in_use(struct dc_state *context)
  */
 void dcn32_determine_det_override(struct dc *dc,
                struct dc_state *context,
-               display_e2e_pipe_params_st *pipes,
-               uint8_t *is_pipe_split_expected)
+               display_e2e_pipe_params_st *pipes)
 {
-       uint32_t i, j;
+       uint32_t i, j, k;
        uint8_t pipe_plane_count, stream_segments, plane_segments, 
pipe_segments[MAX_PIPES] = {0};
        uint8_t pipe_counted[MAX_PIPES] = {0};
        uint8_t pipe_cnt = 0;
        struct dc_plane_state *current_plane = NULL;
-       struct pipe_ctx *next_odm_pipe = NULL;
-       struct pipe_ctx *bottom_pipe = NULL;
        uint8_t stream_count = 0;
 
        for (i = 0; i < context->stream_count; i++) {
@@ -301,32 +298,21 @@ void dcn32_determine_det_override(struct dc *dc,
                                        pipe_plane_count++;
                                        pipe_counted[j] = 1;
                                        current_plane = 
context->res_ctx.pipe_ctx[j].plane_state;
-                                       if (is_pipe_split_expected[j] != 0) {
-                                               pipe_plane_count += 
is_pipe_split_expected[j];
-
-                                               next_odm_pipe = 
context->res_ctx.pipe_ctx[j].next_odm_pipe;
-                                               bottom_pipe = 
context->res_ctx.pipe_ctx[j].bottom_pipe;
-
-                                               /* If pipe already happens to 
be split in context, mark as already
-                                                * counted so we don't double 
count the pipe split.
-                                                */
-                                               while (next_odm_pipe) {
-                                                       if 
(next_odm_pipe->plane_state == current_plane) {
-                                                               
pipe_counted[next_odm_pipe->pipe_idx] = 1;
-                                                               
pipe_segments[next_odm_pipe->pipe_idx] = plane_segments / pipe_plane_count;
-                                                       }
-                                                       next_odm_pipe = 
next_odm_pipe->next_odm_pipe;
+                                       for (k = 0; k < 
dc->res_pool->pipe_count; k++) {
+                                               if (k != j && 
context->res_ctx.pipe_ctx[k].stream == context->streams[i] &&
+                                                               
context->res_ctx.pipe_ctx[k].plane_state == current_plane) {
+                                                       pipe_plane_count++;
+                                                       pipe_counted[k] = 1;
                                                }
+                                       }
 
-                                               while (bottom_pipe) {
-                                                       if 
(bottom_pipe->plane_state == current_plane) {
-                                                               
pipe_counted[bottom_pipe->pipe_idx] = 1;
-                                                               
pipe_segments[bottom_pipe->pipe_idx] = plane_segments / pipe_plane_count;
-                                                       }
-                                                       bottom_pipe = 
bottom_pipe->bottom_pipe;
+                                       pipe_segments[j] = plane_segments / 
pipe_plane_count;
+                                       for (k = 0; k < 
dc->res_pool->pipe_count; k++) {
+                                               if (k != j && 
context->res_ctx.pipe_ctx[k].stream == context->streams[i] &&
+                                                               
context->res_ctx.pipe_ctx[k].plane_state == current_plane) {
+                                                       pipe_segments[k] = 
plane_segments / pipe_plane_count;
                                                }
                                        }
-                                       pipe_segments[j] = plane_segments / 
pipe_plane_count;
                                }
                        }
                }
@@ -342,3 +328,38 @@ void dcn32_determine_det_override(struct dc *dc,
                        pipes[i].pipe.src.det_size_override = 4 * 
DCN3_2_DET_SEG_SIZE; //DCN3_2_DEFAULT_DET_SIZE
        }
 }
+
+void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context,
+       display_e2e_pipe_params_st *pipes)
+{
+       int i, pipe_cnt;
+       struct resource_context *res_ctx = &context->res_ctx;
+       struct pipe_ctx *pipe;
+
+       for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
+
+               if (!res_ctx->pipe_ctx[i].stream)
+                       continue;
+
+               pipe = &res_ctx->pipe_ctx[i];
+               pipe_cnt++;
+       }
+
+       /* For DET allocation, we don't want to use DML policy (not optimal for 
utilizing all
+        * the DET available for each pipe). Use the DET override input to 
maintain our driver
+        * policy.
+        */
+       if (pipe_cnt == 1) {
+               pipes[0].pipe.src.det_size_override = DCN3_2_MAX_DET_SIZE;
+               if (pipe->plane_state && !dc->debug.disable_z9_mpc && 
pipe->plane_state->tiling_info.gfx9.swizzle != DC_SW_LINEAR) {
+                       if (!is_dual_plane(pipe->plane_state->format)) {
+                               pipes[0].pipe.src.det_size_override = 
DCN3_2_DEFAULT_DET_SIZE;
+                               pipes[0].pipe.src.unbounded_req_mode = true;
+                               if (pipe->plane_state->src_rect.width >= 5120 &&
+                                       pipe->plane_state->src_rect.height >= 
2880)
+                                       pipes[0].pipe.src.det_size_override = 
320; // 5K or higher
+                       }
+               }
+       } else
+               dcn32_determine_det_override(dc, context, pipes);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c 
b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
index b573ab7b81ed..fe0770038a90 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
@@ -1720,8 +1720,20 @@ bool dcn32_internal_validate_bw(struct dc *dc,
                goto validate_fail;
        }
 
-       if (repopulate_pipes)
+       if (repopulate_pipes) {
                pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, 
pipes, fast_validate);
+
+               /* repopulate_pipes = 1 means the pipes were either split or 
merged. In this case
+                * we have to re-calculate the DET allocation and run through 
DML once more to
+                * ensure all the params are calculated correctly. We do not 
need to run the
+                * pipe split check again after this call (pipes are already 
split / merged).
+                * */
+               if (!fast_validate) {
+                       
context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
+                                               
dm_prefetch_support_uclk_fclk_and_stutter_if_possible;
+                       vlevel = dml_get_voltage_level(&context->bw_ctx.dml, 
pipes, pipe_cnt);
+               }
+       }
        *vlevel_out = vlevel;
        *pipe_cnt_out = pipe_cnt;
 
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h 
b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h
index b43c45adb7d3..732ed7fadb8a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h
@@ -29,11 +29,6 @@
 
 #include "clk_mgr_internal.h"
 
-#define DCN3_2_DEFAULT_DET_SIZE 256
-#define DCN3_2_MAX_DET_SIZE 1152
-#define DCN3_2_MIN_DET_SIZE 128
-#define DCN3_2_MIN_COMPBUF_SIZE_KB 128
-
 void dcn32_build_wm_range_table_fpu(struct clk_mgr_internal *clk_mgr);
 
 void dcn32_helper_populate_phantom_dlg_params(struct dc *dc,
-- 
2.37.3

Reply via email to