aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3843-drm-amd-display-enable-single-dp-seamless-boot.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3843-drm-amd-display-enable-single-dp-seamless-boot.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3843-drm-amd-display-enable-single-dp-seamless-boot.patch255
1 files changed, 255 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3843-drm-amd-display-enable-single-dp-seamless-boot.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3843-drm-amd-display-enable-single-dp-seamless-boot.patch
new file mode 100644
index 00000000..1105730a
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3843-drm-amd-display-enable-single-dp-seamless-boot.patch
@@ -0,0 +1,255 @@
+From 3fd571fd36708e2dd7c6873038e113251468d836 Mon Sep 17 00:00:00 2001
+From: Martin Leung <martin.leung@amd.com>
+Date: Fri, 16 Aug 2019 17:26:23 -0400
+Subject: [PATCH 3843/4256] drm/amd/display: enable single dp seamless boot
+
+[why]
+seamless boot didn't work for non edp's before
+
+[how]
+removed edp-specific code, made dp read uefi-set link settings. Also fixed
+a hubbub code line to be consistent with usage of function.
+
+Signed-off-by: Martin Leung <martin.leung@amd.com>
+Reviewed-by: Jun Lei <Jun.Lei@amd.com>
+Acked-by: Anthony Koo <Anthony.Koo@amd.com>
+Acked-by: Leo Li <sunpeng.li@amd.com>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 30 +++++-----
+ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 57 ++++++++++++-------
+ .../gpu/drm/amd/display/dc/core/dc_resource.c | 26 ++++-----
+ .../drm/amd/display/dc/dcn20/dcn20_hubbub.c | 5 +-
+ 4 files changed, 71 insertions(+), 47 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index ffa6544f1e25..e5fd65f634ac 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -983,29 +983,33 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc,
+ {
+ struct timing_generator *tg;
+ struct dc_link *link = sink->link;
+- unsigned int enc_inst, tg_inst;
++ unsigned int enc_inst, tg_inst, i;
++
++ // Seamless port only support single DP and EDP so far
++ if (sink->sink_signal != SIGNAL_TYPE_DISPLAY_PORT &&
++ sink->sink_signal != SIGNAL_TYPE_EDP)
++ return false;
+
+ /* Check for enabled DIG to identify enabled display */
+ if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
+ return false;
+
+- /* Check for which front end is used by this encoder.
+- * Note the inst is 1 indexed, where 0 is undefined.
+- * Note that DIG_FE can source from different OTG but our
+- * current implementation always map 1-to-1, so this code makes
+- * the same assumption and doesn't check OTG source.
+- */
+ enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
+
+- /* Instance should be within the range of the pool */
+- if (enc_inst >= dc->res_pool->pipe_count)
++ if (enc_inst == ENGINE_ID_UNKNOWN)
+ return false;
+
+- if (enc_inst >= dc->res_pool->stream_enc_count)
+- return false;
++ for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
++ if (dc->res_pool->stream_enc[i]->id == enc_inst) {
++ tg_inst = dc->res_pool->stream_enc[i]->funcs->dig_source_otg(
++ dc->res_pool->stream_enc[i]);
++ break;
++ }
++ }
+
+- tg_inst = dc->res_pool->stream_enc[enc_inst]->funcs->dig_source_otg(
+- dc->res_pool->stream_enc[enc_inst]);
++ // tg_inst not found
++ if (i == dc->res_pool->stream_enc_count)
++ return false;
+
+ if (tg_inst >= dc->res_pool->timing_generator_count)
+ return false;
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+index a20310feb352..66758033757d 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+@@ -517,7 +517,7 @@ static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *lin
+ }
+
+
+-static void read_edp_current_link_settings_on_detect(struct dc_link *link)
++static void read_current_link_settings_on_detect(struct dc_link *link)
+ {
+ union lane_count_set lane_count_set = { {0} };
+ uint8_t link_bw_set;
+@@ -552,17 +552,23 @@ static void read_edp_current_link_settings_on_detect(struct dc_link *link)
+ &link_bw_set, sizeof(link_bw_set));
+
+ if (link_bw_set == 0) {
+- /* If standard link rates are not being used,
+- * Read DPCD 00115h to find the link rate set used
+- */
+- core_link_read_dpcd(link, DP_LINK_RATE_SET,
+- &link_rate_set, sizeof(link_rate_set));
+-
+- if (link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
+- link->cur_link_settings.link_rate =
+- link->dpcd_caps.edp_supported_link_rates[link_rate_set];
+- link->cur_link_settings.link_rate_set = link_rate_set;
+- link->cur_link_settings.use_link_rate_set = true;
++ if (link->connector_signal == SIGNAL_TYPE_EDP) {
++ /* If standard link rates are not being used,
++ * Read DPCD 00115h to find the edp link rate set used
++ */
++ core_link_read_dpcd(link, DP_LINK_RATE_SET,
++ &link_rate_set, sizeof(link_rate_set));
++
++ // edp_supported_link_rates_count = 0 for DP
++ if (link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
++ link->cur_link_settings.link_rate =
++ link->dpcd_caps.edp_supported_link_rates[link_rate_set];
++ link->cur_link_settings.link_rate_set = link_rate_set;
++ link->cur_link_settings.use_link_rate_set = true;
++ }
++ } else {
++ // Link Rate not found. Seamless boot may not work.
++ ASSERT(false);
+ }
+ } else {
+ link->cur_link_settings.link_rate = link_bw_set;
+@@ -750,6 +756,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
+ struct dpcd_caps prev_dpcd_caps;
+ bool same_dpcd = true;
+ enum dc_connection_type new_connection_type = dc_connection_none;
++ bool perform_dp_seamless_boot = false;
+ DC_LOGGER_INIT(link->ctx->logger);
+
+ if (dc_is_virtual_signal(link->connector_signal))
+@@ -806,15 +813,15 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
+ }
+
+ case SIGNAL_TYPE_EDP: {
+- read_edp_current_link_settings_on_detect(link);
++ read_current_link_settings_on_detect(link);
+ detect_edp_sink_caps(link);
+- sink_caps.transaction_type =
+- DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
++ sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+ sink_caps.signal = SIGNAL_TYPE_EDP;
+ break;
+ }
+
+ case SIGNAL_TYPE_DISPLAY_PORT: {
++
+ /* wa HPD high coming too early*/
+ if (link->link_enc->features.flags.bits.DP_IS_USB_C == 1) {
+
+@@ -868,6 +875,17 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
+ return false;
+ }
+
++ // For seamless boot, to skip verify link cap, we read UEFI settings and set them as verified.
++ if (reason == DETECT_REASON_BOOT &&
++ dc_ctx->dc->config.power_down_display_on_boot == false &&
++ link->link_status.link_active == true)
++ perform_dp_seamless_boot = true;
++
++ if (perform_dp_seamless_boot) {
++ read_current_link_settings_on_detect(link);
++ link->verified_link_cap = link->reported_link_cap;
++ }
++
+ break;
+ }
+
+@@ -952,10 +970,11 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
+ * two link trainings
+ */
+
+- /* deal with non-mst cases */
+- dp_verify_link_cap_with_retries(link,
+- &link->reported_link_cap,
+- LINK_TRAINING_MAX_VERIFY_RETRY);
++ // verify link cap for SST non-seamless boot
++ if (!perform_dp_seamless_boot)
++ dp_verify_link_cap_with_retries(link,
++ &link->reported_link_cap,
++ LINK_TRAINING_MAX_VERIFY_RETRY);
+ } else {
+ // If edid is the same, then discard new sink and revert back to original sink
+ if (same_edid) {
+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 2ae883a248da..af85d6cf4427 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -1845,28 +1845,28 @@ static int acquire_resource_from_hw_enabled_state(
+ struct dc_stream_state *stream)
+ {
+ struct dc_link *link = stream->link;
+- unsigned int inst, tg_inst;
++ unsigned int inst, tg_inst, i;
+
+ /* Check for enabled DIG to identify enabled display */
+ if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
+ return -1;
+
+- /* Check for which front end is used by this encoder.
+- * Note the inst is 1 indexed, where 0 is undefined.
+- * Note that DIG_FE can source from different OTG but our
+- * current implementation always map 1-to-1, so this code makes
+- * the same assumption and doesn't check OTG source.
+- */
+ inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
+
+- /* Instance should be within the range of the pool */
+- if (inst >= pool->pipe_count)
+- return -1;
++ if (inst == ENGINE_ID_UNKNOWN)
++ return false;
+
+- if (inst >= pool->stream_enc_count)
+- return -1;
++ for (i = 0; i < pool->stream_enc_count; i++) {
++ if (pool->stream_enc[i]->id == inst) {
++ tg_inst = pool->stream_enc[i]->funcs->dig_source_otg(
++ pool->stream_enc[i]);
++ break;
++ }
++ }
+
+- tg_inst = pool->stream_enc[inst]->funcs->dig_source_otg(pool->stream_enc[inst]);
++ // tg_inst not found
++ if (i == pool->stream_enc_count)
++ return false;
+
+ if (tg_inst >= pool->timing_generator_count)
+ return false;
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
+index b83c022e2c6f..e0a6e30ac3e1 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
+@@ -588,7 +588,7 @@ static void hubbub2_program_watermarks(
+ DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
+ REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 180);
+
+- hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
++ hubbub->funcs->allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
+ }
+
+ static const struct hubbub_funcs hubbub2_funcs = {
+@@ -600,7 +600,8 @@ static const struct hubbub_funcs hubbub2_funcs = {
+ .get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,
+ .wm_read_state = hubbub2_wm_read_state,
+ .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
+- .program_watermarks = hubbub2_program_watermarks
++ .program_watermarks = hubbub2_program_watermarks,
++ .allow_self_refresh_control = hubbub1_allow_self_refresh_control
+ };
+
+ void hubbub2_construct(struct dcn20_hubbub *hubbub,
+--
+2.17.1
+