aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4072-drm-amd-display-add-more-checks-to-validate-seamless.patch
diff options
context:
space:
mode:
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.patch387
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
+