Commit 65d68369 authored by Isabel Zhang's avatar Isabel Zhang Committed by Alex Deucher

drm/amd/display: Add 4 to 1 MPC split support

[Why]
Want to make use of detile buffer of all 4 pipes to maximize amount of
data stored to hide certain memory latency cases.

[How]
In case of 1 plane and 1 stream, program 4 pipes to each retrieve 1/4 of
plane later mixed together by the MPCs. Added support for transition
from 4 to 1 MPC to 2 to 1 MPC or no pipe split case and vice versa.
Currently, only enabled if debug flag is set.
Signed-off-by: default avatarIsabel Zhang <isabel.zhang@amd.com>
Reviewed-by: default avatarDmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Acked-by: default avatarAurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent e0a3794d
...@@ -277,6 +277,7 @@ struct dc_config { ...@@ -277,6 +277,7 @@ struct dc_config {
bool disable_extended_timeout_support; // Used to disable extended timeout and lttpr feature as well bool disable_extended_timeout_support; // Used to disable extended timeout and lttpr feature as well
bool multi_mon_pp_mclk_switch; bool multi_mon_pp_mclk_switch;
bool disable_dmcu; bool disable_dmcu;
bool enable_4to1MPC;
}; };
enum visual_confirm { enum visual_confirm {
......
...@@ -1922,7 +1922,7 @@ bool dcn20_split_stream_for_odm( ...@@ -1922,7 +1922,7 @@ bool dcn20_split_stream_for_odm(
return true; return true;
} }
bool dcn20_split_stream_for_mpc( void dcn20_split_stream_for_mpc(
struct resource_context *res_ctx, struct resource_context *res_ctx,
const struct resource_pool *pool, const struct resource_pool *pool,
struct pipe_ctx *primary_pipe, struct pipe_ctx *primary_pipe,
...@@ -1951,11 +1951,6 @@ bool dcn20_split_stream_for_mpc( ...@@ -1951,11 +1951,6 @@ bool dcn20_split_stream_for_mpc(
secondary_pipe->top_pipe = primary_pipe; secondary_pipe->top_pipe = primary_pipe;
ASSERT(primary_pipe->plane_state); ASSERT(primary_pipe->plane_state);
if (!resource_build_scaling_params(primary_pipe) ||
!resource_build_scaling_params(secondary_pipe))
return false;
return true;
} }
void dcn20_populate_dml_writeback_from_context( void dcn20_populate_dml_writeback_from_context(
...@@ -2581,11 +2576,32 @@ static void dcn20_merge_pipes_for_validate( ...@@ -2581,11 +2576,32 @@ 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,
int vlevel, int vlevel,
bool *split, int *split,
bool *merge) bool *merge)
{ {
int i, pipe_idx, vlevel_split; int i, pipe_idx, vlevel_split;
...@@ -2640,8 +2656,14 @@ int dcn20_validate_apply_pipe_split_flags( ...@@ -2640,8 +2656,14 @@ int dcn20_validate_apply_pipe_split_flags(
if (!context->res_ctx.pipe_ctx[i].stream) if (!context->res_ctx.pipe_ctx[i].stream)
continue; continue;
if (force_split || context->bw_ctx.dml.vba.NoOfDPP[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_plane] > 1) if (force_split
split[i] = true; || 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)
split[i] = 4;
else
split[i] = 2;
}
if ((pipe->stream->view_format == if ((pipe->stream->view_format ==
VIEW_3D_FORMAT_SIDE_BY_SIDE || VIEW_3D_FORMAT_SIDE_BY_SIDE ||
pipe->stream->view_format == pipe->stream->view_format ==
...@@ -2650,9 +2672,9 @@ int dcn20_validate_apply_pipe_split_flags( ...@@ -2650,9 +2672,9 @@ int dcn20_validate_apply_pipe_split_flags(
TIMING_3D_FORMAT_TOP_AND_BOTTOM || TIMING_3D_FORMAT_TOP_AND_BOTTOM ||
pipe->stream->timing.timing_3d_format == pipe->stream->timing.timing_3d_format ==
TIMING_3D_FORMAT_SIDE_BY_SIDE)) TIMING_3D_FORMAT_SIDE_BY_SIDE))
split[i] = true; 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] = true; split[i] = 2;
context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel][pipe_plane] = dm_odm_combine_mode_2to1; context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel][pipe_plane] = dm_odm_combine_mode_2to1;
} }
context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_plane] = context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_plane] =
...@@ -2660,39 +2682,58 @@ int dcn20_validate_apply_pipe_split_flags( ...@@ -2660,39 +2682,58 @@ int dcn20_validate_apply_pipe_split_flags(
if (pipe->prev_odm_pipe && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_plane] != dm_odm_combine_mode_disabled) { 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*/ /*Already split odm pipe tree, don't try to split again*/
split[i] = false; split[i] = 0;
split[pipe->prev_odm_pipe->pipe_idx] = false; split[pipe->prev_odm_pipe->pipe_idx] = 0;
} else if (pipe->top_pipe && pipe->plane_state == pipe->top_pipe->plane_state } 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) { && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_plane] == dm_odm_combine_mode_disabled) {
/*Already split mpc tree, don't try to split again, assumes only 2x mpc combine*/ /*If 2 way split but can support 4 way split, then split each pipe again*/
split[i] = false; if (context->stream_count == 1 && plane_count == 1
split[pipe->top_pipe->pipe_idx] = false; && dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4) {
} else if (pipe->prev_odm_pipe || (pipe->top_pipe && pipe->plane_state == pipe->top_pipe->plane_state)) { split[i] = 2;
if (split[i] == false) { } else {
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*/ /*Exiting mpc/odm combine*/
merge[i] = true; merge[i] = true;
if (pipe->prev_odm_pipe) {
ASSERT(0); /*should not actually happen yet*/
merge[pipe->prev_odm_pipe->pipe_idx] = true;
} else
merge[pipe->top_pipe->pipe_idx] = true;
} else { } else {
/*Transition from mpc combine to odm combine or vice versa*/ /*Transition from mpc combine to odm combine or vice versa*/
ASSERT(0); /*should not actually happen yet*/ ASSERT(0); /*should not actually happen yet*/
split[i] = true; split[i] = 2;
merge[i] = true; merge[i] = true;
if (pipe->prev_odm_pipe) { if (pipe->prev_odm_pipe) {
split[pipe->prev_odm_pipe->pipe_idx] = true; split[pipe->prev_odm_pipe->pipe_idx] = 2;
merge[pipe->prev_odm_pipe->pipe_idx] = true; merge[pipe->prev_odm_pipe->pipe_idx] = true;
} else { } else {
split[pipe->top_pipe->pipe_idx] = true; split[pipe->top_pipe->pipe_idx] = 2;
merge[pipe->top_pipe->pipe_idx] = true; merge[pipe->top_pipe->pipe_idx] = 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;
split[i] = 0;
}
} }
/* 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] && context->bw_ctx.dml.vba.NoOfDPP[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] == 1) 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; context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] /= 2;
pipe_idx++; pipe_idx++;
} }
...@@ -2709,7 +2750,7 @@ bool dcn20_fast_validate_bw( ...@@ -2709,7 +2750,7 @@ bool dcn20_fast_validate_bw(
int *vlevel_out) int *vlevel_out)
{ {
bool out = false; bool out = false;
bool split[MAX_PIPES] = { false }; int split[MAX_PIPES] = { 0 };
int pipe_cnt, i, pipe_idx, vlevel; int pipe_cnt, i, pipe_idx, vlevel;
ASSERT(pipes); ASSERT(pipes);
...@@ -2769,7 +2810,7 @@ bool dcn20_fast_validate_bw( ...@@ -2769,7 +2810,7 @@ bool dcn20_fast_validate_bw(
&& context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx])
goto validate_fail; goto validate_fail;
if (split[i]) { if (split[i] == 2) {
if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state) { if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state) {
/* pipe not split previously needs split */ /* pipe not split previously needs split */
hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe); hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe);
...@@ -2784,11 +2825,13 @@ bool dcn20_fast_validate_bw( ...@@ -2784,11 +2825,13 @@ bool dcn20_fast_validate_bw(
pipe, hsplit_pipe)) pipe, hsplit_pipe))
goto validate_fail; goto validate_fail;
dcn20_build_mapped_resource(dc, context, pipe->stream); dcn20_build_mapped_resource(dc, context, pipe->stream);
} else } else {
if (!dcn20_split_stream_for_mpc( dcn20_split_stream_for_mpc(
&context->res_ctx, dc->res_pool, &context->res_ctx, dc->res_pool,
pipe, hsplit_pipe)) pipe, hsplit_pipe);
if (!resource_build_scaling_params(pipe) || !resource_build_scaling_params(hsplit_pipe))
goto validate_fail; goto validate_fail;
}
pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx; pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx;
} }
} else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) {
......
...@@ -119,17 +119,18 @@ void dcn20_set_mcif_arb_params( ...@@ -119,17 +119,18 @@ 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,
int vlevel, int vlevel,
bool *split, int *split,
bool *merge); bool *merge);
void dcn20_release_dsc(struct resource_context *res_ctx, void dcn20_release_dsc(struct resource_context *res_ctx,
const struct resource_pool *pool, const struct resource_pool *pool,
struct display_stream_compressor **dsc); struct display_stream_compressor **dsc);
bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx); bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx);
bool dcn20_split_stream_for_mpc( void dcn20_split_stream_for_mpc(
struct resource_context *res_ctx, struct resource_context *res_ctx,
const struct resource_pool *pool, const struct resource_pool *pool,
struct pipe_ctx *primary_pipe, struct pipe_ctx *primary_pipe,
......
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