From: Dmytro Laktyushkin <dmytro.laktyush...@amd.com>

Current odm/mpc combine logic to detect which pipes need to split
logically is flawed leading to incorrect pipe merge/split operations
being taken.

This change cleans up the logic and fixes the logical errors.

Signed-off-by: Dmytro Laktyushkin <dmytro.laktyush...@amd.com>
Reviewed-by: Eric Bernstein <eric.bernst...@amd.com>
Acked-by: Rodrigo Siqueira <rodrigo.sique...@amd.com>
---
 .../gpu/drm/amd/display/dc/core/dc_resource.c |  25 ++-
 .../drm/amd/display/dc/dcn20/dcn20_resource.c | 153 ++++++++----------
 .../drm/amd/display/dc/dcn20/dcn20_resource.h |   5 +-
 drivers/gpu/drm/amd/display/dc/inc/resource.h |   2 +
 4 files changed, 94 insertions(+), 91 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index bbef8c67d1db..0c5619364e7d 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -532,6 +532,24 @@ static inline void get_vp_scan_direction(
                *flip_horz_scan_dir = !*flip_horz_scan_dir;
 }
 
+int get_num_mpc_splits(struct pipe_ctx *pipe)
+{
+       int mpc_split_count = 0;
+       struct pipe_ctx *other_pipe = pipe->bottom_pipe;
+
+       while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
+               mpc_split_count++;
+               other_pipe = other_pipe->bottom_pipe;
+       }
+       other_pipe = pipe->top_pipe;
+       while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
+               mpc_split_count++;
+               other_pipe = other_pipe->top_pipe;
+       }
+
+       return mpc_split_count;
+}
+
 int get_num_odm_splits(struct pipe_ctx *pipe)
 {
        int odm_split_count = 0;
@@ -556,16 +574,11 @@ static void calculate_split_count_and_index(struct 
pipe_ctx *pipe_ctx, int *spli
                /*Check for mpc split*/
                struct pipe_ctx *split_pipe = pipe_ctx->top_pipe;
 
+               *split_count = get_num_mpc_splits(pipe_ctx);
                while (split_pipe && split_pipe->plane_state == 
pipe_ctx->plane_state) {
                        (*split_idx)++;
-                       (*split_count)++;
                        split_pipe = split_pipe->top_pipe;
                }
-               split_pipe = pipe_ctx->bottom_pipe;
-               while (split_pipe && split_pipe->plane_state == 
pipe_ctx->plane_state) {
-                       (*split_count)++;
-                       split_pipe = split_pipe->bottom_pipe;
-               }
        } else {
                /*Get odm split index*/
                struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
index 4912160f81b3..4190ee592e6d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -1663,7 +1663,7 @@ enum dc_status dcn20_build_mapped_resource(const struct 
dc *dc, struct dc_state
 }
 
 
-static void acquire_dsc(const struct dc *dc,
+void dcn20_acquire_dsc(const struct dc *dc,
                        struct resource_context *res_ctx,
                        struct display_stream_compressor **dsc,
                        int pipe_idx)
@@ -1731,7 +1731,7 @@ enum dc_status dcn20_add_dsc_to_stream_resource(struct dc 
*dc,
                if (pipe_ctx->stream_res.dsc)
                        continue;
 
-               acquire_dsc(dc, &dc_ctx->res_ctx, &pipe_ctx->stream_res.dsc, i);
+               dcn20_acquire_dsc(dc, &dc_ctx->res_ctx, 
&pipe_ctx->stream_res.dsc, i);
 
                /* The number of DSCs can be less than the number of pipes */
                if (!pipe_ctx->stream_res.dsc) {
@@ -1923,7 +1923,7 @@ bool dcn20_split_stream_for_odm(
        }
        next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx];
        if (next_odm_pipe->stream->timing.flags.DSC == 1) {
-               acquire_dsc(dc, res_ctx, &next_odm_pipe->stream_res.dsc, 
next_odm_pipe->pipe_idx);
+               dcn20_acquire_dsc(dc, res_ctx, &next_odm_pipe->stream_res.dsc, 
next_odm_pipe->pipe_idx);
                ASSERT(next_odm_pipe->stream_res.dsc);
                if (next_odm_pipe->stream_res.dsc == NULL)
                        return false;
@@ -2586,27 +2586,6 @@ static void dcn20_merge_pipes_for_validate(
        }
 }
 
-int dcn20_find_previous_split_count(struct pipe_ctx *pipe)
-{
-       int previous_split = 1;
-       struct pipe_ctx *current_pipe = pipe;
-
-       while (current_pipe->bottom_pipe) {
-               if (current_pipe->plane_state != 
current_pipe->bottom_pipe->plane_state)
-                       break;
-               previous_split++;
-               current_pipe = current_pipe->bottom_pipe;
-       }
-       current_pipe = pipe;
-       while (current_pipe->top_pipe) {
-               if (current_pipe->plane_state != 
current_pipe->top_pipe->plane_state)
-                       break;
-               previous_split++;
-               current_pipe = current_pipe->top_pipe;
-       }
-       return previous_split;
-}
-
 int dcn20_validate_apply_pipe_split_flags(
                struct dc *dc,
                struct dc_state *context,
@@ -2618,6 +2597,8 @@ int dcn20_validate_apply_pipe_split_flags(
        int plane_count = 0;
        bool force_split = false;
        bool avoid_split = dc->debug.pipe_split_policy == MPC_SPLIT_AVOID;
+       struct vba_vars_st *v = &context->bw_ctx.dml.vba;
+       int max_mpc_comb = v->maxMpcComb;
 
        if (context->stream_count > 1) {
                if (dc->debug.pipe_split_policy == MPC_SPLIT_AVOID_MULT_DISP)
@@ -2638,15 +2619,13 @@ int dcn20_validate_apply_pipe_split_flags(
 
        /* Avoid split loop looks for lowest voltage level that allows most 
unsplit pipes possible */
        if (avoid_split) {
-               int max_mpc_comb = context->bw_ctx.dml.vba.maxMpcComb;
-
                for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
                        if (!context->res_ctx.pipe_ctx[i].stream)
                                continue;
 
                        for (vlevel_split = vlevel; vlevel <= 
context->bw_ctx.dml.soc.num_states; vlevel++)
-                               if 
(context->bw_ctx.dml.vba.NoOfDPP[vlevel][0][pipe_idx] == 1 &&
-                                               
context->bw_ctx.dml.vba.ModeSupport[vlevel][0])
+                               if (v->NoOfDPP[vlevel][0][pipe_idx] == 1 &&
+                                               v->ModeSupport[vlevel][0])
                                        break;
                        /* Impossible to not split this pipe */
                        if (vlevel > context->bw_ctx.dml.soc.num_states)
@@ -2655,21 +2634,21 @@ int dcn20_validate_apply_pipe_split_flags(
                                max_mpc_comb = 0;
                        pipe_idx++;
                }
-               context->bw_ctx.dml.vba.maxMpcComb = max_mpc_comb;
+               v->maxMpcComb = max_mpc_comb;
        }
 
        /* Split loop sets which pipe should be split based on dml outputs and 
dc flags */
        for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
                struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
-               int pipe_plane = context->bw_ctx.dml.vba.pipe_plane[pipe_idx];
+               int pipe_plane = v->pipe_plane[pipe_idx];
+               bool split4mpc = context->stream_count == 1 && plane_count == 1
+                               && dc->config.enable_4to1MPC && 
dc->res_pool->pipe_count >= 4;
 
                if (!context->res_ctx.pipe_ctx[i].stream)
                        continue;
 
-               if (force_split
-                               || 
context->bw_ctx.dml.vba.NoOfDPP[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_plane]
 > 1) {
-                       if (context->stream_count == 1 && plane_count == 1
-                                       && dc->config.enable_4to1MPC && 
dc->res_pool->pipe_count >= 4)
+               if (force_split || v->NoOfDPP[vlevel][max_mpc_comb][pipe_plane] 
> 1) {
+                       if (split4mpc)
                                split[i] = 4;
                        else
                                split[i] = 2;
@@ -2685,66 +2664,72 @@ int dcn20_validate_apply_pipe_split_flags(
                        split[i] = 2;
                if (dc->debug.force_odm_combine & (1 << 
pipe->stream_res.tg->inst)) {
                        split[i] = 2;
-                       
context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel][pipe_plane] = 
dm_odm_combine_mode_2to1;
+                       v->ODMCombineEnablePerState[vlevel][pipe_plane] = 
dm_odm_combine_mode_2to1;
                }
-               context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_plane] =
-                       
context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel][pipe_plane];
-
-               if (pipe->prev_odm_pipe && 
context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_plane] != 
dm_odm_combine_mode_disabled) {
-                       /*Already split odm pipe tree, don't try to split 
again*/
-                       split[i] = 0;
-                       split[pipe->prev_odm_pipe->pipe_idx] = 0;
-               } else if (pipe->top_pipe && pipe->plane_state == 
pipe->top_pipe->plane_state
-                               && 
context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_plane] == 
dm_odm_combine_mode_disabled) {
-                       /*If 2 way split but can support 4 way split, then 
split each pipe again*/
-                       if (context->stream_count == 1 && plane_count == 1
-                                       && dc->config.enable_4to1MPC && 
dc->res_pool->pipe_count >= 4) {
-                               split[i] = 2;
-                       } else {
+               v->ODMCombineEnabled[pipe_plane] =
+                       v->ODMCombineEnablePerState[vlevel][pipe_plane];
+
+               if (v->ODMCombineEnabled[pipe_plane] == 
dm_odm_combine_mode_disabled) {
+                       if (get_num_mpc_splits(pipe) == 1) {
+                               /*If need split for mpc but 2 way split 
already*/
+                               if (split[i] == 4)
+                                       split[i] = 2; /* 2 -> 4 MPC */
+                               else if (split[i] == 2)
+                                       split[i] = 0; /* 2 -> 2 MPC */
+                               else if (pipe->top_pipe && 
pipe->top_pipe->plane_state == pipe->plane_state)
+                                       merge[i] = true; /* 2 -> 1 MPC */
+                       } else if (get_num_mpc_splits(pipe) == 3) {
+                               /*If need split for mpc but 4 way split 
already*/
+                               if (split[i] == 2 && ((pipe->top_pipe && 
!pipe->top_pipe->top_pipe)
+                                               || !pipe->bottom_pipe)) {
+                                       merge[i] = true; /* 4 -> 2 MPC */
+                               } else if (split[i] == 0 && pipe->top_pipe &&
+                                               pipe->top_pipe->plane_state == 
pipe->plane_state)
+                                       merge[i] = true; /* 4 -> 1 MPC */
                                split[i] = 0;
-                               split[pipe->top_pipe->pipe_idx] = 0;
-                       }
-               } else if (pipe->prev_odm_pipe || 
(dcn20_find_previous_split_count(pipe) == 2 && pipe->top_pipe)) {
-                       if (split[i] == 0) {
-                               /*Exiting mpc/odm combine*/
-                               merge[i] = true;
-                       } else {
-                               /*Transition from mpc combine to odm combine or 
vice versa*/
-                               ASSERT(0); /*should not actually happen yet*/
-                               split[i] = 2;
-                               merge[i] = true;
+                       } else if (get_num_odm_splits(pipe)) {
+                               /* ODM -> MPC transition */
+                               ASSERT(0); /* NOT expected yet */
                                if (pipe->prev_odm_pipe) {
-                                       split[pipe->prev_odm_pipe->pipe_idx] = 
2;
-                                       merge[pipe->prev_odm_pipe->pipe_idx] = 
true;
-                               } else {
-                                       split[pipe->top_pipe->pipe_idx] = 2;
-                                       merge[pipe->top_pipe->pipe_idx] = true;
+                                       split[i] = 0;
+                                       merge[i] = true;
                                }
                        }
-               } else if (dcn20_find_previous_split_count(pipe) == 3) {
-                       if (split[i] == 0 && !pipe->top_pipe) {
-                               merge[pipe->bottom_pipe->pipe_idx] = true;
-                               merge[pipe->bottom_pipe->bottom_pipe->pipe_idx] 
= true;
-                       } else if (split[i] == 2 && !pipe->top_pipe) {
-                               merge[pipe->bottom_pipe->bottom_pipe->pipe_idx] 
= true;
-                               split[i] = 0;
-                       }
-               } else if (dcn20_find_previous_split_count(pipe) == 4) {
-                       if (split[i] == 0 && !pipe->top_pipe) {
-                               merge[pipe->bottom_pipe->pipe_idx] = true;
-                               merge[pipe->bottom_pipe->bottom_pipe->pipe_idx] 
= true;
-                               
merge[pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx] = true;
-                       } else if (split[i] == 2 && !pipe->top_pipe) {
-                               merge[pipe->bottom_pipe->bottom_pipe->pipe_idx] 
= true;
-                               
merge[pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx] = true;
+               } else {
+                       if (get_num_odm_splits(pipe) == 1) {
+                               /*If need split for odm but 2 way split 
already*/
+                               if (split[i] == 4)
+                                       split[i] = 2; /* 2 -> 4 ODM */
+                               else if (split[i] == 2)
+                                       split[i] = 0; /* 2 -> 2 ODM */
+                               else if (pipe->prev_odm_pipe) {
+                                       ASSERT(0); /* NOT expected yet */
+                                       merge[i] = true; /* exit ODM */
+                               }
+                       } else if (get_num_odm_splits(pipe) == 3) {
+                               /*If need split for odm but 4 way split 
already*/
+                               if (split[i] == 2 && ((pipe->prev_odm_pipe && 
!pipe->prev_odm_pipe->prev_odm_pipe)
+                                               || !pipe->next_odm_pipe)) {
+                                       ASSERT(0); /* NOT expected yet */
+                                       merge[i] = true; /* 4 -> 2 ODM */
+                               } else if (split[i] == 0 && 
pipe->prev_odm_pipe) {
+                                       ASSERT(0); /* NOT expected yet */
+                                       merge[i] = true; /* exit ODM */
+                               }
                                split[i] = 0;
+                       } else if (get_num_mpc_splits(pipe)) {
+                               /* MPC -> ODM transition */
+                               ASSERT(0); /* NOT expected yet */
+                               if (pipe->top_pipe && 
pipe->top_pipe->plane_state == pipe->plane_state) {
+                                       split[i] = 0;
+                                       merge[i] = true;
+                               }
                        }
                }
 
                /* Adjust dppclk when split is forced, do not bother with 
dispclk */
-               if (split[i] != 0
-                               && 
context->bw_ctx.dml.vba.NoOfDPP[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx]
 == 1)
-                       
context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx]
 /= 2;
+               if (split[i] != 0 && v->NoOfDPP[vlevel][max_mpc_comb][pipe_idx] 
== 1)
+                       v->RequiredDPPCLK[vlevel][max_mpc_comb][pipe_idx] /= 2;
                pipe_idx++;
        }
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
index ed5d31253314..2c1959845c29 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
@@ -119,7 +119,6 @@ void dcn20_set_mcif_arb_params(
                display_e2e_pipe_params_st *pipes,
                int pipe_cnt);
 bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, bool 
fast_validate);
-int dcn20_find_previous_split_count(struct pipe_ctx *pipe);
 int dcn20_validate_apply_pipe_split_flags(
                struct dc *dc,
                struct dc_state *context,
@@ -140,6 +139,10 @@ bool dcn20_split_stream_for_odm(
                struct resource_context *res_ctx,
                struct pipe_ctx *prev_odm_pipe,
                struct pipe_ctx *next_odm_pipe);
+void dcn20_acquire_dsc(const struct dc *dc,
+                       struct resource_context *res_ctx,
+                       struct display_stream_compressor **dsc,
+                       int pipe_idx);
 struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc,
                struct resource_context *res_ctx,
                const struct resource_pool *pool,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h 
b/drivers/gpu/drm/amd/display/dc/inc/resource.h
index 109c589eb97c..a9be495af922 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
@@ -177,6 +177,8 @@ unsigned int resource_pixel_format_to_bpp(enum 
surface_pixel_format format);
 void get_audio_check(struct audio_info *aud_modes,
        struct audio_check *aud_chk);
 
+int get_num_mpc_splits(struct pipe_ctx *pipe);
+
 int get_num_odm_splits(struct pipe_ctx *pipe);
 
 #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */
-- 
2.26.2

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to