From: George Shen <george.shen@xxxxxxx> [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.liu@xxxxxxx> Acked-by: Tom Chung <chiahsuan.chung@xxxxxxx> Signed-off-by: George Shen <george.shen@xxxxxxx> --- 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(¶ms, 0, sizeof(params)); + odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms); + 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(¶ms, 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, ¶ms); 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, ¶ms); - 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, ¶ms); 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, ¶ms); - 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