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 16/23] drm/amd/display: Poll analog connectors (v2)
Date: Fri, 26 Sep 2025 20:01:56 +0200 [thread overview]
Message-ID: <20250926180203.16690-17-timur.kristof@gmail.com> (raw)
In-Reply-To: <20250926180203.16690-1-timur.kristof@gmail.com>
VGA connectors don't support any hotplug detection, so the kernel
needs to periodically poll them to see if a display is connected.
DVI-I connectors have hotplug detection for digital signals, and
some analog DVI cables pull up that pin to work with that.
However, in general not all DVI cables do this so we can't rely on
this feature, therefore we need to poll DVI-I connectors as well.
v2:
Call drm_kms_helper_poll_fini in amdgpu_dm_hpd_fini.
Disable/enable polling on suspend/resume.
Don't call full link detection when already connected.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 73 ++++++++++++++++++-
.../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 20 +++++
2 files changed, 91 insertions(+), 2 deletions(-)
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 cdc6112e5875..07cfd9cae0df 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3768,7 +3768,9 @@ void amdgpu_dm_update_connector_after_detect(
drm_dbg_kms(dev, "DCHPD: connector_id=%d: Old sink=%p New sink=%p\n",
aconnector->connector_id, aconnector->dc_sink, sink);
- guard(mutex)(&dev->mode_config.mutex);
+ /* When polling, DRM has already locked the mutex for us. */
+ if (!drm_kms_helper_is_poll_worker())
+ mutex_lock(&dev->mode_config.mutex);
/*
* 1. Update status of the drm connector
@@ -3831,6 +3833,10 @@ void amdgpu_dm_update_connector_after_detect(
}
update_subconnector_property(aconnector);
+
+ /* When polling, the mutex will be unlocked for us by DRM. */
+ if (!drm_kms_helper_is_poll_worker())
+ mutex_unlock(&dev->mode_config.mutex);
}
static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
@@ -7123,12 +7129,63 @@ create_stream_for_sink(struct drm_connector *connector,
return stream;
}
+/**
+ * amdgpu_dm_connector_poll() - Poll a connector to see if it's connected to a display
+ *
+ * Used for connectors that don't support HPD (hotplug detection)
+ * to periodically checked whether the connector is connected to a display.
+ */
+static enum drm_connector_status
+amdgpu_dm_connector_poll(struct amdgpu_dm_connector *aconnector, bool force)
+{
+ struct drm_connector *connector = &aconnector->base;
+ struct drm_device *dev = connector->dev;
+ struct amdgpu_device *adev = drm_to_adev(dev);
+ struct dc_link *link = aconnector->dc_link;
+ enum dc_connection_type conn_type = dc_connection_none;
+ enum drm_connector_status status = connector_status_disconnected;
+
+ mutex_lock(&aconnector->hpd_lock);
+
+ if (dc_link_detect_connection_type(aconnector->dc_link, &conn_type) &&
+ conn_type != dc_connection_none) {
+ mutex_lock(&adev->dm.dc_lock);
+
+ /* Only call full link detection when a sink isn't created yet,
+ * ie. just when the display is plugged in, otherwise we risk flickering.
+ */
+ if (link->local_sink ||
+ dc_link_detect(link, DETECT_REASON_HPD))
+ status = connector_status_connected;
+
+ mutex_unlock(&adev->dm.dc_lock);
+ }
+
+ if (connector->status != status) {
+ if (status == connector_status_disconnected) {
+ if (link->local_sink)
+ dc_sink_release(link->local_sink);
+
+ link->local_sink = NULL;
+ link->dpcd_sink_count = 0;
+ link->type = dc_connection_none;
+ }
+
+ amdgpu_dm_update_connector_after_detect(aconnector);
+ }
+
+ mutex_unlock(&aconnector->hpd_lock);
+ return status;
+}
+
/**
* amdgpu_dm_connector_detect() - Detect whether a DRM connector is connected to a display
*
* A connector is considered connected when it has a sink that is not NULL.
* For connectors that support HPD (hotplug detection), the connection is
* handled in the HPD interrupt.
+ * For connectors that may not support HPD, such as analog connectors,
+ * DRM will call this function repeatedly to poll them.
*
* Notes:
* 1. This interface is NOT called in context of HPD irq.
@@ -7148,6 +7205,14 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)
else if (aconnector->base.force == DRM_FORCE_OFF)
return connector_status_disconnected;
+ /* Poll analog connectors and only when either
+ * disconnected or connected to an analog display.
+ */
+ if (drm_kms_helper_is_poll_worker() &&
+ dc_connector_supports_analog(aconnector->dc_link->link_id.id) &&
+ (!aconnector->dc_sink || aconnector->dc_sink->edid_caps.analog))
+ return amdgpu_dm_connector_poll(aconnector, force);
+
return (aconnector->dc_sink ? connector_status_connected :
connector_status_disconnected);
}
@@ -8545,9 +8610,13 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
link->link_enc->features.dp_ycbcr420_supported ? true : false;
break;
case DRM_MODE_CONNECTOR_DVID:
- case DRM_MODE_CONNECTOR_DVII:
aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
break;
+ case DRM_MODE_CONNECTOR_DVII:
+ case DRM_MODE_CONNECTOR_VGA:
+ aconnector->base.polled =
+ DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
+ break;
default:
break;
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
index a1c722112c22..61b0bf7b8269 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
@@ -476,6 +476,7 @@ void amdgpu_dm_irq_fini(struct amdgpu_device *adev)
void amdgpu_dm_irq_suspend(struct amdgpu_device *adev)
{
+ struct drm_device *dev = adev_to_drm(adev);
int src;
struct list_head *hnd_list_h;
struct list_head *hnd_list_l;
@@ -512,6 +513,9 @@ void amdgpu_dm_irq_suspend(struct amdgpu_device *adev)
}
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+ if (dev->mode_config.poll_enabled)
+ drm_kms_helper_poll_disable(dev);
}
void amdgpu_dm_irq_resume_early(struct amdgpu_device *adev)
@@ -537,6 +541,7 @@ void amdgpu_dm_irq_resume_early(struct amdgpu_device *adev)
void amdgpu_dm_irq_resume_late(struct amdgpu_device *adev)
{
+ struct drm_device *dev = adev_to_drm(adev);
int src;
struct list_head *hnd_list_h, *hnd_list_l;
unsigned long irq_table_flags;
@@ -557,6 +562,9 @@ void amdgpu_dm_irq_resume_late(struct amdgpu_device *adev)
}
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+ if (dev->mode_config.poll_enabled)
+ drm_kms_helper_poll_enable(dev);
}
/*
@@ -893,6 +901,7 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
struct drm_connector_list_iter iter;
int irq_type;
int i;
+ bool use_polling = false;
/* First, clear all hpd and hpdrx interrupts */
for (i = DC_IRQ_SOURCE_HPD1; i <= DC_IRQ_SOURCE_HPD6RX; i++) {
@@ -906,6 +915,8 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
struct amdgpu_dm_connector *amdgpu_dm_connector;
const struct dc_link *dc_link;
+ use_polling |= connector->polled != DRM_CONNECTOR_POLL_HPD;
+
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
continue;
@@ -947,6 +958,9 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
}
}
drm_connector_list_iter_end(&iter);
+
+ if (use_polling)
+ drm_kms_helper_poll_init(dev);
}
/**
@@ -963,12 +977,15 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
struct drm_connector *connector;
struct drm_connector_list_iter iter;
int irq_type;
+ bool use_polling = false;
drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter) {
struct amdgpu_dm_connector *amdgpu_dm_connector;
const struct dc_link *dc_link;
+ use_polling |= connector->polled != DRM_CONNECTOR_POLL_HPD;
+
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
continue;
@@ -997,4 +1014,7 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
}
}
drm_connector_list_iter_end(&iter);
+
+ if (dev->mode_config.poll_enabled)
+ drm_kms_helper_poll_fini(dev);
}
--
2.51.0
next prev 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 ` [PATCH 14/23] drm/amd/display: Add analog link detection (v2) Timur Kristóf
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 ` Timur Kristóf [this message]
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-17-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