Skip to content

Commit 39c8b93

Browse files
Wenjing Liualexdeucher
authored andcommitted
Partially revert "drm/amd/display: update add plane to context logic with a new algorithm"
This partially reverts commit 460ea89 ("drm/amd/display: update add plane to context logic with a new algorithm"). The new secondary pipe allocation logic triggers an issue with a specific hardware state transition and causes a frame of corruption when toggling between windowed MPO and ODM desktop only mode. Ideally hwss is supposed to handle this scenario. We are temporarily reverting the logic and investigate the root cause why this transition would cause corruptions. Fixes: 460ea89 ("drm/amd/display: update add plane to context logic with a new algorithm") Reviewed-by: Martin Leung <[email protected]> Acked-by: Hamza Mahfooz <[email protected]> Signed-off-by: Wenjing Liu <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent 1611917 commit 39c8b93

File tree

1 file changed

+114
-4
lines changed

1 file changed

+114
-4
lines changed

drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c

Lines changed: 114 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2564,18 +2564,128 @@ static int find_optimal_free_pipe_as_secondary_dpp_pipe(
25642564
return free_pipe_idx;
25652565
}
25662566

2567+
static struct pipe_ctx *find_idle_secondary_pipe_check_mpo(
2568+
struct resource_context *res_ctx,
2569+
const struct resource_pool *pool,
2570+
const struct pipe_ctx *primary_pipe)
2571+
{
2572+
int i;
2573+
struct pipe_ctx *secondary_pipe = NULL;
2574+
struct pipe_ctx *next_odm_mpo_pipe = NULL;
2575+
int primary_index, preferred_pipe_idx;
2576+
struct pipe_ctx *old_primary_pipe = NULL;
2577+
2578+
/*
2579+
* Modified from find_idle_secondary_pipe
2580+
* With windowed MPO and ODM, we want to avoid the case where we want a
2581+
* free pipe for the left side but the free pipe is being used on the
2582+
* right side.
2583+
* Add check on current_state if the primary_pipe is the left side,
2584+
* to check the right side ( primary_pipe->next_odm_pipe ) to see if
2585+
* it is using a pipe for MPO ( primary_pipe->next_odm_pipe->bottom_pipe )
2586+
* - If so, then don't use this pipe
2587+
* EXCEPTION - 3 plane ( 2 MPO plane ) case
2588+
* - in this case, the primary pipe has already gotten a free pipe for the
2589+
* MPO window in the left
2590+
* - when it tries to get a free pipe for the MPO window on the right,
2591+
* it will see that it is already assigned to the right side
2592+
* ( primary_pipe->next_odm_pipe ). But in this case, we want this
2593+
* free pipe, since it will be for the right side. So add an
2594+
* additional condition, that skipping the free pipe on the right only
2595+
* applies if the primary pipe has no bottom pipe currently assigned
2596+
*/
2597+
if (primary_pipe) {
2598+
primary_index = primary_pipe->pipe_idx;
2599+
old_primary_pipe = &primary_pipe->stream->ctx->dc->current_state->res_ctx.pipe_ctx[primary_index];
2600+
if ((old_primary_pipe->next_odm_pipe) && (old_primary_pipe->next_odm_pipe->bottom_pipe)
2601+
&& (!primary_pipe->bottom_pipe))
2602+
next_odm_mpo_pipe = old_primary_pipe->next_odm_pipe->bottom_pipe;
2603+
2604+
preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx;
2605+
if ((res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) &&
2606+
!(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == preferred_pipe_idx)) {
2607+
secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
2608+
secondary_pipe->pipe_idx = preferred_pipe_idx;
2609+
}
2610+
}
2611+
2612+
/*
2613+
* search backwards for the second pipe to keep pipe
2614+
* assignment more consistent
2615+
*/
2616+
if (!secondary_pipe)
2617+
for (i = pool->pipe_count - 1; i >= 0; i--) {
2618+
if ((res_ctx->pipe_ctx[i].stream == NULL) &&
2619+
!(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == i)) {
2620+
secondary_pipe = &res_ctx->pipe_ctx[i];
2621+
secondary_pipe->pipe_idx = i;
2622+
break;
2623+
}
2624+
}
2625+
2626+
return secondary_pipe;
2627+
}
2628+
2629+
static struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
2630+
struct dc_state *state,
2631+
const struct resource_pool *pool,
2632+
struct dc_stream_state *stream,
2633+
const struct pipe_ctx *head_pipe)
2634+
{
2635+
struct resource_context *res_ctx = &state->res_ctx;
2636+
struct pipe_ctx *idle_pipe, *pipe;
2637+
struct resource_context *old_ctx = &stream->ctx->dc->current_state->res_ctx;
2638+
int head_index;
2639+
2640+
if (!head_pipe)
2641+
ASSERT(0);
2642+
2643+
/*
2644+
* Modified from dcn20_acquire_idle_pipe_for_layer
2645+
* Check if head_pipe in old_context already has bottom_pipe allocated.
2646+
* - If so, check if that pipe is available in the current context.
2647+
* -- If so, reuse pipe from old_context
2648+
*/
2649+
head_index = head_pipe->pipe_idx;
2650+
pipe = &old_ctx->pipe_ctx[head_index];
2651+
if (pipe->bottom_pipe && res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx].stream == NULL) {
2652+
idle_pipe = &res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx];
2653+
idle_pipe->pipe_idx = pipe->bottom_pipe->pipe_idx;
2654+
} else {
2655+
idle_pipe = find_idle_secondary_pipe_check_mpo(res_ctx, pool, head_pipe);
2656+
if (!idle_pipe)
2657+
return NULL;
2658+
}
2659+
2660+
idle_pipe->stream = head_pipe->stream;
2661+
idle_pipe->stream_res.tg = head_pipe->stream_res.tg;
2662+
idle_pipe->stream_res.opp = head_pipe->stream_res.opp;
2663+
2664+
idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx];
2665+
idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx];
2666+
idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx];
2667+
idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst;
2668+
2669+
return idle_pipe;
2670+
}
2671+
25672672
struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe(
25682673
const struct dc_state *cur_ctx,
25692674
struct dc_state *new_ctx,
25702675
const struct resource_pool *pool,
25712676
const struct pipe_ctx *opp_head_pipe)
25722677
{
2573-
int free_pipe_idx =
2574-
find_optimal_free_pipe_as_secondary_dpp_pipe(
2575-
&cur_ctx->res_ctx, &new_ctx->res_ctx,
2576-
pool, opp_head_pipe);
2678+
2679+
int free_pipe_idx;
25772680
struct pipe_ctx *free_pipe;
25782681

2682+
if (!opp_head_pipe->stream->ctx->dc->config.enable_windowed_mpo_odm)
2683+
return dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
2684+
new_ctx, pool, opp_head_pipe->stream, opp_head_pipe);
2685+
2686+
free_pipe_idx = find_optimal_free_pipe_as_secondary_dpp_pipe(
2687+
&cur_ctx->res_ctx, &new_ctx->res_ctx,
2688+
pool, opp_head_pipe);
25792689
if (free_pipe_idx >= 0) {
25802690
free_pipe = &new_ctx->res_ctx.pipe_ctx[free_pipe_idx];
25812691
free_pipe->pipe_idx = free_pipe_idx;

0 commit comments

Comments
 (0)