From: Martin Tsai <[email protected]> [why] To set link bandwidth with zero could hit error protection from Sink panel to fail link training and cause screen corruption.
[how] To skip link bw cleaning in two conditions: 1. eDP v1.5 or latter, because the last write will take effect. 2. Sink requires not to clear it. Reviewed-by: Anthony Koo <[email protected]> Signed-off-by: Martin Tsai <[email protected]> Signed-off-by: Roman Li <[email protected]> --- .../drm/amd/display/dc/core/dc_link_exports.c | 5 +++++ drivers/gpu/drm/amd/display/dc/dc.h | 3 +++ drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 1 + .../dc/link/protocols/link_dp_training.c | 20 ++++++++++++++----- .../amd/display/include/link_service_types.h | 1 + 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c index fef857c7336b..5926e8a4f95a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c @@ -263,6 +263,11 @@ void dc_link_set_preferred_training_settings(struct dc *dc, lt_overrides, link, skip_immediate_retrain); } +void dc_link_set_skip_link_bw_clear(struct dc_link *link, bool skip) +{ + link->preferred_training_settings.skip_link_bw_clear = skip; +} + bool dc_dp_trace_is_initialized(struct dc_link *link) { return link->dc->link_srv->dp_trace_is_initialized(link); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d2256c454424..957e15e4a84c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -2869,6 +2869,9 @@ void dc_link_set_preferred_training_settings(struct dc *dc, struct dc_link *link, bool skip_immediate_retrain); +/* Configure the sink-specific policy for future DP link training. */ +void dc_link_set_skip_link_bw_clear(struct dc_link *link, bool skip); + /* return - true if FEC is supported with connected DP RX, false otherwise */ bool dc_link_is_fec_supported(const struct dc_link *link); diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index d0ba9ad67a3e..b0e91b321f43 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -203,6 +203,7 @@ struct dc_link_training_overrides { bool *enhanced_framing; bool *mst_enable; bool *fec_enable; + bool skip_link_bw_clear; }; union payload_table_update_status { diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c index 04eedec8a230..3be36d1063de 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c @@ -724,6 +724,8 @@ void override_training_settings( { uint32_t lane; + lt_settings->skip_link_bw_clear = overrides->skip_link_bw_clear; + /* Override link spread */ if (!link->dp_ss_off && overrides->downspread != NULL) lt_settings->link_settings.link_spread = *overrides->downspread ? @@ -1095,7 +1097,7 @@ enum dc_status dpcd_set_link_settings( struct dc_link *link, const struct link_training_settings *lt_settings) { - uint8_t rate; + uint8_t rate = 0; enum dc_status status; union down_spread_ctrl downspread = {0}; @@ -1129,7 +1131,7 @@ enum dc_status dpcd_set_link_settings( if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 && lt_settings->link_settings.use_link_rate_set == true) { - rate = 0; + /* WA for some MUX chips that will power down with eDP and lose supported * link rate set for eDP 1.4. Source reads DPCD 0x010 again to ensure * MUX chip gets link rate set back before link training. @@ -1140,9 +1142,17 @@ enum dc_status dpcd_set_link_settings( core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES, supported_link_rates, sizeof(supported_link_rates)); } - status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1); - if (status != DC_OK) - DC_LOG_ERROR("%s:%d: core_link_write_dpcd (DP_LINK_BW_SET) failed\n", __func__, __LINE__); + + /* + * It doesn't need to clear 0x100 in below two conditions: + * 1. eDP v1.5 or later, because the last write will take effect in Sink. + * 2. Sink requires not to clear 0x100. + */ + if (!lt_settings->skip_link_bw_clear && link->dpcd_caps.edp_rev <= DP_EDP_14b) { + status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1); + if (status != DC_OK) + DC_LOG_ERROR("%s:%d: core_link_write_dpcd (DP_LINK_BW_SET) failed\n", __func__, __LINE__); + } status = core_link_write_dpcd(link, DP_LINK_RATE_SET, <_settings->link_settings.link_rate_set, 1); diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index da74ed66c8f9..798d83238828 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -73,6 +73,7 @@ struct link_training_settings { enum dc_pre_emphasis *pre_emphasis; enum dc_post_cursor2 *post_cursor2; bool should_set_fec_ready; + bool skip_link_bw_clear; union dc_dp_ffe_preset *ffe_preset; uint16_t cr_pattern_time; -- 2.34.1
