From 5891f533f7770b52d3a1c48a8b0889841cb90b70 Mon Sep 17 00:00:00 2001 From: Jun Lei Date: Tue, 12 Mar 2019 15:12:41 -0400 Subject: [PATCH 1694/2940] drm/amd/display: add preferred pipe split logic [why] existing logic finds "first free pipe from 5 -> 0" to split this will cause certain sequences to require DC to move an MPCC from one tree to another, which is unsupported this leads to blackscreen to mitigate this problem, we will always try to acquire the "preferred" pipe, and each pipe has a unique preferred pipe this means we avoid most of the scenarios where pipe splitting leads to moving MPCC from one tree to another Change-Id: Ia6fc5a942cd9da243b824af80d889c0b015bb69f Signed-off-by: Jun Lei Reviewed-by: Tony Cheng Acked-by: Bhawanpreet Lakha --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 54 +++++++++++++++---- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 3 +- 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index d2083e0b59a7..e572ac59b035 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1141,7 +1141,7 @@ bool dcn_validate_bandwidth( hsplit_pipe->pipe_dlg_param.vblank_end = pipe->pipe_dlg_param.vblank_end; } else { /* pipe not split previously needs split */ - hsplit_pipe = find_idle_secondary_pipe(&context->res_ctx, pool); + hsplit_pipe = find_idle_secondary_pipe(&context->res_ctx, pool, pipe); ASSERT(hsplit_pipe); split_stream_across_pipes( &context->res_ctx, pool, 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 740602111110..788b771efcf4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1038,24 +1038,60 @@ enum dc_status resource_build_scaling_params_for_context( struct pipe_ctx *find_idle_secondary_pipe( struct resource_context *res_ctx, - const struct resource_pool *pool) + const struct resource_pool *pool, + const struct pipe_ctx *primary_pipe) { int i; struct pipe_ctx *secondary_pipe = NULL; /* - * search backwards for the second pipe to keep pipe - * assignment more consistent + * We add a preferred pipe mapping to avoid the chance that + * MPCCs already in use will need to be reassigned to other trees. + * For example, if we went with the strict, assign backwards logic: + * + * (State 1) + * Display A on, no surface, top pipe = 0 + * Display B on, no surface, top pipe = 1 + * + * (State 2) + * Display A on, no surface, top pipe = 0 + * Display B on, surface enable, top pipe = 1, bottom pipe = 5 + * + * (State 3) + * Display A on, surface enable, top pipe = 0, bottom pipe = 5 + * Display B on, surface enable, top pipe = 1, bottom pipe = 4 + * + * The state 2->3 transition requires remapping MPCC 5 from display B + * to display A. + * + * However, with the preferred pipe logic, state 2 would look like: + * + * (State 2) + * Display A on, no surface, top pipe = 0 + * Display B on, surface enable, top pipe = 1, bottom pipe = 4 + * + * This would then cause 2->3 to not require remapping any MPCCs. */ - - for (i = pool->pipe_count - 1; i >= 0; i--) { - if (res_ctx->pipe_ctx[i].stream == NULL) { - secondary_pipe = &res_ctx->pipe_ctx[i]; - secondary_pipe->pipe_idx = i; - break; + if (primary_pipe) { + int preferred_pipe_idx = (pool->pipe_count - 1) - primary_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; } } + /* + * search backwards for the second pipe to keep pipe + * assignment more consistent + */ + if (!secondary_pipe) + for (i = pool->pipe_count - 1; i >= 0; i--) { + if (res_ctx->pipe_ctx[i].stream == NULL) { + secondary_pipe = &res_ctx->pipe_ctx[i]; + secondary_pipe->pipe_idx = i; + break; + } + } return secondary_pipe; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index e879829a34b9..29f8893e44b6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1081,7 +1081,7 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( { struct resource_context *res_ctx = &context->res_ctx; struct pipe_ctx *head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); - struct pipe_ctx *idle_pipe = find_idle_secondary_pipe(res_ctx, pool); + struct pipe_ctx *idle_pipe = find_idle_secondary_pipe(res_ctx, pool, head_pipe); if (!head_pipe) { ASSERT(0); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 62e00a9f3184..028c63061767 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -131,7 +131,8 @@ bool resource_attach_surfaces_to_context( struct pipe_ctx *find_idle_secondary_pipe( struct resource_context *res_ctx, - const struct resource_pool *pool); + const struct resource_pool *pool, + const struct pipe_ctx *primary_pipe); bool resource_is_stream_unchanged( struct dc_state *old_context, struct dc_stream_state *stream); -- 2.17.1