summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Chang <jack.chang@amd.com>2025-11-06 05:58:26 +0300
committerAlex Deucher <alexander.deucher@amd.com>2026-01-10 22:21:53 +0300
commit53edf8604a7c594d1d5091deb7c11d2c3b2e6b79 (patch)
tree6cd51e35000be1eedb1746bfa65ddfb02de348bc
parenta230696d4e009abb22b7a2f9d434f1555bfa08ca (diff)
downloadlinux-53edf8604a7c594d1d5091deb7c11d2c3b2e6b79.tar.xz
drm/amd/display: PR error HPD_IRQ handling
[Why & How] Add error handling for IRQ_HPD in Panel Replay Reviewed-by: Robin Chen <robin.chen@amd.com> Reviewed-by: Wenjing Liu <wenjing.liu@amd.com> Signed-off-by: Jack Chang <jack.chang@amd.com> Signed-off-by: Matthew Stewart <matthew.stewart2@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dp_types.h11
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c42
-rw-r--r--drivers/gpu/drm/amd/display/include/dpcd_defs.h15
3 files changed, 68 insertions, 0 deletions
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,