From 694eca3bb6f6e24fd64db71bb06d95d545e1d009 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 5 Aug 2012 00:01:43 -0500 Subject: [PATCH] radeon_hd: Add DP link_train_ce * First attempts at DisplayPort link training clock equalization. * Add DP define to detect equalization state * Working towards resolving #8626 --- headers/private/graphics/common/dp_raw.h | 6 ++ .../accelerants/radeon_hd/displayport.cpp | 75 ++++++++++++++++++- .../accelerants/radeon_hd/displayport.h | 1 + 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/headers/private/graphics/common/dp_raw.h b/headers/private/graphics/common/dp_raw.h index 556c1b163b..6673ef5899 100644 --- a/headers/private/graphics/common/dp_raw.h +++ b/headers/private/graphics/common/dp_raw.h @@ -168,6 +168,12 @@ #define DP_LANE_STATUS_CR_DONE_B (1 << 4) // Bool #define DP_LANE_STATUS_CHEQ_DONE_B (1 << 5) // Bool #define DP_LANE_STATUS_SYMB_LOCK_B (1 << 6) // Bool +#define DP_LANE_STATUS_EQUALIZED_A DP_LANE_STATUS_CR_DONE_A \ + || DP_LANE_STATUS_CHEQ_DONE_A \ + || DP_LANE_STATUS_SYMB_LOCK_A +#define DP_LANE_STATUS_EQUALIZED_B DP_LANE_STATUS_CR_DONE_B \ + || DP_LANE_STATUS_CHEQ_DONE_B \ + || DP_LANE_STATUS_SYMB_LOCK_B // DP Lane Align Status (0x0204) #define DP_LANE_ALIGN 0x0204 // Reg #define DP_LANE_ALIGN_DONE (1 << 0) // Bool diff --git a/src/add-ons/accelerants/radeon_hd/displayport.cpp b/src/add-ons/accelerants/radeon_hd/displayport.cpp index ec3bb93f7c..0efa52578e 100644 --- a/src/add-ons/accelerants/radeon_hd/displayport.cpp +++ b/src/add-ons/accelerants/radeon_hd/displayport.cpp @@ -410,6 +410,27 @@ dp_clock_recovery_ok(dp_info* dp) } +static bool +dp_clock_equalization_ok(dp_info* dp) +{ + uint8 laneAlignment + = dp->linkStatus[DP_LANE_ALIGN - DP_LANE_STATUS_0_1]; + + if ((laneAlignment & DP_LANE_ALIGN_DONE) == 0) + return false; + + int lane; + for (lane = 0; lane < dp->laneCount; lane++) { + uint8 laneStatus = dp_get_lane_status(dp, lane); + if ((laneStatus & DP_LANE_STATUS_EQUALIZED_A) + != DP_LANE_STATUS_EQUALIZED_A) { + return false; + } + } + return true; +} + + static void dp_update_vs_emph(uint32 connectorIndex) { @@ -612,6 +633,58 @@ dp_link_train_cr(uint32 connectorIndex) } +status_t +dp_link_train_ce(uint32 connectorIndex) +{ + TRACE("%s\n", __func__); + + dp_info* dp = &gConnector[connectorIndex]->dpInfo; + + // TODO: DisplayPort: Supports TP3? + dp_set_tp(connectorIndex, DP_TRAIN_PATTERN_2); + + dp->trainingAttempts = 0; + bool channelEqual = false; + + while (1) { + if (dp->trainingReadInterval == 0) + snooze(100); + else + snooze(1000 * 4 * dp->trainingReadInterval); + + if (!dp_get_link_status(dp)) + break; + + if (dp_clock_equalization_ok(dp)) { + channelEqual = true; + break; + } + + if (dp->trainingAttempts > 5) { + ERROR("%s: ERROR: failed > 5 times!\n", __func__); + break; + } + + dp_get_adjust_train(dp); + + dp_update_vs_emph(connectorIndex); + dp->trainingAttempts++; + } + + if (!channelEqual) { + ERROR("%s: ERROR: failed\n", __func__); + return B_ERROR; + } + + TRACE("%s: channels equalized at voltage %d pre-emphasis %d\n", + __func__, dp->trainingSet[0] & DP_ADJ_VCC_SWING_LANEA_MASK, + (dp->trainingSet[0] & DP_TRAIN_PRE_EMPHASIS_MASK) + >> DP_TRAIN_PRE_EMPHASIS_SHIFT); + + return B_OK; +} + + status_t dp_link_train(uint8 crtcID, display_mode* mode) { @@ -702,7 +775,7 @@ dp_link_train(uint8 crtcID, display_mode* mode) dpcd_reg_write(hwPin, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED); dp_link_train_cr(connectorIndex); - // TODO: dp_link_train_ce + dp_link_train_ce(connectorIndex); // *** DisplayPort link training finish diff --git a/src/add-ons/accelerants/radeon_hd/displayport.h b/src/add-ons/accelerants/radeon_hd/displayport.h index ebf06fbb22..570934a431 100644 --- a/src/add-ons/accelerants/radeon_hd/displayport.h +++ b/src/add-ons/accelerants/radeon_hd/displayport.h @@ -37,6 +37,7 @@ void dp_setup_connectors(); status_t dp_link_train(uint8 crtcID, display_mode* mode); status_t dp_link_train_cr(uint32 connectorIndex); +status_t dp_link_train_ce(uint32 connectorIndex); #endif /* RADEON_HD_DISPLAYPORT_H */