From d3768874e5fe410d80c45e57bff47e8e708c0516 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 28 Sep 2020 17:59:38 -0400 Subject: [PATCH] drm/amd/display: add pipe reassignment prevention code to dcn3 Add code to gracefuly handle any pipe reassignment occuring on dcn3 hardware. This should only happen when new surfaces are used for an update rather than old ones updated. Fixes: 69fc1f4b976cea ("amd/drm/display: avoid dcn3 on flip opp change for slave pipes") Signed-off-by: Dmytro Laktyushkin Reviewed-by: Bhawanpreet Lakha Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn30/dcn30_resource.c | 61 +++++++++++++++---- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index c223f8af2084f..24fb39a11e5d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -1901,21 +1901,28 @@ static bool dcn30_split_stream_for_mpc_or_odm( static struct pipe_ctx *dcn30_find_split_pipe( struct dc *dc, - struct dc_state *context) + struct dc_state *context, + int old_index) { struct pipe_ctx *pipe = NULL; int i; - for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { - if (dc->current_state->res_ctx.pipe_ctx[i].top_pipe == NULL - && dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) { - if (context->res_ctx.pipe_ctx[i].stream == NULL) { - pipe = &context->res_ctx.pipe_ctx[i]; - pipe->pipe_idx = i; - break; + if (old_index >= 0 && context->res_ctx.pipe_ctx[old_index].stream == NULL) { + pipe = &context->res_ctx.pipe_ctx[old_index]; + pipe->pipe_idx = old_index; + } + + if (!pipe) + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + if (dc->current_state->res_ctx.pipe_ctx[i].top_pipe == NULL + && dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) { + if (context->res_ctx.pipe_ctx[i].stream == NULL) { + pipe = &context->res_ctx.pipe_ctx[i]; + pipe->pipe_idx = i; + break; + } } } - } /* * May need to fix pipes getting tossed from 1 opp to another on flip @@ -2082,8 +2089,10 @@ static bool dcn30_internal_validate_bw( for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *hsplit_pipe = NULL; bool odm; + int old_index = -1; if (!pipe->stream || newly_split[i]) continue; @@ -2095,7 +2104,20 @@ static bool dcn30_internal_validate_bw( continue; if (split[i]) { - hsplit_pipe = dcn30_find_split_pipe(dc, context); + if (odm) { + if (split[i] == 4 && old_pipe->next_odm_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx; + else if (old_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->pipe_idx; + } else { + if (split[i] == 4 && old_pipe->bottom_pipe->bottom_pipe && + old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx; + else if (old_pipe->bottom_pipe && + old_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->pipe_idx; + } + hsplit_pipe = dcn30_find_split_pipe(dc, context, old_index); ASSERT(hsplit_pipe); if (!hsplit_pipe) goto validate_fail; @@ -2109,8 +2131,16 @@ static bool dcn30_internal_validate_bw( repopulate_pipes = true; } if (split[i] == 4) { - struct pipe_ctx *pipe_4to1 = dcn30_find_split_pipe(dc, context); + struct pipe_ctx *pipe_4to1; + if (odm && old_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->pipe_idx; + else if (!odm && old_pipe->bottom_pipe && + old_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->pipe_idx; + else + old_index = -1; + pipe_4to1 = dcn30_find_split_pipe(dc, context, old_index); ASSERT(pipe_4to1); if (!pipe_4to1) goto validate_fail; @@ -2120,7 +2150,14 @@ static bool dcn30_internal_validate_bw( goto validate_fail; newly_split[pipe_4to1->pipe_idx] = true; - pipe_4to1 = dcn30_find_split_pipe(dc, context); + if (odm && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx; + else if (!odm && old_pipe->bottom_pipe->bottom_pipe->bottom_pipe && + old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx; + else + old_index = -1; + pipe_4to1 = dcn30_find_split_pipe(dc, context, old_index); ASSERT(pipe_4to1); if (!pipe_4to1) goto validate_fail; -- 2.30.2