From: Lewis Huang <lewis.hu...@amd.com>

[Why]
LTTPR caps will read fail if aux channel is not active.

[How]
1.Perform 600 read upto 10 retry with 1ms delay in between.
2.If fail, return false and trigger another retry detection.
3.If pass, read LTTPR caps in retrieve link caps.

Reviewed-by: Jimmy Kizito <jimmy.kiz...@amd.com>
Acked-by: Brian Chang <brian.ch...@amd.com>
Signed-off-by: Lewis Huang <lewis.hu...@amd.com>
---
 .../gpu/drm/amd/display/dc/core/dc_link_dp.c  | 45 ++++++++++++++-----
 1 file changed, 34 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index 2b7bb3a796e8..8617de559174 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -5275,6 +5275,7 @@ static bool retrieve_link_cap(struct dc_link *link)
        union dp_downstream_port_present ds_port = { 0 };
        enum dc_status status = DC_ERROR_UNEXPECTED;
        uint32_t read_dpcd_retry_cnt = 3;
+       uint32_t aux_channel_retry_cnt = 0;
        int i;
        struct dp_sink_hw_fw_revision dp_hw_fw_revision;
        const uint32_t post_oui_delay = 30; // 30ms
@@ -5302,21 +5303,43 @@ static bool retrieve_link_cap(struct dc_link *link)
                status = wa_try_to_wake_dprx(link, timeout_ms);
        }
 
+       while (status != DC_OK && aux_channel_retry_cnt < 10) {
+               status = core_link_read_dpcd(link, DP_SET_POWER,
+                               &dpcd_power_state, sizeof(dpcd_power_state));
+
+               /* Delay 1 ms if AUX CH is in power down state. Based on spec
+                * section 2.3.1.2, if AUX CH may be powered down due to
+                * write to DPCD 600h = 2. Sink AUX CH is monitoring 
differential
+                * signal and may need up to 1 ms before being able to reply.
+                */
+               if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3) {
+                       udelay(1000);
+                       aux_channel_retry_cnt++;
+               }
+       }
+
+       /* If aux channel is not active, return false and trigger another 
detect*/
+       if (status != DC_OK) {
+               dpcd_power_state = DP_SET_POWER_D0;
+               status = core_link_write_dpcd(
+                               link,
+                               DP_SET_POWER,
+                               &dpcd_power_state,
+                               sizeof(dpcd_power_state));
+
+               dpcd_power_state = DP_SET_POWER_D3;
+               status = core_link_write_dpcd(
+                               link,
+                               DP_SET_POWER,
+                               &dpcd_power_state,
+                               sizeof(dpcd_power_state));
+               return false;
+       }
+
        is_lttpr_present = dp_retrieve_lttpr_cap(link);
        /* Read DP tunneling information. */
        status = dpcd_get_tunneling_device_data(link);
 
-       status = core_link_read_dpcd(link, DP_SET_POWER,
-                       &dpcd_power_state, sizeof(dpcd_power_state));
-
-       /* Delay 1 ms if AUX CH is in power down state. Based on spec
-        * section 2.3.1.2, if AUX CH may be powered down due to
-        * write to DPCD 600h = 2. Sink AUX CH is monitoring differential
-        * signal and may need up to 1 ms before being able to reply.
-        */
-       if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3)
-               udelay(1000);
-
        dpcd_set_source_specific_data(link);
        /* Sink may need to configure internals based on vendor, so allow some
         * time before proceeding with possibly vendor specific transactions
-- 
2.25.1

Reply via email to