From: Weiguang Li <[email protected]>

[HOW]
Add Replay recovery flow so that when HPD occurs and ESD is detected,
Replay can restore the system back to normal.

Reviewed-by: Wenjing Liu <[email protected]>
Reviewed-by: Robin Chen <[email protected]>
Reviewed-by: Aric Cyr <[email protected]>
Signed-off-by: Weiguang Li <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
---
 .../dc/link/protocols/link_dp_irq_handler.c   | 36 +++++++++++++------
 .../gpu/drm/amd/display/include/dpcd_defs.h   |  3 ++
 2 files changed, 28 insertions(+), 11 deletions(-)

diff --git 
a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c 
b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
index cc18a3bebef2..1860d44f63c1 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
@@ -223,9 +223,10 @@ static void handle_hpd_irq_vesa_replay_sink(struct dc_link 
*link)
        }
 }
 
-static void handle_hpd_irq_replay_sink(struct dc_link *link)
+static void handle_hpd_irq_replay_sink(struct dc_link *link, bool 
*need_re_enable)
 {
        union dpcd_replay_configuration replay_configuration = {0};
+       union dpcd_replay_configuration replay_sink_status = {0};
        /*AMD Replay version reuse DP_PSR_ERROR_STATUS for REPLAY_ERROR 
status.*/
        union psr_error_status replay_error_status = {0};
        bool ret = false;
@@ -265,9 +266,17 @@ static void handle_hpd_irq_replay_sink(struct dc_link 
*link)
                &replay_error_status.raw,
                sizeof(replay_error_status.raw));
 
+       dm_helpers_dp_read_dpcd(
+               link->ctx,
+               link,
+               DP_PR_REPLAY_SINK_STATUS,
+               &replay_sink_status.raw,
+               1);
+
        if (replay_error_status.bits.LINK_CRC_ERROR ||
                replay_configuration.bits.DESYNC_ERROR_STATUS ||
-               replay_configuration.bits.STATE_TRANSITION_ERROR_STATUS) {
+               replay_configuration.bits.STATE_TRANSITION_ERROR_STATUS ||
+               replay_sink_status.bits.SINK_DEVICE_REPLAY_STATUS == 0x7) {
                bool allow_active;
 
                link->replay_settings.config.replay_error_status.raw |= 
replay_error_status.raw;
@@ -299,8 +308,7 @@ static void handle_hpd_irq_replay_sink(struct dc_link *link)
                if (link->replay_settings.replay_allow_active) {
                        allow_active = false;
                        edp_set_replay_allow_active(link, &allow_active, true, 
false, NULL);
-                       allow_active = true;
-                       edp_set_replay_allow_active(link, &allow_active, true, 
false, NULL);
+                       *need_re_enable = true;
                }
        }
 }
@@ -460,6 +468,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
        union device_service_irq device_service_clear = {0};
        enum dc_status result;
        bool status = false;
+       bool replay_re_enable_needed = false;
 
        if (out_link_loss)
                *out_link_loss = false;
@@ -519,7 +528,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
                /* PSR-related error was detected and handled */
                return true;
 
-       handle_hpd_irq_replay_sink(link);
+       handle_hpd_irq_replay_sink(link, &replay_re_enable_needed);
 
        /* If PSR-related error handled, Main link may be off,
         * so do not handle as a normal sink status change interrupt.
@@ -538,16 +547,16 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
                return false;
        }
 
-       /* For now we only handle 'Downstream port status' case.
+       /* Handle 'Downstream port status' case for all DP link types.
         * If we got sink count changed it means
         * Downstream port status changed,
         * then DM should call DC to do the detection.
-        * NOTE: Do not handle link loss on eDP since it is internal link
+        * NOTE: Now includes eDP link loss detection and retraining
         */
-       if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
-                       dp_parse_link_loss_status(
-                                       link,
-                                       &hpd_irq_dpcd_data)) {
+
+       if (dp_parse_link_loss_status(
+                       link,
+                       &hpd_irq_dpcd_data)) {
                /* Connectivity log: link loss */
                CONN_DATA_LINK_LOSS(link,
                                        hpd_irq_dpcd_data.raw,
@@ -576,6 +585,11 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
                        != link->dpcd_sink_count)
                status = true;
 
+       if (replay_re_enable_needed) {
+               bool allow_active = true;
+
+               edp_set_replay_allow_active(link, &allow_active, true, false, 
NULL);
+       }
        /* reasons for HPD RX:
         * 1. Link Loss - ie Re-train the Link
         * 2. MST sideband message
diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h 
b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
index 1afa10e85eb5..4a8ca0ac1266 100644
--- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h
+++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
@@ -64,6 +64,9 @@
 #ifndef DP_PR_ERROR_STATUS                  // can remove this once the define 
gets into linux drm_dp_helper.h
 #define DP_PR_ERROR_STATUS                  0x2020  /* DP 2.0 */
 #endif /* DP_PR_ERROR_STATUS */
+#ifndef DP_PR_REPLAY_SINK_STATUS            // can remove this once the define 
gets into linux drm_dp_helper.h
+#define DP_PR_REPLAY_SINK_STATUS            0x2022
+#endif /* DP_PR_REPLAY_SINK_STATUS */
 #ifndef DP_PR_LINK_CRC_ERROR               // can remove this once the define 
gets into linux drm_dp_helper.h
 #define DP_PR_LINK_CRC_ERROR               (1 << 0)
 #endif /* DP_PR_LINK_CRC_ERROR */
-- 
2.43.0

Reply via email to