drm/amd/display: fix issues with bad AUX reply on some displays
authorAnthony Koo <anthony.koo@amd.com>
Wed, 15 May 2019 20:39:23 +0000 (16:39 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 31 May 2019 15:39:32 +0000 (10:39 -0500)
[Why]
Some displays take some time to power up AUX CH once they are
put into D3 state via write to DPCD 600h=2.

Interestingly enough, some display may simply NACK, but some might
also ACK with a bunch of 0s, which can cause issues with receiver
cap retrieval. Note that not all DPCD address return 0s, but in
particular it has been observed on some higher DPCD address such
as DPCD 2200h, etc.

[How]
Based on spec, receiver will monitor differential signal while in D3 and
AUX CH is in low power mode. When detected, it may allow up to
1 ms to power up AUX CH and reply.

If we read Sink power state D3, we should add 1 ms delay to satisfy
this spec requirement.

Signed-off-by: Anthony Koo <anthony.koo@amd.com>
Reviewed-by: Wenjing Liu <Wenjing.Liu@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c

index 1ee544a32ebb3c33875c9d161d08a0f5675279e4..65d6caedbd82c1d122f6d3e77b8b77e317657559 100644 (file)
@@ -2361,6 +2361,7 @@ static bool retrieve_link_cap(struct dc_link *link)
        /*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST.
         */
        uint8_t dpcd_dprx_data = '\0';
+       uint8_t dpcd_power_state = '\0';
 
        struct dp_device_vendor_id sink_id;
        union down_stream_port_count down_strm_port_count;
@@ -2377,6 +2378,17 @@ static bool retrieve_link_cap(struct dc_link *link)
        memset(&edp_config_cap, '\0',
                sizeof(union edp_configuration_cap));
 
+       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);
+
        for (i = 0; i < read_dpcd_retry_cnt; i++) {
                status = core_link_read_dpcd(
                                link,