From: Fangzhi Zuo <[email protected]>

[Why & How]
On resume, dm_resume() walks the connector list and, for each connector,
calls dc_link_detect_connection_type() at the top of the loop iteration
before the per-connector dc_exit_ips_for_hw_access() that sits in the
detection branch. There is no dc_exit_ips_for_hw_access() before the loop,
so the very first HW access relies on an earlier connector having already
taken the display out of IPS.

Commit d1d51519bc3b ("drm/amd/display: Skip eDP detection when no sink")
skips the eDP connector when no panel is present. On a DCN3.5 APU whose
eDP link has no sink, the eDP iteration - which used to bring the HW out
of IPS first - is now skipped, so a downstream DP connector becomes the
first one processed. Its initial DDC/AUX access then runs while the HW is
still idle, the AUX transfers time out (-ETIMEDOUT), and the EDID read
fails:

  [drm:dm_helpers_read_local_edid [amdgpu]] *ERROR* EDID err: 2, on connector: 
DP-1
  amdgpu: [drm] *ERROR* No EDID read.

Take the display out of IPS once before the detection loop so the first
connector processed no longer touches the AUX/DDC engine while the HW is
still in idle power state. This keeps the eDP-skip boot/resume
optimization while fixing the DP EDID read failure.

Fixes: d1d51519bc3b ("drm/amd/display: Skip eDP detection when no sink")
Reviewed-by: Roman Li <[email protected]>
Signed-off-by: Fangzhi Zuo <[email protected]>
Signed-off-by: Ray Wu <[email protected]>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 8879196b2675..da379c48a5aa 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2023,6 +2023,10 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
        /* On resume we need to rewrite the MSTM control bits to enable MST*/
        s3_handle_mst(ddev, false);
 
+       /* Exit IPS before the detection loop's first AUX/DDC access. */
+       scoped_guard(mutex, &dm->dc_lock)
+               dc_exit_ips_for_hw_access(dm->dc);
+
        /* Do detection*/
        drm_connector_list_iter_begin(ddev, &iter);
        drm_for_each_connector_iter(connector, &iter) {
-- 
2.43.0

Reply via email to