diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4072-drm-amd-display-add-more-checks-to-validate-seamless.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4072-drm-amd-display-add-more-checks-to-validate-seamless.patch | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4072-drm-amd-display-add-more-checks-to-validate-seamless.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4072-drm-amd-display-add-more-checks-to-validate-seamless.patch new file mode 100644 index 00000000..07321739 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4072-drm-amd-display-add-more-checks-to-validate-seamless.patch @@ -0,0 +1,387 @@ +From a3434a791c3fc3a0935356e45f4b38f880d36f12 Mon Sep 17 00:00:00 2001 +From: Martin Leung <martin.leung@amd.com> +Date: Tue, 17 Sep 2019 14:50:22 -0400 +Subject: [PATCH 4072/4256] drm/amd/display: add more checks to validate + seamless boot timing + +[why] +we found using an active DP to HDMI panel that we weren't validating +dp_pixel_format and hardware timing v_front_porch, causing screen to +blank and/or corrupt while attempting a seamless boot. + +[how] +added checks during dc_validate_seamless_boot_timing for these values + +Signed-off-by: Martin Leung <martin.leung@amd.com> +Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> +Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 61 +++++++++++++++++- + .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.c | 60 ++++-------------- + .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.h | 5 +- + .../display/dc/dcn10/dcn10_stream_encoder.c | 62 +++++++++++++++++++ + .../display/dc/dcn10/dcn10_stream_encoder.h | 5 ++ + .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 2 +- + .../display/dc/dcn20/dcn20_stream_encoder.c | 4 ++ + .../amd/display/dc/inc/hw/stream_encoder.h | 5 ++ + .../amd/display/dc/inc/hw/timing_generator.h | 2 + + 9 files changed, 153 insertions(+), 53 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 85be4db9dcbf..f89766a5cc72 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -1001,6 +1001,10 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc, + struct dc_crtc_timing *crtc_timing) + { + struct timing_generator *tg; ++ struct stream_encoder *se; ++ ++ struct dc_crtc_timing hw_crtc_timing = {0}; ++ + struct dc_link *link = sink->link; + unsigned int i, enc_inst, tg_inst = 0; + +@@ -1020,6 +1024,9 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc, + + for (i = 0; i < dc->res_pool->stream_enc_count; i++) { + if (dc->res_pool->stream_enc[i]->id == enc_inst) { ++ ++ se = dc->res_pool->stream_enc[i]; ++ + tg_inst = dc->res_pool->stream_enc[i]->funcs->dig_source_otg( + dc->res_pool->stream_enc[i]); + break; +@@ -1035,10 +1042,46 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc, + + tg = dc->res_pool->timing_generators[tg_inst]; + +- if (!tg->funcs->is_matching_timing) ++ if (!tg->funcs->get_hw_timing) ++ return false; ++ ++ if (!tg->funcs->get_hw_timing(tg, &hw_crtc_timing)) ++ return false; ++ ++ if (crtc_timing->h_total != hw_crtc_timing.h_total) ++ return false; ++ ++ if (crtc_timing->h_border_left != hw_crtc_timing.h_border_left) ++ return false; ++ ++ if (crtc_timing->h_addressable != hw_crtc_timing.h_addressable) ++ return false; ++ ++ if (crtc_timing->h_border_right != hw_crtc_timing.h_border_right) ++ return false; ++ ++ if (crtc_timing->h_front_porch != hw_crtc_timing.h_front_porch) ++ return false; ++ ++ if (crtc_timing->h_sync_width != hw_crtc_timing.h_sync_width) + return false; + +- if (!tg->funcs->is_matching_timing(tg, crtc_timing)) ++ if (crtc_timing->v_total != hw_crtc_timing.v_total) ++ return false; ++ ++ if (crtc_timing->v_border_top != hw_crtc_timing.v_border_top) ++ return false; ++ ++ if (crtc_timing->v_addressable != hw_crtc_timing.v_addressable) ++ return false; ++ ++ if (crtc_timing->v_border_bottom != hw_crtc_timing.v_border_bottom) ++ return false; ++ ++ if (crtc_timing->v_front_porch != hw_crtc_timing.v_front_porch) ++ return false; ++ ++ if (crtc_timing->v_sync_width != hw_crtc_timing.v_sync_width) + return false; + + if (dc_is_dp_signal(link->connector_signal)) { +@@ -1051,6 +1094,20 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc, + if (crtc_timing->pix_clk_100hz != pix_clk_100hz) + return false; + ++ if (!se->funcs->dp_get_pixel_format) ++ return false; ++ ++ if (!se->funcs->dp_get_pixel_format( ++ se, ++ &hw_crtc_timing.pixel_encoding, ++ &hw_crtc_timing.display_color_depth)) ++ return false; ++ ++ if (hw_crtc_timing.display_color_depth != crtc_timing->display_color_depth) ++ return false; ++ ++ if (hw_crtc_timing.pixel_encoding != crtc_timing->pixel_encoding) ++ return false; + } + + return true; +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +index f3cade20e45c..8710f3ac2abf 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +@@ -1238,59 +1238,25 @@ bool optc1_is_stereo_left_eye(struct timing_generator *optc) + return ret; + } + +-bool optc1_is_matching_timing(struct timing_generator *tg, +- const struct dc_crtc_timing *otg_timing) ++bool optc1_get_hw_timing(struct timing_generator *tg, ++ struct dc_crtc_timing *hw_crtc_timing) + { +- struct dc_crtc_timing hw_crtc_timing = {0}; + struct dcn_otg_state s = {0}; + +- if (tg == NULL || otg_timing == NULL) ++ if (tg == NULL || hw_crtc_timing == NULL) + return false; + + optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s); + +- hw_crtc_timing.h_total = s.h_total + 1; +- hw_crtc_timing.h_addressable = s.h_total - ((s.h_total - s.h_blank_start) + s.h_blank_end); +- hw_crtc_timing.h_front_porch = s.h_total + 1 - s.h_blank_start; +- hw_crtc_timing.h_sync_width = s.h_sync_a_end - s.h_sync_a_start; ++ hw_crtc_timing->h_total = s.h_total + 1; ++ hw_crtc_timing->h_addressable = s.h_total - ((s.h_total - s.h_blank_start) + s.h_blank_end); ++ hw_crtc_timing->h_front_porch = s.h_total + 1 - s.h_blank_start; ++ hw_crtc_timing->h_sync_width = s.h_sync_a_end - s.h_sync_a_start; + +- hw_crtc_timing.v_total = s.v_total + 1; +- hw_crtc_timing.v_addressable = s.v_total - ((s.v_total - s.v_blank_start) + s.v_blank_end); +- hw_crtc_timing.v_front_porch = s.v_total + 1 - s.v_blank_start; +- hw_crtc_timing.v_sync_width = s.v_sync_a_end - s.v_sync_a_start; +- +- if (otg_timing->h_total != hw_crtc_timing.h_total) +- return false; +- +- if (otg_timing->h_border_left != hw_crtc_timing.h_border_left) +- return false; +- +- if (otg_timing->h_addressable != hw_crtc_timing.h_addressable) +- return false; +- +- if (otg_timing->h_border_right != hw_crtc_timing.h_border_right) +- return false; +- +- if (otg_timing->h_front_porch != hw_crtc_timing.h_front_porch) +- return false; +- +- if (otg_timing->h_sync_width != hw_crtc_timing.h_sync_width) +- return false; +- +- if (otg_timing->v_total != hw_crtc_timing.v_total) +- return false; +- +- if (otg_timing->v_border_top != hw_crtc_timing.v_border_top) +- return false; +- +- if (otg_timing->v_addressable != hw_crtc_timing.v_addressable) +- return false; +- +- if (otg_timing->v_border_bottom != hw_crtc_timing.v_border_bottom) +- return false; +- +- if (otg_timing->v_sync_width != hw_crtc_timing.v_sync_width) +- return false; ++ hw_crtc_timing->v_total = s.v_total + 1; ++ hw_crtc_timing->v_addressable = s.v_total - ((s.v_total - s.v_blank_start) + s.v_blank_end); ++ hw_crtc_timing->v_front_porch = s.v_total + 1 - s.v_blank_start; ++ hw_crtc_timing->v_sync_width = s.v_sync_a_end - s.v_sync_a_start; + + return true; + } +@@ -1494,7 +1460,6 @@ static const struct timing_generator_funcs dcn10_tg_funcs = { + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .get_otg_active_size = optc1_get_otg_active_size, +- .is_matching_timing = optc1_is_matching_timing, + .set_early_control = optc1_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = optc1_wait_for_state, +@@ -1522,7 +1487,8 @@ static const struct timing_generator_funcs dcn10_tg_funcs = { + .configure_crc = optc1_configure_crc, + .set_vtg_params = optc1_set_vtg_params, + .program_manual_trigger = optc1_program_manual_trigger, +- .setup_manual_trigger = optc1_setup_manual_trigger ++ .setup_manual_trigger = optc1_setup_manual_trigger, ++ .get_hw_timing = optc1_get_hw_timing, + }; + + void dcn10_timing_generator_init(struct optc *optc1) +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +index 83575599672e..c8d795b335ba 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +@@ -547,9 +547,8 @@ struct dcn_otg_state { + void optc1_read_otg_state(struct optc *optc1, + struct dcn_otg_state *s); + +-bool optc1_is_matching_timing( +- struct timing_generator *tg, +- const struct dc_crtc_timing *otg_timing); ++bool optc1_get_hw_timing(struct timing_generator *tg, ++ struct dc_crtc_timing *hw_crtc_timing); + + bool optc1_validate_timing( + struct timing_generator *optc, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +index 6800b906a86e..f10c1554ec01 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +@@ -1552,6 +1552,66 @@ unsigned int enc1_dig_source_otg( + return tg_inst; + } + ++bool enc1_stream_encoder_dp_get_pixel_format( ++ struct stream_encoder *enc, ++ enum dc_pixel_encoding *encoding, ++ enum dc_color_depth *depth) ++{ ++ uint32_t hw_encoding = 0; ++ uint32_t hw_depth = 0; ++ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); ++ ++ if (enc == NULL || ++ encoding == NULL || ++ depth == NULL) ++ return false; ++ ++ REG_GET_2(DP_PIXEL_FORMAT, ++ DP_PIXEL_ENCODING, &hw_encoding, ++ DP_COMPONENT_DEPTH, &hw_depth); ++ ++ switch (hw_depth) { ++ case DP_COMPONENT_PIXEL_DEPTH_6BPC: ++ *depth = COLOR_DEPTH_666; ++ break; ++ case DP_COMPONENT_PIXEL_DEPTH_8BPC: ++ *depth = COLOR_DEPTH_888; ++ break; ++ case DP_COMPONENT_PIXEL_DEPTH_10BPC: ++ *depth = COLOR_DEPTH_101010; ++ break; ++ case DP_COMPONENT_PIXEL_DEPTH_12BPC: ++ *depth = COLOR_DEPTH_121212; ++ break; ++ case DP_COMPONENT_PIXEL_DEPTH_16BPC: ++ *depth = COLOR_DEPTH_161616; ++ break; ++ default: ++ *depth = COLOR_DEPTH_UNDEFINED; ++ break; ++ } ++ ++ switch (hw_encoding) { ++ case DP_PIXEL_ENCODING_TYPE_RGB444: ++ *encoding = PIXEL_ENCODING_RGB; ++ break; ++ case DP_PIXEL_ENCODING_TYPE_YCBCR422: ++ *encoding = PIXEL_ENCODING_YCBCR422; ++ break; ++ case DP_PIXEL_ENCODING_TYPE_YCBCR444: ++ case DP_PIXEL_ENCODING_TYPE_Y_ONLY: ++ *encoding = PIXEL_ENCODING_YCBCR444; ++ break; ++ case DP_PIXEL_ENCODING_TYPE_YCBCR420: ++ *encoding = PIXEL_ENCODING_YCBCR420; ++ break; ++ default: ++ *encoding = PIXEL_ENCODING_UNDEFINED; ++ break; ++ } ++ return true; ++} ++ + static const struct stream_encoder_funcs dcn10_str_enc_funcs = { + .dp_set_stream_attribute = + enc1_stream_encoder_dp_set_stream_attribute, +@@ -1588,6 +1648,8 @@ static const struct stream_encoder_funcs dcn10_str_enc_funcs = { + .dig_connect_to_otg = enc1_dig_connect_to_otg, + .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, + .dig_source_otg = enc1_dig_source_otg, ++ ++ .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, + }; + + void dcn10_stream_encoder_construct( +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +index a512cbea00d1..c9cbc21d121e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +@@ -621,4 +621,9 @@ void get_audio_clock_info( + void enc1_reset_hdmi_stream_attribute( + struct stream_encoder *enc); + ++bool enc1_stream_encoder_dp_get_pixel_format( ++ struct stream_encoder *enc, ++ enum dc_pixel_encoding *encoding, ++ enum dc_color_depth *depth); ++ + #endif /* __DC_STREAM_ENCODER_DCN10_H__ */ +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c +index dda90995ba93..3b613fb93ef8 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c +@@ -460,7 +460,7 @@ static struct timing_generator_funcs dcn20_tg_funcs = { + .set_vtg_params = optc1_set_vtg_params, + .program_manual_trigger = optc2_program_manual_trigger, + .setup_manual_trigger = optc2_setup_manual_trigger, +- .is_matching_timing = optc1_is_matching_timing ++ .get_hw_timing = optc1_get_hw_timing, + }; + + void dcn20_timing_generator_init(struct optc *optc1) +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c +index b7d977b4b0d5..412d3032e4ef 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c +@@ -576,6 +576,10 @@ static const struct stream_encoder_funcs dcn20_str_enc_funcs = { + .set_avmute = enc1_stream_encoder_set_avmute, + .dig_connect_to_otg = enc1_dig_connect_to_otg, + .dig_source_otg = enc1_dig_source_otg, ++ ++ .dp_get_pixel_format = ++ enc1_stream_encoder_dp_get_pixel_format, ++ + #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT + .enc_read_state = enc2_read_state, + .dp_set_dsc_config = enc2_dp_set_dsc_config, +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +index fe9b7a10a1c3..6305e388612a 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +@@ -214,6 +214,11 @@ struct stream_encoder_funcs { + unsigned int (*dig_source_otg)( + struct stream_encoder *enc); + ++ bool (*dp_get_pixel_format)( ++ struct stream_encoder *enc, ++ enum dc_pixel_encoding *encoding, ++ enum dc_color_depth *depth); ++ + #if defined(CONFIG_DRM_AMD_DC_DCN2_0) + #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT + void (*enc_read_state)(struct stream_encoder *enc, struct enc_state *s); +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +index 6196cc32356e..27c73caf74ee 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +@@ -261,6 +261,8 @@ struct timing_generator_funcs { + + void (*program_manual_trigger)(struct timing_generator *optc); + void (*setup_manual_trigger)(struct timing_generator *optc); ++ bool (*get_hw_timing)(struct timing_generator *optc, ++ struct dc_crtc_timing *hw_crtc_timing); + + void (*set_vtg_params)(struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing); +-- +2.17.1 + |