From: Mike Lothian <mike@fireburn.co.uk>
To: rust-for-linux@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
"Danilo Krummrich" <dakr@kernel.org>,
"Lyude Paul" <lyude@redhat.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
linux-kernel@vger.kernel.org,
"Mike Lothian" <mike@fireburn.co.uk>
Subject: [RFC PATCH v2 17/18] rust: drm: kms: add connector detect() and mode_valid() hooks
Date: Fri, 3 Jul 2026 04:01:04 +0100 [thread overview]
Message-ID: <20260703030123.2814-18-mike@fireburn.co.uk> (raw)
In-Reply-To: <20260703030123.2814-1-mike@fireburn.co.uk>
The safe connector layer only exposed get_modes(), so a driver couldn't
report hotplug state or prune modes it can't drive. Add two optional
DriverConnector hooks, gated the same way as the plane/CRTC optionals
(registered in the vtable only when the driver overrides them):
- detect(&Connector, force) -> Status, wired to
drm_connector_funcs.detect, returning a new Status enum
(Connected/Disconnected/Unknown mapping to enum drm_connector_status).
- mode_valid(&Connector, &DisplayMode) -> ModeStatus, wired to
drm_connector_helper_funcs.mode_valid, returning a new ModeStatus enum
(Ok/Bad/ClockHigh/ClockLow, a common subset of enum drm_mode_status).
Both leave DRM's default behaviour (always connected, all modes valid)
unchanged for connectors that don't implement them.
Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
Assisted-by: Claude:claude-opus-4-8 [Claude-Code]
---
rust/kernel/drm/kms/connector.rs | 98 +++++++++++++++++++++++++++++++-
1 file changed, 95 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/drm/kms/connector.rs b/rust/kernel/drm/kms/connector.rs
index 591153de7ab4..a66243db8868 100644
--- a/rust/kernel/drm/kms/connector.rs
+++ b/rust/kernel/drm/kms/connector.rs
@@ -5,7 +5,8 @@
//! C header: [`include/drm/drm_connector.h`](srctree/include/drm/drm_connector.h)
use super::{
- atomic::*, encoder::*, KmsDriver, ModeConfigGuard, ModeObject, ModeObjectVtable, Sealed
+ atomic::*, encoder::*, modes::DisplayMode, KmsDriver, ModeConfigGuard, ModeObject,
+ ModeObjectVtable, Sealed,
};
use crate::{
alloc::KBox,
@@ -72,6 +73,43 @@ pub enum Type {
USB as Usb
}
+/// The connection status of a [`Connector`], as returned by [`DriverConnector::detect`].
+///
+/// This is identical to [`enum drm_connector_status`].
+///
+/// [`enum drm_connector_status`]: srctree/include/drm/drm_connector.h
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[repr(u32)]
+pub enum Status {
+ /// The connector is connected to a display and a mode list can be retrieved.
+ Connected = bindings::drm_connector_status_connector_status_connected,
+ /// The connector has no display attached.
+ Disconnected = bindings::drm_connector_status_connector_status_disconnected,
+ /// The connection state could not be determined (treated as connected for probing).
+ Unknown = bindings::drm_connector_status_connector_status_unknown,
+}
+
+/// The result of validating a display mode against a [`Connector`], as returned by
+/// [`DriverConnector::mode_valid`].
+///
+/// This mirrors a small, commonly-used subset of [`enum drm_mode_status`]; use [`ModeStatus::Bad`]
+/// for a generic rejection, or the clock-specific variants when a mode is out of the driver's
+/// pixel-clock range.
+///
+/// [`enum drm_mode_status`]: srctree/include/drm/drm_modes.h
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[repr(i32)]
+pub enum ModeStatus {
+ /// The mode is usable.
+ Ok = bindings::drm_mode_status_MODE_OK,
+ /// The mode is rejected for an unspecified reason.
+ Bad = bindings::drm_mode_status_MODE_BAD,
+ /// The mode's pixel clock is above what the driver can drive.
+ ClockHigh = bindings::drm_mode_status_MODE_CLOCK_HIGH,
+ /// The mode's pixel clock is below what the driver can drive.
+ ClockLow = bindings::drm_mode_status_MODE_CLOCK_LOW,
+}
+
/// The main trait for implementing the [`struct drm_connector`] API for [`Connector`].
///
/// Any KMS driver should have at least one implementation of this type, which allows them to create
@@ -105,14 +143,22 @@ pub trait DriverConnector: Send + Sync + Sized {
atomic_destroy_state: Some(atomic_destroy_state_callback::<Self::State>),
destroy: Some(connector_destroy_callback::<Self>),
force: None,
- detect: None,
+ detect: if Self::HAS_DETECT {
+ Some(detect_callback::<Self>)
+ } else {
+ None
+ },
fill_modes: Some(bindings::drm_helper_probe_single_connector_modes),
debugfs_init: None,
oob_hotplug_event: None,
atomic_duplicate_state: Some(atomic_duplicate_state_callback::<Self::State>),
},
helper_funcs: bindings::drm_connector_helper_funcs {
- mode_valid: None,
+ mode_valid: if Self::HAS_MODE_VALID {
+ Some(mode_valid_callback::<Self>)
+ } else {
+ None
+ },
atomic_check: None,
get_modes: Some(get_modes_callback::<Self>),
detect_ctx: None,
@@ -151,6 +197,28 @@ fn get_modes<'a>(
connector: ConnectorGuard<'a, Self>,
guard: &ModeConfigGuard<'a, Self::Driver>,
) -> i32;
+
+ /// The optional [`drm_connector_funcs.detect`] hook for this connector.
+ ///
+ /// Drivers may implement this to report whether a display is currently attached. If not
+ /// implemented, the connector is always considered connected (DRM's default with no `detect`
+ /// hook). `force` is set when userspace explicitly requested a forced probe.
+ ///
+ /// [`drm_connector_funcs.detect`]: srctree/include/drm/drm_connector.h
+ fn detect(_connector: &Connector<Self>, _force: bool) -> Status {
+ build_error::build_error("This should not be reachable")
+ }
+
+ /// The optional [`drm_connector_helper_funcs.mode_valid`] hook for this connector.
+ ///
+ /// Drivers may implement this to reject modes they cannot drive (for example, a mode whose
+ /// pixel clock exceeds the hardware's budget). Returning anything other than [`ModeStatus::Ok`]
+ /// prunes the mode from the probed list. If not implemented, every mode is accepted.
+ ///
+ /// [`drm_connector_helper_funcs.mode_valid`]: srctree/include/drm/drm_modeset_helper_vtables.h
+ fn mode_valid(_connector: &Connector<Self>, _mode: &DisplayMode) -> ModeStatus {
+ build_error::build_error("This should not be reachable")
+ }
}
/// The generated C vtable for a [`DriverConnector`].
@@ -464,6 +532,30 @@ impl<T: AsRawConnector> RawConnector for T {}
T::get_modes(connector.guard(&guard), &guard)
}
+unsafe extern "C" fn detect_callback<T: DriverConnector>(
+ connector: *mut bindings::drm_connector,
+ force: bool,
+) -> bindings::drm_connector_status {
+ // SAFETY: This is safe via `DriverConnector`s type invariants.
+ let connector = unsafe { Connector::<T>::from_raw(connector) };
+
+ T::detect(connector, force) as bindings::drm_connector_status
+}
+
+unsafe extern "C" fn mode_valid_callback<T: DriverConnector>(
+ connector: *mut bindings::drm_connector,
+ mode: *const bindings::drm_display_mode,
+) -> bindings::drm_mode_status {
+ // SAFETY: This is safe via `DriverConnector`s type invariants.
+ let connector = unsafe { Connector::<T>::from_raw(connector) };
+
+ // SAFETY: DRM guarantees `mode` points to a valid `drm_display_mode` for the duration of this
+ // callback, and only passes us shared access to it.
+ let mode = unsafe { DisplayMode::as_ref(mode) };
+
+ T::mode_valid(connector, mode) as bindings::drm_mode_status
+}
+
/// A [`struct drm_connector`] without a known [`DriverConnector`] implementation.
///
/// This is mainly for situations where our bindings can't infer the [`DriverConnector`]
--
2.55.0
next prev parent reply other threads:[~2026-07-03 3:02 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-17 15:02 [RFC PATCH 0/5] rust: drm: minimal KMS bindings, EDID read, rotation, HDCP defs Mike Lothian
2026-06-17 15:02 ` [RFC PATCH 1/4] rust: drm: add minimal KMS bindings for simple-display-pipe drivers Mike Lothian
2026-06-17 15:02 ` [RFC PATCH 2/4] rust: drm: expose drm_edid.h for reading connector EDID Mike Lothian
2026-06-17 15:02 ` [RFC PATCH 3/4] rust: drm: expose drm::Device::as_raw() Mike Lothian
2026-06-17 15:02 ` [RFC PATCH 4/4] rust: drm: expose drm_blend.h and the atomic new-CRTC-state accessor Mike Lothian
2026-06-17 15:11 ` [RFC PATCH 0/5] rust: drm: minimal KMS bindings, EDID read, rotation, HDCP defs Miguel Ojeda
2026-06-17 15:29 ` Mike Lothian
2026-07-03 3:00 ` [RFC PATCH v2 00/18] rust: drm: safe KMS mode-object layer + evdi bindings Mike Lothian
2026-07-03 3:00 ` [RFC PATCH v2 01/18] rust: drm: kms: forward-port the safe mode-object layer onto the typestate device Mike Lothian
2026-07-07 21:46 ` lyude
2026-07-07 22:21 ` lyude
2026-07-03 3:00 ` [RFC PATCH v2 02/18] rust: drm: kms: adapt the port to current drm-next Mike Lothian
2026-07-03 3:00 ` [RFC PATCH v2 03/18] rust: drm: kms: break the Driver* trait well-formedness cycle Mike Lothian
2026-07-03 3:00 ` [RFC PATCH v2 04/18] rust: drm: kms: build the kernel crate clean under -Znext-solver Mike Lothian
2026-07-03 3:00 ` [RFC PATCH v2 05/18] rust: drm: expose <drm/display/drm_hdcp.h> HDCP 2.2 message definitions Mike Lothian
2026-07-03 3:00 ` [RFC PATCH v2 06/18] rust: drm: kms: add a Framebuffer::vmap() guard Mike Lothian
2026-07-07 21:51 ` lyude
2026-07-03 3:00 ` [RFC PATCH v2 07/18] rust: drm: kms: add safe accessors for common state and connector modes Mike Lothian
2026-07-03 3:00 ` [RFC PATCH v2 08/18] rust: drm: tyr: add the Kms associated type Mike Lothian
2026-07-03 3:00 ` [RFC PATCH v2 09/18] rust: drm: add drm_event delivery Mike Lothian
2026-07-03 3:00 ` [RFC PATCH v2 10/18] rust: drm: allow drivers to declare ioctls from their own uAPI module Mike Lothian
2026-07-03 3:00 ` [RFC PATCH v2 11/18] rust: platform: add runtime platform device creation Mike Lothian
2026-07-03 3:00 ` [RFC PATCH v2 12/18] rust: drm: framebuffer: add geometry accessors, refcounting and a byte-slice vmap Mike Lothian
2026-07-03 3:01 ` [RFC PATCH v2 13/18] rust: i2c: add adapter-provider (bus controller) registration Mike Lothian
2026-07-03 3:01 ` [RFC PATCH v2 14/18] rust: add sysfs device attribute groups Mike Lothian
2026-07-03 3:01 ` [RFC PATCH v2 15/18] rust: drm: support hardware cursor planes with sleepable event delivery Mike Lothian
2026-07-03 3:01 ` [RFC PATCH v2 16/18] rust: drm: add CRTC gamma LUT and plane rotation property bindings Mike Lothian
2026-07-03 3:01 ` Mike Lothian [this message]
2026-07-03 3:01 ` [RFC PATCH v2 18/18] rust: drm: kms: add plane damage-clip accessors Mike Lothian
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=20260703030123.2814-18-mike@fireburn.co.uk \
--to=mike@fireburn.co.uk \
--cc=a.hindborg@kernel.org \
--cc=airlied@gmail.com \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=dakr@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=lyude@redhat.com \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=simona@ffwll.ch \
--cc=tmgross@umich.edu \
/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