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,
                                &lt_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

Reply via email to