Commit c681491a authored by Jun Lei's avatar Jun Lei Committed by Alex Deucher

drm/amd/display: fix pipe selection logic in validate

[why]
Resource mapping done in dcn20_validate_bandwidth has a flaw:  When a full
update is performed, the HWSS will only update the MPCC tree for the stream
that is updated as opposed to all streams.  This means that when mapping pipes
in validation, care must be taken to not change any existing mapping, otherwise it
leads to partial hw programming

[how]
it's not strictly necessary to track which stream/mpcc tree is being updated, but
rather it's sufficient to compare current and new state and just keep pipes that were
previously already mapped unchanged.
Signed-off-by: default avatarJun Lei <Jun.Lei@amd.com>
Reviewed-by: default avatarEric Yang <eric.yang2@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 04cf85d2
...@@ -2128,6 +2128,74 @@ static bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx) ...@@ -2128,6 +2128,74 @@ static bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx)
} }
#endif #endif
static struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc,
struct resource_context *res_ctx,
const struct resource_pool *pool,
const struct pipe_ctx *primary_pipe)
{
struct pipe_ctx *secondary_pipe = NULL;
if (dc && primary_pipe) {
int j;
int preferred_pipe_idx = 0;
/* first check the prev dc state:
* if this primary pipe has a bottom pipe in prev. state
* and if the bottom pipe is still available (which it should be),
* pick that pipe as secondary
*/
if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe) {
preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe->pipe_idx;
if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
secondary_pipe->pipe_idx = preferred_pipe_idx;
}
}
/*
* if this primary pipe does not have a bottom pipe in prev. state
* start backward and find a pipe that did not used to be a bottom pipe in
* prev. dc state. This way we make sure we keep the same assignment as
* last state and will not have to reprogram every pipe
*/
if (secondary_pipe == NULL) {
for (j = dc->res_pool->pipe_count - 1; j >= 0; j--) {
if (dc->current_state->res_ctx.pipe_ctx[j].top_pipe == NULL) {
preferred_pipe_idx = j;
if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
secondary_pipe->pipe_idx = preferred_pipe_idx;
break;
}
}
}
}
/*
* We should never hit this assert unless assignments are shuffled around
* if this happens we will prob. hit a vsync tdr
*/
ASSERT(secondary_pipe);
/*
* search backwards for the second pipe to keep pipe
* assignment more consistent
*/
if (secondary_pipe == NULL) {
for (j = dc->res_pool->pipe_count - 1; j >= 0; j--) {
preferred_pipe_idx = j;
if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
secondary_pipe->pipe_idx = preferred_pipe_idx;
break;
}
}
}
}
return secondary_pipe;
}
bool dcn20_fast_validate_bw( bool dcn20_fast_validate_bw(
struct dc *dc, struct dc *dc,
struct dc_state *context, struct dc_state *context,
...@@ -2281,7 +2349,7 @@ bool dcn20_fast_validate_bw( ...@@ -2281,7 +2349,7 @@ bool dcn20_fast_validate_bw(
if (force_split && context->bw_ctx.dml.vba.NoOfDPP[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] == 1) if (force_split && 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;
if (!pipe->top_pipe && !pipe->plane_state && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) { if (!pipe->top_pipe && !pipe->plane_state && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) {
hsplit_pipe = find_idle_secondary_pipe(&context->res_ctx, dc->res_pool, pipe); hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe);
ASSERT(hsplit_pipe); ASSERT(hsplit_pipe);
if (!dcn20_split_stream_for_combine( if (!dcn20_split_stream_for_combine(
&context->res_ctx, dc->res_pool, &context->res_ctx, dc->res_pool,
...@@ -2322,7 +2390,7 @@ bool dcn20_fast_validate_bw( ...@@ -2322,7 +2390,7 @@ bool dcn20_fast_validate_bw(
if (need_split3d || need_split || force_split) { if (need_split3d || need_split || force_split) {
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 = find_idle_secondary_pipe(&context->res_ctx, dc->res_pool, pipe); hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe);
ASSERT(hsplit_pipe || force_split); ASSERT(hsplit_pipe || force_split);
if (!hsplit_pipe) if (!hsplit_pipe)
continue; continue;
......
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