Commit 570bc18c authored by Dmytro Laktyushkin's avatar Dmytro Laktyushkin Committed by Alex Deucher

drm/amd/display: fix and simplify pipe split logic

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: default avatarDmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Reviewed-by: default avatarEric Bernstein <Eric.Bernstein@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 14e49bb3
...@@ -532,6 +532,24 @@ static inline void get_vp_scan_direction( ...@@ -532,6 +532,24 @@ static inline void get_vp_scan_direction(
*flip_horz_scan_dir = !*flip_horz_scan_dir; *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 get_num_odm_splits(struct pipe_ctx *pipe)
{ {
int odm_split_count = 0; int odm_split_count = 0;
...@@ -556,16 +574,11 @@ static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *spli ...@@ -556,16 +574,11 @@ static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *spli
/*Check for mpc split*/ /*Check for mpc split*/
struct pipe_ctx *split_pipe = pipe_ctx->top_pipe; 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) { while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) {
(*split_idx)++; (*split_idx)++;
(*split_count)++;
split_pipe = split_pipe->top_pipe; 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 { } else {
/*Get odm split index*/ /*Get odm split index*/
struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe; struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe;
......
...@@ -1663,7 +1663,7 @@ enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state ...@@ -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 resource_context *res_ctx,
struct display_stream_compressor **dsc, struct display_stream_compressor **dsc,
int pipe_idx) int pipe_idx)
...@@ -1731,7 +1731,7 @@ enum dc_status dcn20_add_dsc_to_stream_resource(struct dc *dc, ...@@ -1731,7 +1731,7 @@ enum dc_status dcn20_add_dsc_to_stream_resource(struct dc *dc,
if (pipe_ctx->stream_res.dsc) if (pipe_ctx->stream_res.dsc)
continue; 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 */ /* The number of DSCs can be less than the number of pipes */
if (!pipe_ctx->stream_res.dsc) { if (!pipe_ctx->stream_res.dsc) {
...@@ -1923,7 +1923,7 @@ bool dcn20_split_stream_for_odm( ...@@ -1923,7 +1923,7 @@ bool dcn20_split_stream_for_odm(
} }
next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx]; next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx];
if (next_odm_pipe->stream->timing.flags.DSC == 1) { 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); ASSERT(next_odm_pipe->stream_res.dsc);
if (next_odm_pipe->stream_res.dsc == NULL) if (next_odm_pipe->stream_res.dsc == NULL)
return false; return false;
...@@ -2586,27 +2586,6 @@ static void dcn20_merge_pipes_for_validate( ...@@ -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( int dcn20_validate_apply_pipe_split_flags(
struct dc *dc, struct dc *dc,
struct dc_state *context, struct dc_state *context,
...@@ -2618,6 +2597,8 @@ int dcn20_validate_apply_pipe_split_flags( ...@@ -2618,6 +2597,8 @@ int dcn20_validate_apply_pipe_split_flags(
int plane_count = 0; int plane_count = 0;
bool force_split = false; bool force_split = false;
bool avoid_split = dc->debug.pipe_split_policy == MPC_SPLIT_AVOID; 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 (context->stream_count > 1) {
if (dc->debug.pipe_split_policy == MPC_SPLIT_AVOID_MULT_DISP) if (dc->debug.pipe_split_policy == MPC_SPLIT_AVOID_MULT_DISP)
...@@ -2638,15 +2619,13 @@ int dcn20_validate_apply_pipe_split_flags( ...@@ -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 */ /* Avoid split loop looks for lowest voltage level that allows most unsplit pipes possible */
if (avoid_split) { 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++) { for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
if (!context->res_ctx.pipe_ctx[i].stream) if (!context->res_ctx.pipe_ctx[i].stream)
continue; continue;
for (vlevel_split = vlevel; vlevel <= context->bw_ctx.dml.soc.num_states; vlevel++) 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 && if (v->NoOfDPP[vlevel][0][pipe_idx] == 1 &&
context->bw_ctx.dml.vba.ModeSupport[vlevel][0]) v->ModeSupport[vlevel][0])
break; break;
/* Impossible to not split this pipe */ /* Impossible to not split this pipe */
if (vlevel > context->bw_ctx.dml.soc.num_states) if (vlevel > context->bw_ctx.dml.soc.num_states)
...@@ -2655,21 +2634,21 @@ int dcn20_validate_apply_pipe_split_flags( ...@@ -2655,21 +2634,21 @@ int dcn20_validate_apply_pipe_split_flags(
max_mpc_comb = 0; max_mpc_comb = 0;
pipe_idx++; 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 */ /* 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++) { for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[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) if (!context->res_ctx.pipe_ctx[i].stream)
continue; continue;
if (force_split if (force_split || v->NoOfDPP[vlevel][max_mpc_comb][pipe_plane] > 1) {
|| context->bw_ctx.dml.vba.NoOfDPP[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_plane] > 1) { if (split4mpc)
if (context->stream_count == 1 && plane_count == 1
&& dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4)
split[i] = 4; split[i] = 4;
else else
split[i] = 2; split[i] = 2;
...@@ -2685,66 +2664,72 @@ int dcn20_validate_apply_pipe_split_flags( ...@@ -2685,66 +2664,72 @@ int dcn20_validate_apply_pipe_split_flags(
split[i] = 2; split[i] = 2;
if (dc->debug.force_odm_combine & (1 << pipe->stream_res.tg->inst)) { if (dc->debug.force_odm_combine & (1 << pipe->stream_res.tg->inst)) {
split[i] = 2; 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] = v->ODMCombineEnabled[pipe_plane] =
context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel][pipe_plane]; v->ODMCombineEnablePerState[vlevel][pipe_plane];
if (pipe->prev_odm_pipe && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_plane] != dm_odm_combine_mode_disabled) { if (v->ODMCombineEnabled[pipe_plane] == dm_odm_combine_mode_disabled) {
/*Already split odm pipe tree, don't try to split again*/ if (get_num_mpc_splits(pipe) == 1) {
split[i] = 0; /*If need split for mpc but 2 way split already*/
split[pipe->prev_odm_pipe->pipe_idx] = 0; if (split[i] == 4)
} else if (pipe->top_pipe && pipe->plane_state == pipe->top_pipe->plane_state split[i] = 2; /* 2 -> 4 MPC */
&& context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_plane] == dm_odm_combine_mode_disabled) { else if (split[i] == 2)
/*If 2 way split but can support 4 way split, then split each pipe again*/ split[i] = 0; /* 2 -> 2 MPC */
if (context->stream_count == 1 && plane_count == 1 else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state)
&& dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4) { merge[i] = true; /* 2 -> 1 MPC */
split[i] = 2; } else if (get_num_mpc_splits(pipe) == 3) {
} else { /*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[i] = 0;
split[pipe->top_pipe->pipe_idx] = 0; } else if (get_num_odm_splits(pipe)) {
} /* ODM -> MPC transition */
} else if (pipe->prev_odm_pipe || (dcn20_find_previous_split_count(pipe) == 2 && pipe->top_pipe)) { ASSERT(0); /* NOT expected yet */
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;
if (pipe->prev_odm_pipe) { if (pipe->prev_odm_pipe) {
split[pipe->prev_odm_pipe->pipe_idx] = 2; split[i] = 0;
merge[pipe->prev_odm_pipe->pipe_idx] = true; merge[i] = true;
} else {
split[pipe->top_pipe->pipe_idx] = 2;
merge[pipe->top_pipe->pipe_idx] = true;
} }
} }
} else if (dcn20_find_previous_split_count(pipe) == 3) { } else {
if (split[i] == 0 && !pipe->top_pipe) { if (get_num_odm_splits(pipe) == 1) {
merge[pipe->bottom_pipe->pipe_idx] = true; /*If need split for odm but 2 way split already*/
merge[pipe->bottom_pipe->bottom_pipe->pipe_idx] = true; if (split[i] == 4)
} else if (split[i] == 2 && !pipe->top_pipe) { split[i] = 2; /* 2 -> 4 ODM */
merge[pipe->bottom_pipe->bottom_pipe->pipe_idx] = true; else if (split[i] == 2)
split[i] = 0; split[i] = 0; /* 2 -> 2 ODM */
} else if (pipe->prev_odm_pipe) {
} else if (dcn20_find_previous_split_count(pipe) == 4) { ASSERT(0); /* NOT expected yet */
if (split[i] == 0 && !pipe->top_pipe) { merge[i] = true; /* exit ODM */
merge[pipe->bottom_pipe->pipe_idx] = true; }
merge[pipe->bottom_pipe->bottom_pipe->pipe_idx] = true; } else if (get_num_odm_splits(pipe) == 3) {
merge[pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx] = true; /*If need split for odm but 4 way split already*/
} else if (split[i] == 2 && !pipe->top_pipe) { if (split[i] == 2 && ((pipe->prev_odm_pipe && !pipe->prev_odm_pipe->prev_odm_pipe)
merge[pipe->bottom_pipe->bottom_pipe->pipe_idx] = true; || !pipe->next_odm_pipe)) {
merge[pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx] = true; 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; 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 */ /* Adjust dppclk when split is forced, do not bother with dispclk */
if (split[i] != 0 if (split[i] != 0 && v->NoOfDPP[vlevel][max_mpc_comb][pipe_idx] == 1)
&& context->bw_ctx.dml.vba.NoOfDPP[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] == 1) v->RequiredDPPCLK[vlevel][max_mpc_comb][pipe_idx] /= 2;
context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] /= 2;
pipe_idx++; pipe_idx++;
} }
......
...@@ -119,7 +119,6 @@ void dcn20_set_mcif_arb_params( ...@@ -119,7 +119,6 @@ void dcn20_set_mcif_arb_params(
display_e2e_pipe_params_st *pipes, display_e2e_pipe_params_st *pipes,
int pipe_cnt); int pipe_cnt);
bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate); 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( int dcn20_validate_apply_pipe_split_flags(
struct dc *dc, struct dc *dc,
struct dc_state *context, struct dc_state *context,
...@@ -140,6 +139,10 @@ bool dcn20_split_stream_for_odm( ...@@ -140,6 +139,10 @@ bool dcn20_split_stream_for_odm(
struct resource_context *res_ctx, struct resource_context *res_ctx,
struct pipe_ctx *prev_odm_pipe, struct pipe_ctx *prev_odm_pipe,
struct pipe_ctx *next_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 pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc,
struct resource_context *res_ctx, struct resource_context *res_ctx,
const struct resource_pool *pool, const struct resource_pool *pool,
......
...@@ -177,6 +177,8 @@ unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format); ...@@ -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, void get_audio_check(struct audio_info *aud_modes,
struct audio_check *aud_chk); struct audio_check *aud_chk);
int get_num_mpc_splits(struct pipe_ctx *pipe);
int get_num_odm_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_ */ #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment