drm/amd/display: add pipe reassignment prevention code to dcn3
authorDmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Mon, 28 Sep 2020 21:59:38 +0000 (17:59 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 30 Sep 2020 17:50:22 +0000 (13:50 -0400)
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 <Dmytro.Laktyushkin@amd.com>
Reviewed-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c

index c223f8a..24fb39a 100644 (file)
@@ -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;