[PATCH 18/20] drm/amd/display: Use DAC load detection on analog connectors

Timur Kristóf timur.kristof at gmail.com
Wed Jul 23 15:58:11 UTC 2025


This feature is useful for analog connections without EDID:
- Really old monitors with a VGA connector
- Cheap DVI/VGA adapters that don't connect DDC pins

When a connection is established through DAC load detection,
the driver is supposed to fill in the supported modes for the
display, which we already do in amdgpu_dm_connector_get_modes.

Signed-off-by: Timur Kristóf <timur.kristof at gmail.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 ++++++
 .../drm/amd/display/dc/link/link_detection.c  | 43 +++++++++++++++++++
 2 files changed, 55 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 13823469fa7c..49ee516dc83d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7077,6 +7077,18 @@ amdgpu_dm_connector_poll(struct amdgpu_dm_connector *aconnector, bool force)
 	enum dc_connection_type conn_type = dc_connection_none;
 	enum drm_connector_status status = connector_status_disconnected;
 
+	/* When the EDID is missing on an analog connector, that means
+	 * we determined the connection using DAC load detection.
+	 * In this case do NOT poll the connector do detect disconnect
+	 * because that would run DAC load detection again which can cause
+	 * visible visual glitches.
+	 *
+	 * Only allow to poll such a connector again when forcing.
+	 */
+	if (!force && link->local_sink && link->local_sink->edid_caps.analog &&
+		!aconnector->drm_edid)
+		return connector->status;
+
 	mutex_lock(&aconnector->hpd_lock);
 
 	if (dc_link_detect_connection_type(aconnector->dc_link, &conn_type) &&
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
index fcabc83464af..6dd96e2797f4 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -1073,6 +1073,20 @@ static bool detect_link_and_local_sink(struct dc_link *link,
 			break;
 		case EDID_NO_RESPONSE:
 			DC_LOG_ERROR("No EDID read.\n");
+
+			/* Analog connectors without EDID.
+			 * This can be an old monitor that actually doesn't have EDID,
+			 * or could be a cheap DVI/VGA adapter that doesn't connect DDC,
+			 * and therefore we can't read the EDID.
+			 */
+			if (link->link_enc->connector.id == CONNECTOR_ID_VGA ||
+				link->link_enc->connector.id == CONNECTOR_ID_DUAL_LINK_DVII ||
+				link->link_enc->connector.id == CONNECTOR_ID_SINGLE_LINK_DVII) {
+				DC_LOG_INFO("%s detected analog display without EDID\n", __func__);
+				sink->edid_caps.analog = true;
+				break;
+			}
+
 			/*
 			 * Abort detection for non-DP connectors if we have
 			 * no EDID
@@ -1280,6 +1294,30 @@ static bool link_detect_ddc_probe(struct dc_link *link)
 	return true;
 }
 
+static bool link_detect_dac_load_detect(struct dc_link *link)
+{
+	struct dc_bios *bios = link->ctx->dc_bios;
+	struct link_encoder *link_enc = link->link_enc;
+	enum engine_id engine_id = link_enc->preferred_engine;
+	enum dal_device_type device_type = DEVICE_TYPE_CRT;
+	enum bp_result bp_result;
+	uint32_t enum_id;
+
+	switch (engine_id) {
+	case ENGINE_ID_DACB:
+		enum_id = 2;
+		break;
+	case ENGINE_ID_DACA:
+	default:
+		engine_id = ENGINE_ID_DACA;
+		enum_id = 1;
+		break;
+	}
+
+	bp_result = bios->funcs->dac_load_detection(bios, engine_id, device_type, enum_id);
+	return bp_result == BP_RESULT_OK;
+}
+
 /**
  * Determines if there is an analog sink connected.
  */
@@ -1296,6 +1334,11 @@ static bool link_detect_analog(struct dc_link *link, enum dc_connection_type *ty
 		return true;
 	}
 
+	if (link_detect_dac_load_detect(link)) {
+		*type = dc_connection_single;
+		return true;
+	}
+
 	*type = dc_connection_none;
 	return true;
 }
-- 
2.50.1



More information about the amd-gfx mailing list