aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3418-drm-amd-display-fix-pipe-selection-logic-in-validate.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3418-drm-amd-display-fix-pipe-selection-logic-in-validate.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3418-drm-amd-display-fix-pipe-selection-logic-in-validate.patch125
1 files changed, 125 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3418-drm-amd-display-fix-pipe-selection-logic-in-validate.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3418-drm-amd-display-fix-pipe-selection-logic-in-validate.patch
new file mode 100644
index 00000000..683d8282
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3418-drm-amd-display-fix-pipe-selection-logic-in-validate.patch
@@ -0,0 +1,125 @@
+From fe94baa31d7dd52be4ab26f0688ee6ee05d48dd0 Mon Sep 17 00:00:00 2001
+From: Jun Lei <Jun.Lei@amd.com>
+Date: Mon, 22 Jul 2019 09:45:20 -0400
+Subject: [PATCH 3418/4256] 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: Jun Lei <Jun.Lei@amd.com>
+Reviewed-by: Eric Yang <eric.yang2@amd.com>
+Acked-by: Leo Li <sunpeng.li@amd.com>
+---
+ .../drm/amd/display/dc/dcn20/dcn20_resource.c | 72 ++++++++++++++++++-
+ 1 file changed, 70 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+index af8ab57a8af5..bdd3478f80ee 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+@@ -2126,6 +2126,74 @@ static bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx)
+ }
+ #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(
+ struct dc *dc,
+ struct dc_state *context,
+@@ -2279,7 +2347,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)
+ 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]) {
+- 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);
+ if (!dcn20_split_stream_for_combine(
+ &context->res_ctx, dc->res_pool,
+@@ -2320,7 +2388,7 @@ bool dcn20_fast_validate_bw(
+ if (need_split3d || need_split || force_split) {
+ if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state) {
+ /* 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);
+ if (!hsplit_pipe)
+ continue;
+--
+2.17.1
+