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
