AMD-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "Timur Kristóf" <timur.kristof@gmail.com>
To: amd-gfx@lists.freedesktop.org
Cc: alexander.deucher@amd.com, alex.hung@amd.com,
	harry.wentland@amd.com, siqueira@igalia.com,
	christian.koenig@amd.com,
	"Timur Kristóf" <timur.kristof@gmail.com>
Subject: [PATCH 14/23] drm/amd/display: Add analog link detection (v2)
Date: Fri, 26 Sep 2025 20:01:54 +0200	[thread overview]
Message-ID: <20250926180203.16690-15-timur.kristof@gmail.com> (raw)
In-Reply-To: <20250926180203.16690-1-timur.kristof@gmail.com>

Analog displays typically have a DDC connection which can be
used by the GPU to read EDID. This commit adds the capability
to probe analog displays using DDC, reading the EDID header and
deciding whether the analog link is connected based on the data
that was read.

Note that VGA has no HPD (hotplug detection), so we need to
to do analog link detection for VGA before checking HPD.

In case of DVI-I, while the connector supports HPD, not all
analog cables connect the HPD pins, so we can't rely on HPD
either.

For reference, see the legacy display code:
amdgpu_connector_vga_detect
amdgpu_display_ddc_probe

DAC load detection will be implemented in a separate commit.

v2:
Fix crash / black screen on newer GPUs during link detection.
Ignore HPD pin for analog connectors.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
 .../amd/display/dc/link/hwss/link_hwss_dio.c  | 16 ++--
 .../drm/amd/display/dc/link/link_detection.c  | 86 ++++++++++++++++++-
 .../gpu/drm/amd/display/dc/link/link_dpms.c   |  3 +
 .../drm/amd/display/dc/link/link_factory.c    |  3 +
 4 files changed, 101 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
index 80344cbd1f99..befa67b2b2ae 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
@@ -58,8 +58,9 @@ void setup_dio_stream_encoder(struct pipe_ctx *pipe_ctx)
 		return;
 	}
 
-	link_enc->funcs->connect_dig_be_to_fe(link_enc,
-			pipe_ctx->stream_res.stream_enc->id, true);
+	if (!dc_is_rgb_signal(pipe_ctx->stream->signal))
+		link_enc->funcs->connect_dig_be_to_fe(link_enc,
+				pipe_ctx->stream_res.stream_enc->id, true);
 	if (dc_is_dp_signal(pipe_ctx->stream->signal))
 		pipe_ctx->stream->ctx->dc->link_srv->dp_trace_source_sequence(pipe_ctx->stream->link,
 				DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE);
@@ -98,10 +99,13 @@ void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx)
 	if (stream_enc->funcs->enable_stream)
 		stream_enc->funcs->enable_stream(stream_enc,
 				pipe_ctx->stream->signal, false);
-	link_enc->funcs->connect_dig_be_to_fe(
-			link_enc,
-			pipe_ctx->stream_res.stream_enc->id,
-			false);
+
+	if (!dc_is_rgb_signal(pipe_ctx->stream->signal))
+		link_enc->funcs->connect_dig_be_to_fe(
+				link_enc,
+				pipe_ctx->stream_res.stream_enc->id,
+				false);
+
 	if (dc_is_dp_signal(pipe_ctx->stream->signal))
 		pipe_ctx->stream->ctx->dc->link_srv->dp_trace_source_sequence(
 				pipe_ctx->stream->link,
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 2ab8ee7f42c1..2ad4862ad659 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -858,6 +858,48 @@ static void verify_link_capability(struct dc_link *link, struct dc_sink *sink,
 		verify_link_capability_non_destructive(link);
 }
 
+/**
+ * link_detect_evaluate_edid_header() - Evaluate if an EDID header is acceptable.
+ *
+ * Evaluates an 8-byte EDID header to check if it's good enough
+ * for the purpose of determining whether a display is connected
+ * without reading the full EDID.
+ */
+static bool link_detect_evaluate_edid_header(uint8_t edid_header[8])
+{
+	int edid_header_score = 0;
+	int i;
+
+	for (i = 0; i < 8; ++i)
+		edid_header_score += edid_header[i] == ((i == 0 || i == 7) ? 0x00 : 0xff);
+
+	return edid_header_score >= 6;
+}
+
+/**
+ * link_detect_ddc_probe() - Probe the DDC to see if a display is connected.
+ *
+ * Detect whether a display is connected to DDC without reading full EDID.
+ * Reads only the EDID header (the first 8 bytes of EDID) from DDC and
+ * evaluates whether that matches.
+ */
+static bool link_detect_ddc_probe(struct dc_link *link)
+{
+	if (!link->ddc)
+		return false;
+
+	uint8_t edid_header[8] = {0};
+	bool ddc_probed = i2c_read(link->ddc, 0x50, edid_header, sizeof(edid_header));
+
+	if (!ddc_probed)
+		return false;
+
+	if (!link_detect_evaluate_edid_header(edid_header))
+		return false;
+
+	return true;
+}
+
 /*
  * detect_link_and_local_sink() - Detect if a sink is attached to a given link
  *
@@ -942,6 +984,12 @@ static bool detect_link_and_local_sink(struct dc_link *link,
 			break;
 		}
 
+		case SIGNAL_TYPE_RGB: {
+			sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+			sink_caps.signal = SIGNAL_TYPE_RGB;
+			break;
+		}
+
 		case SIGNAL_TYPE_LVDS: {
 			sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
 			sink_caps.signal = SIGNAL_TYPE_LVDS;
@@ -1135,9 +1183,17 @@ static bool detect_link_and_local_sink(struct dc_link *link,
 				sink = prev_sink;
 				prev_sink = NULL;
 			}
-			query_hdcp_capability(sink->sink_signal, link);
+
+			if (!sink->edid_caps.analog)
+				query_hdcp_capability(sink->sink_signal, link);
 		}
 
+		/* DVI-I connector connected to analog display. */
+		if ((link->link_id.id == CONNECTOR_ID_DUAL_LINK_DVII ||
+		     link->link_id.id == CONNECTOR_ID_SINGLE_LINK_DVII) &&
+			sink->edid_caps.analog)
+			sink->sink_signal = SIGNAL_TYPE_RGB;
+
 		/* HDMI-DVI Dongle */
 		if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A &&
 		    !sink->edid_caps.edid_hdmi)
@@ -1234,6 +1290,23 @@ static bool detect_link_and_local_sink(struct dc_link *link,
 	return true;
 }
 
+/**
+ * link_detect_analog() - Determines if an analog sink is connected.
+ */
+static bool link_detect_analog(struct dc_link *link, enum dc_connection_type *type)
+{
+	/* Don't care about connectors that don't support an analog signal. */
+	ASSERT(dc_connector_supports_analog(link->link_id.id));
+
+	if (link_detect_ddc_probe(link)) {
+		*type = dc_connection_single;
+		return true;
+	}
+
+	*type = dc_connection_none;
+	return true;
+}
+
 /*
  * link_detect_connection_type() - Determine if there is a sink connected
  *
@@ -1250,6 +1323,17 @@ bool link_detect_connection_type(struct dc_link *link, enum dc_connection_type *
 		return true;
 	}
 
+	/* Ignore the HPD pin (if any) for analog connectors.
+	 * Instead rely on DDC.
+	 *
+	 * - VGA connectors don't have any HPD at all.
+	 * - Some DVI-A cables don't connect the HPD pin.
+	 * - Some DVI-A cables pull up the HPD pin.
+	 *   (So it's high even when no display is connected.)
+	 */
+	if (dc_connector_supports_analog(link->link_id.id))
+		return link_detect_analog(link, type);
+
 	if (link->connector_signal == SIGNAL_TYPE_EDP) {
 		/*in case it is not on*/
 		if (!link->dc->config.edp_no_power_sequencing)
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index c92d46c25f8c..6e16d8419fd9 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -2256,6 +2256,9 @@ static enum dc_status enable_link(
 		enable_link_lvds(pipe_ctx);
 		status = DC_OK;
 		break;
+	case SIGNAL_TYPE_RGB:
+		status = DC_OK;
+		break;
 	case SIGNAL_TYPE_VIRTUAL:
 		status = enable_link_virtual(pipe_ctx);
 		break;
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
index 4dbe88d17a11..b6990088b8b7 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
@@ -583,6 +583,9 @@ static bool construct_phy(struct dc_link *link,
 	case CONNECTOR_ID_DUAL_LINK_DVII:
 		link->connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
 		break;
+	case CONNECTOR_ID_VGA:
+		link->connector_signal = SIGNAL_TYPE_RGB;
+		break;
 	case CONNECTOR_ID_DISPLAY_PORT:
 	case CONNECTOR_ID_MXM:
 	case CONNECTOR_ID_USBC:
-- 
2.51.0


  parent reply	other threads:[~2025-09-26 18:03 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-26 18:01 [PATCH 00/23] Analog connector support in DC (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 01/23] drm/amd/display: Determine DVI-I connector type (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 02/23] drm/amd/display: Add analog bit to edid_caps (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 03/23] drm/amd/display: Introduce MAX_LINK_ENCODERS (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 04/23] drm/amd/display: Hook up DAC to bios_parser_encoder_control Timur Kristóf
2025-09-26 18:01 ` [PATCH 05/23] drm/amd/display: Add SelectCRTC_Source to BIOS parser Timur Kristóf
2025-09-26 18:01 ` [PATCH 06/23] drm/amd/display: Get maximum pixel clock from VBIOS Timur Kristóf
2025-09-26 18:01 ` [PATCH 07/23] drm/amd/display: Don't use stereo sync and audio on RGB signals (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 08/23] drm/amd/display: Don't try to enable/disable HPD when unavailable Timur Kristóf
2025-09-26 18:01 ` [PATCH 09/23] drm/amd/display: Determine early if a link has supported encoders (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 10/23] drm/amd/display: Add concept of analog " Timur Kristóf
2025-09-26 18:01 ` [PATCH 11/23] drm/amd/display: Implement DCE analog stream encoders Timur Kristóf
2025-09-26 18:01 ` [PATCH 12/23] drm/amd/display: Implement DCE analog link encoders (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 13/23] drm/amd/display: Support DAC in dce110_hwseq Timur Kristóf
2025-10-08 21:01   ` Harry Wentland
2025-09-26 18:01 ` Timur Kristóf [this message]
2025-09-26 18:01 ` [PATCH 15/23] drm/amd/display: Refactor amdgpu_dm_connector_detect (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 16/23] drm/amd/display: Poll analog connectors (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 17/23] drm/amd/display: Add DCE BIOS_SCRATCH_0 register Timur Kristóf
2025-09-26 18:01 ` [PATCH 18/23] drm/amd/display: Make get_support_mask_for_device_id reusable Timur Kristóf
2025-09-26 18:01 ` [PATCH 19/23] drm/amd/display: Add DAC_LoadDetection to BIOS parser (v2) Timur Kristóf
2025-09-26 18:02 ` [PATCH 20/23] drm/amd/display: Use DAC load detection on analog connectors (v2) Timur Kristóf
2025-09-26 18:02 ` [PATCH 21/23] drm/amd/display: Add common modes to analog displays without EDID Timur Kristóf
2025-09-26 18:02 ` [PATCH 22/23] drm/amd/display: Don't add freesync modes to analog displays (v2) Timur Kristóf
2025-09-26 18:02 ` [PATCH 23/23] drm/amdgpu: Use DC by default for Bonaire Timur Kristóf
2025-10-08 21:11 ` [PATCH 00/23] Analog connector support in DC (v2) Harry Wentland
2025-10-09 17:26   ` Harry Wentland
2025-10-09 17:49     ` Wheeler, Daniel
2025-10-09 18:27       ` Harry Wentland
2025-10-21 16:15         ` Timur Kristóf
2025-10-21 16:44           ` Alex Deucher
2025-10-21 17:32           ` Wheeler, Daniel
2025-10-24 19:07             ` timur.kristof
2025-10-24 21:28               ` Wheeler, Daniel
2025-10-31  8:19                 ` Timur Kristóf
2025-10-31 13:07                   ` Wheeler, Daniel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250926180203.16690-15-timur.kristof@gmail.com \
    --to=timur.kristof@gmail.com \
    --cc=alex.hung@amd.com \
    --cc=alexander.deucher@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=christian.koenig@amd.com \
    --cc=harry.wentland@amd.com \
    --cc=siqueira@igalia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox