From: Jack Chang <[email protected]>

[Why & How]
Add error handling for IRQ_HPD in Panel Replay

Reviewed-by: Robin Chen <[email protected]>
Reviewed-by: Wenjing Liu <[email protected]>
Signed-off-by: Jack Chang <[email protected]>
Signed-off-by: Matthew Stewart <[email protected]>
---
 drivers/gpu/drm/amd/display/dc/dc_dp_types.h  | 11 +++++
 .../dc/link/protocols/link_dp_irq_handler.c   | 42 +++++++++++++++++++
 .../gpu/drm/amd/display/include/dpcd_defs.h   | 15 +++++++
 3 files changed, 68 insertions(+)

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 d0d9297ccac0..5e3646b7550c 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
@@ -1423,6 +1423,17 @@ union dpcd_sink_active_vtotal_control_mode {
        unsigned char raw;
 };
 
+union pr_error_status {
+       struct {
+               unsigned char LINK_CRC_ERROR        :1;
+               unsigned char RFB_STORAGE_ERROR     :1;
+               unsigned char VSC_SDP_ERROR         :1;
+               unsigned char ASSDP_MISSING_ERROR   :1;
+               unsigned char RESERVED              :4;
+       } bits;
+       unsigned char raw;
+};
+
 union psr_error_status {
        struct {
                unsigned char LINK_CRC_ERROR        :1;
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 47abd3ec69b3..cc18a3bebef2 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
@@ -34,6 +34,7 @@
 #include "link_dp_training.h"
 #include "link_dp_capability.h"
 #include "link_edp_panel_control.h"
+#include "link_dp_panel_replay.h"
 #include "link/accessories/link_dp_trace.h"
 #include "link/link_dpms.h"
 #include "dm_helpers.h"
@@ -186,6 +187,42 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link)
        return false;
 }
 
+static void handle_hpd_irq_vesa_replay_sink(struct dc_link *link)
+{
+       union pr_error_status pr_error_status = {0};
+
+       if (!link->replay_settings.replay_feature_enabled ||
+                       link->replay_settings.config.replay_version != 
DC_VESA_PANEL_REPLAY)
+               return;
+
+       dm_helpers_dp_read_dpcd(
+               link->ctx,
+               link,
+               DP_PR_ERROR_STATUS,
+               &pr_error_status.raw,
+               sizeof(pr_error_status.raw));
+
+       if (pr_error_status.bits.LINK_CRC_ERROR ||
+                       pr_error_status.bits.RFB_STORAGE_ERROR ||
+                       pr_error_status.bits.VSC_SDP_ERROR ||
+                       pr_error_status.bits.ASSDP_MISSING_ERROR) {
+
+               /* Acknowledge and clear error bits */
+               dm_helpers_dp_write_dpcd(
+                       link->ctx,
+                       link,
+                       DP_PR_ERROR_STATUS, /*DpcdAddress_PR_Error_Status*/
+                       &pr_error_status.raw,
+                       sizeof(pr_error_status.raw));
+
+               /* Replay error, disable and re-enable Replay */
+               if (link->replay_settings.replay_allow_active) {
+                       dp_pr_enable(link, false);
+                       dp_pr_enable(link, true);
+               }
+       }
+}
+
 static void handle_hpd_irq_replay_sink(struct dc_link *link)
 {
        union dpcd_replay_configuration replay_configuration = {0};
@@ -197,6 +234,11 @@ static void handle_hpd_irq_replay_sink(struct dc_link 
*link)
        if (!link->replay_settings.replay_feature_enabled)
                return;
 
+       if (link->replay_settings.config.replay_version != DC_FREESYNC_REPLAY) {
+               handle_hpd_irq_vesa_replay_sink(link);
+               return;
+       }
+
        while (retries < 10) {
                ret = dm_helpers_dp_read_dpcd(
                        link->ctx,
diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h 
b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
index 43d58df67bab..7d8359a7d99d 100644
--- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h
+++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
@@ -61,6 +61,21 @@
 #ifndef DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 // can remove this once the 
define gets into linux drm_dp_helper.h
 #define DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 0x1b1
 #endif /* DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 */
+#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_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 */
+#ifndef DP_PR_RFB_STORAGE_ERROR            // can remove this once the define 
gets into linux drm_dp_helper.h
+#define DP_PR_RFB_STORAGE_ERROR            (1 << 1)
+#endif /* DP_PR_RFB_STORAGE_ERROR */
+#ifndef DP_PR_VSC_SDP_UNCORRECTABLE_ERROR // can remove this once the define 
gets into linux drm_dp_helper.h
+#define DP_PR_VSC_SDP_UNCORRECTABLE_ERROR  (1 << 2) /* eDP 1.4 */
+#endif /* DP_PR_VSC_SDP_UNCORRECTABLE_ERROR */
+#ifndef DP_PR_ASSDP_MISSING_ERROR          // can remove this once the define 
gets into linux drm_dp_helper.h
+#define DP_PR_ASSDP_MISSING_ERROR          (1 << 3) /* eDP 1.5 */
+#endif /* DP_PR_ASSDP_MISSING_ERROR */
 
 enum dpcd_revision {
        DPCD_REV_10 = 0x10,
-- 
2.52.0

Reply via email to