From: George Shen <george.s...@amd.com>

[Why]
Current DPG test pattern logic does not account for ODM configuration
changes after test pattern has already been programmed. For example, if
ODM2:1 is enabled after test pattern is already being output, the second
pipe is not programmed to output test pattern, causing half the screen
to be black.

[How]
Move DPG test pattern parameter calculations into separate function.
Whenever ODM pipe configuration changes, re-calculate DPG test pattern
parameters and program DPG if test pattern is currently enabled.

Reviewed-by: Wenjing Liu <wenjing....@amd.com>
Acked-by: Tom Chung <chiahsuan.ch...@amd.com>
Signed-off-by: George Shen <george.s...@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c      |   8 ++
 .../gpu/drm/amd/display/dc/core/dc_resource.c | 104 ++++++++++++++++
 .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c   |  22 ++++
 .../gpu/drm/amd/display/dc/inc/core_types.h   |  13 ++
 drivers/gpu/drm/amd/display/dc/inc/resource.h |   4 +
 .../display/dc/link/accessories/link_dp_cts.c | 117 ++++--------------
 6 files changed, 175 insertions(+), 93 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 88d41bf6d53a..544c915469f9 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3145,6 +3145,14 @@ static bool update_planes_and_stream_state(struct dc *dc,
                        BREAK_TO_DEBUGGER();
                        goto fail;
                }
+
+               for (i = 0; i < context->stream_count; i++) {
+                       struct pipe_ctx *otg_master = 
resource_get_otg_master_for_stream(&context->res_ctx,
+                                       context->streams[i]);
+
+                       if (otg_master->stream->test_pattern.type != 
DP_TEST_PATTERN_VIDEO_MODE)
+                               
resource_build_test_pattern_params(&context->res_ctx, otg_master);
+               }
        }
 
        *new_context = context;
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 3549a9b852a2..22e05f3d01e0 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1360,6 +1360,110 @@ static bool is_subvp_high_refresh_candidate(struct 
dc_stream_state *stream)
        return false;
 }
 
+static enum controller_dp_test_pattern convert_dp_to_controller_test_pattern(
+                               enum dp_test_pattern test_pattern)
+{
+       enum controller_dp_test_pattern controller_test_pattern;
+
+       switch (test_pattern) {
+       case DP_TEST_PATTERN_COLOR_SQUARES:
+               controller_test_pattern =
+                               CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
+       break;
+       case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
+               controller_test_pattern =
+                               CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
+       break;
+       case DP_TEST_PATTERN_VERTICAL_BARS:
+               controller_test_pattern =
+                               CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
+       break;
+       case DP_TEST_PATTERN_HORIZONTAL_BARS:
+               controller_test_pattern =
+                               CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
+       break;
+       case DP_TEST_PATTERN_COLOR_RAMP:
+               controller_test_pattern =
+                               CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
+       break;
+       default:
+               controller_test_pattern =
+                               CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
+       break;
+       }
+
+       return controller_test_pattern;
+}
+
+static enum controller_dp_color_space convert_dp_to_controller_color_space(
+               enum dp_test_pattern_color_space color_space)
+{
+       enum controller_dp_color_space controller_color_space;
+
+       switch (color_space) {
+       case DP_TEST_PATTERN_COLOR_SPACE_RGB:
+               controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
+               break;
+       case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
+               controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
+               break;
+       case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
+               controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
+               break;
+       case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
+       default:
+               controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
+               break;
+       }
+
+       return controller_color_space;
+}
+
+void resource_build_test_pattern_params(struct resource_context *res_ctx,
+                               struct pipe_ctx *otg_master)
+{
+       int odm_slice_width, last_odm_slice_width, offset = 0;
+       struct pipe_ctx *opp_heads[MAX_PIPES];
+       struct test_pattern_params *params;
+       int odm_cnt = 1;
+       enum controller_dp_test_pattern controller_test_pattern;
+       enum controller_dp_color_space controller_color_space;
+       enum dc_color_depth color_depth = 
otg_master->stream->timing.display_color_depth;
+       int h_active = otg_master->stream->timing.h_addressable +
+               otg_master->stream->timing.h_border_left +
+               otg_master->stream->timing.h_border_right;
+       int v_active = otg_master->stream->timing.v_addressable +
+               otg_master->stream->timing.v_border_bottom +
+               otg_master->stream->timing.v_border_top;
+       int i;
+
+       controller_test_pattern = convert_dp_to_controller_test_pattern(
+                       otg_master->stream->test_pattern.type);
+       controller_color_space = convert_dp_to_controller_color_space(
+                       otg_master->stream->test_pattern.color_space);
+
+       odm_cnt = resource_get_opp_heads_for_otg_master(otg_master, res_ctx, 
opp_heads);
+
+       odm_slice_width = h_active / odm_cnt;
+       last_odm_slice_width = h_active - odm_slice_width * (odm_cnt - 1);
+
+       for (i = 0; i < odm_cnt; i++) {
+               params = &opp_heads[i]->stream_res.test_pattern_params;
+               params->test_pattern = controller_test_pattern;
+               params->color_space = controller_color_space;
+               params->color_depth = color_depth;
+               params->height = v_active;
+               params->offset = offset;
+
+               if (i < odm_cnt - 1)
+                       params->width = odm_slice_width;
+               else
+                       params->width = last_odm_slice_width;
+
+               offset += odm_slice_width;
+       }
+}
+
 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
 {
        const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index d8c02f83b7d7..4d6493e0ccfc 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -1538,6 +1538,11 @@ static void dcn20_detect_pipe_changes(struct pipe_ctx 
*old_pipe, struct pipe_ctx
 
        if (old_pipe->unbounded_req != new_pipe->unbounded_req)
                new_pipe->update_flags.bits.unbounded_req = 1;
+
+       if (memcmp(&old_pipe->stream_res.test_pattern_params,
+                               &new_pipe->stream_res.test_pattern_params, 
sizeof(struct test_pattern_params))) {
+               new_pipe->update_flags.bits.test_pattern_changed = 1;
+       }
 }
 
 static void dcn20_update_dchubp_dpp(
@@ -1846,6 +1851,23 @@ static void dcn20_program_pipe(
                                pipe_ctx->stream->abm_level);
                }
        }
+
+       if (pipe_ctx->update_flags.bits.test_pattern_changed) {
+               struct output_pixel_processor *odm_opp = 
pipe_ctx->stream_res.opp;
+               struct bit_depth_reduction_params params;
+
+               memset(&params, 0, sizeof(params));
+               odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, 
&params);
+               dc->hwss.set_disp_pattern_generator(dc,
+                               pipe_ctx,
+                               
pipe_ctx->stream_res.test_pattern_params.test_pattern,
+                               
pipe_ctx->stream_res.test_pattern_params.color_space,
+                               
pipe_ctx->stream_res.test_pattern_params.color_depth,
+                               NULL,
+                               pipe_ctx->stream_res.test_pattern_params.width,
+                               pipe_ctx->stream_res.test_pattern_params.height,
+                               
pipe_ctx->stream_res.test_pattern_params.offset);
+       }
 }
 
 void dcn20_program_front_end_for_ctx(
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h 
b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
index c095ccbb80c4..92e52b218150 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -308,6 +308,16 @@ struct dcn_fe_bandwidth {
 
 };
 
+/* Parameters needed to call set_disp_pattern_generator */
+struct test_pattern_params {
+       enum controller_dp_test_pattern test_pattern;
+       enum controller_dp_color_space color_space;
+       enum dc_color_depth color_depth;
+       int width;
+       int height;
+       int offset;
+};
+
 struct stream_resource {
        struct output_pixel_processor *opp;
        struct display_stream_compressor *dsc;
@@ -324,6 +334,8 @@ struct stream_resource {
         * otherwise it's using group number 'gsl_group-1'
         */
        uint8_t gsl_group;
+
+       struct test_pattern_params test_pattern_params;
 };
 
 struct plane_resource {
@@ -367,6 +379,7 @@ union pipe_update_flags {
                uint32_t plane_changed : 1;
                uint32_t det_size : 1;
                uint32_t unbounded_req : 1;
+               uint32_t test_pattern_changed : 1;
        } bits;
        uint32_t raw;
 };
diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h 
b/drivers/gpu/drm/amd/display/dc/inc/resource.h
index 67d1ec0f3c68..06ca8bfb91e7 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
@@ -103,6 +103,10 @@ enum dc_status resource_map_pool_resources(
                struct dc_state *context,
                struct dc_stream_state *stream);
 
+void resource_build_test_pattern_params(
+               struct resource_context *res_ctx,
+               struct pipe_ctx *pipe_ctx);
+
 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx);
 
 enum dc_status resource_build_scaling_params_for_context(
diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c 
b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
index fe4282771cd0..0894e6aef3dd 100644
--- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
+++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
@@ -429,49 +429,13 @@ static void set_crtc_test_pattern(struct dc_link *link,
        struct bit_depth_reduction_params params;
        struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
        struct pipe_ctx *odm_pipe;
-       int odm_cnt = 1;
-       int h_active = pipe_ctx->stream->timing.h_addressable +
-               pipe_ctx->stream->timing.h_border_left +
-               pipe_ctx->stream->timing.h_border_right;
-       int v_active = pipe_ctx->stream->timing.v_addressable +
-               pipe_ctx->stream->timing.v_border_bottom +
-               pipe_ctx->stream->timing.v_border_top;
-       int odm_slice_width, last_odm_slice_width, offset = 0;
+       struct test_pattern_params *tp_params;
 
        memset(&params, 0, sizeof(params));
 
-       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = 
odm_pipe->next_odm_pipe)
-               odm_cnt++;
-
-       odm_slice_width = h_active / odm_cnt;
-       last_odm_slice_width = h_active - odm_slice_width * (odm_cnt - 1);
-
-       switch (test_pattern) {
-       case DP_TEST_PATTERN_COLOR_SQUARES:
-               controller_test_pattern =
-                               CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
-       break;
-       case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
-               controller_test_pattern =
-                               CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
-       break;
-       case DP_TEST_PATTERN_VERTICAL_BARS:
-               controller_test_pattern =
-                               CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
-       break;
-       case DP_TEST_PATTERN_HORIZONTAL_BARS:
-               controller_test_pattern =
-                               CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
-       break;
-       case DP_TEST_PATTERN_COLOR_RAMP:
-               controller_test_pattern =
-                               CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
-       break;
-       default:
-               controller_test_pattern =
-                               CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
-       break;
-       }
+       resource_build_test_pattern_params(&link->dc->current_state->res_ctx,
+                       pipe_ctx);
+       controller_test_pattern = 
pipe_ctx->stream_res.test_pattern_params.test_pattern;
 
        switch (test_pattern) {
        case DP_TEST_PATTERN_COLOR_SQUARES:
@@ -490,51 +454,29 @@ static void set_crtc_test_pattern(struct dc_link *link,
                        enum controller_dp_color_space controller_color_space;
                        struct output_pixel_processor *odm_opp;
 
-                       switch (test_pattern_color_space) {
-                       case DP_TEST_PATTERN_COLOR_SPACE_RGB:
-                               controller_color_space = 
CONTROLLER_DP_COLOR_SPACE_RGB;
-                               break;
-                       case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
-                               controller_color_space = 
CONTROLLER_DP_COLOR_SPACE_YCBCR601;
-                               break;
-                       case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
-                               controller_color_space = 
CONTROLLER_DP_COLOR_SPACE_YCBCR709;
-                               break;
-                       case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
-                       default:
-                               controller_color_space = 
CONTROLLER_DP_COLOR_SPACE_UDEFINED;
-                               DC_LOG_ERROR("%s: Color space must be defined 
for test pattern", __func__);
+                       controller_color_space = 
pipe_ctx->stream_res.test_pattern_params.color_space;
+
+                       if (controller_color_space == 
CONTROLLER_DP_COLOR_SPACE_UDEFINED) {
+                               DC_LOG_WARNING("%s: Color space must be defined 
for test pattern", __func__);
                                ASSERT(0);
-                               break;
                        }
 
                        odm_pipe = pipe_ctx;
-                       while (odm_pipe->next_odm_pipe) {
+                       while (odm_pipe) {
+                               tp_params = 
&odm_pipe->stream_res.test_pattern_params;
                                odm_opp = odm_pipe->stream_res.opp;
                                
odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
                                
link->dc->hwss.set_disp_pattern_generator(link->dc,
                                                odm_pipe,
-                                               controller_test_pattern,
-                                               controller_color_space,
-                                               color_depth,
+                                               tp_params->test_pattern,
+                                               tp_params->color_space,
+                                               tp_params->color_depth,
                                                NULL,
-                                               odm_slice_width,
-                                               v_active,
-                                               offset);
-                               offset += odm_slice_width;
+                                               tp_params->width,
+                                               tp_params->height,
+                                               tp_params->offset);
                                odm_pipe = odm_pipe->next_odm_pipe;
                        }
-                       odm_opp = odm_pipe->stream_res.opp;
-                       
odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
-                       link->dc->hwss.set_disp_pattern_generator(link->dc,
-                                       odm_pipe,
-                                       controller_test_pattern,
-                                       controller_color_space,
-                                       color_depth,
-                                       NULL,
-                                       last_odm_slice_width,
-                                       v_active,
-                                       offset);
                }
        }
        break;
@@ -552,32 +494,21 @@ static void set_crtc_test_pattern(struct dc_link *link,
                        struct output_pixel_processor *odm_opp;
 
                        odm_pipe = pipe_ctx;
-                       while (odm_pipe->next_odm_pipe) {
+                       while (odm_pipe) {
+                               tp_params = 
&odm_pipe->stream_res.test_pattern_params;
                                odm_opp = odm_pipe->stream_res.opp;
                                
odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
                                
link->dc->hwss.set_disp_pattern_generator(link->dc,
                                                odm_pipe,
-                                               
CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
-                                               
CONTROLLER_DP_COLOR_SPACE_UDEFINED,
-                                               color_depth,
+                                               tp_params->test_pattern,
+                                               tp_params->color_space,
+                                               tp_params->color_depth,
                                                NULL,
-                                               odm_slice_width,
-                                               v_active,
-                                               offset);
-                               offset += odm_slice_width;
+                                               tp_params->width,
+                                               tp_params->height,
+                                               tp_params->offset);
                                odm_pipe = odm_pipe->next_odm_pipe;
                        }
-                       odm_opp = odm_pipe->stream_res.opp;
-                       
odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
-                       link->dc->hwss.set_disp_pattern_generator(link->dc,
-                                       odm_pipe,
-                                       CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
-                                       CONTROLLER_DP_COLOR_SPACE_UDEFINED,
-                                       color_depth,
-                                       NULL,
-                                       last_odm_slice_width,
-                                       v_active,
-                                       offset);
                }
        }
        break;
-- 
2.25.1

Reply via email to