STRUCT DRM_CONNECTOR_HELPER_FUNCS(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

🌸 struct drm_connector_helper_funcs πŸ’… (Kernel API Manual, section 9)

okay bestie, welcome to the connector helper ops ✨ this is the whole Kernel API Manual page for struct drm_connector_helper_funcs, and it's giving very important, so hydrate and let's go 🫢


NAME πŸŽ€

struct drm_connector_helper_funcs β€” the helper operations for connectors, no cap πŸ’–

Basically: this is the lil struct where connector drivers drop their custom callbacks. Main character energy for sure πŸ‘‘


SYNOPSIS ⭐

here's the whole struct, verbatim, every last field β€” do not lose a single one, i'm watching πŸ‘€

struct drm_connector_helper_funcs {
    int (*get_modes)(struct drm_connector *connector);
    int (*detect_ctx)(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx, bool force);
    enum drm_mode_status (*mode_valid)(struct drm_connector *connector, const struct drm_display_mode *mode);
    int (*mode_valid_ctx)(struct drm_connector *connector, const struct drm_display_mode *mode, struct drm_modeset_acquire_ctx *ctx, enum drm_mode_status *status);
    struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
    struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector, struct drm_atomic_commit *state);
    int (*atomic_check)(struct drm_connector *connector, struct drm_atomic_commit *state);
    void (*atomic_commit)(struct drm_connector *connector, struct drm_atomic_commit *state);
    int (*prepare_writeback_job)(struct drm_writeback_connector *connector, struct drm_writeback_job *job);
    void (*cleanup_writeback_job)(struct drm_writeback_connector *connector, struct drm_writeback_job *job);
    void (*enable_hpd)(struct drm_connector *connector);
    void (*disable_hpd)(struct drm_connector *connector);
 };

like… the way that's twelve function pointers just vibing in there 😭 every single one is a callback, and they're all listed above so you literally can't miss them. lowkey iconic struct design ngl πŸ’…

buckle up, more parts coming next β€” we're just getting started 🌈

✨ MEMBERS ✨

πŸ’– get_modes πŸ’–

Okay so this one's job is literally to fill in all the modes that are currently valid for the sink into the drm_connector.probed_modes list. That's it, that's the vibe. It should also update the EDID property by calling drm_connector_update_edid_property β€” don't forget that part bestie, it matters. 🫢

The usual way to implement this is to cache the EDID you retrieved in the probe callback somewhere in the driver-private connector structure. Then in this function, drivers parse the modes out of the EDID and add them by calling drm_add_edid_modes. But connectors that drive a fixed panel can also manually add specific modes using drm_mode_probed_add. And heads up β€” drivers which manually add modes should also make sure that the drm_connector.display_info, drm_connector.width_mm and drm_connector.height_mm fields are filled in. No skipping that. πŸ’…

Note that the caller function will automatically add standard VESA DMT modes up to 1024x768 if the .get_modes helper operation returns no mode and if the connector status is connector_status_connected or connector_status_unknown. So like, there is no need to call drm_add_modes_noedid manually in that case. Let the caller cook. πŸ”₯

Virtual drivers that just want some standard VESA mode with a given resolution can call drm_add_modes_noedid, and mark the preferred one using drm_set_preferred_mode. Slay.

This function is only called after the detect hook has indicated that a sink is connected, and when the EDID isn't overridden through sysfs or the kernel commandline. So the stars have to align ✨

This callback is used by the probe helpers in e.g. drm_helper_probe_single_connector_modes.

To avoid races with concurrent connector state updates, the helper libraries always call this with the drm_mode_config.connection_mutex held. Because of this it's safe to inspect drm_connector->state. πŸŽ€

RETURNS:

The number of modes added by calling drm_mode_probed_add. Return 0 on failures (no modes) instead of negative error codes. Like, zero, not a sad little negative number, okay? πŸ’€


🌸 detect_ctx 🌸

Check to see if anything is attached to the connector. The parameter force is set to false whilst polling, true when checking the connector due to a user request. force can be used by the driver to avoid expensive, destructive operations during automated probing β€” very main character energy of it tbh.

This callback is optional, if not implemented the connector will be considered as always being attached. Iconic shortcut behavior.

This is the atomic version of drm_connector_funcs.detect.

To avoid races against concurrent connector state updates, the helper libraries always call this with ctx set to a valid context, and drm_mode_config.connection_mutex will always be locked with the ctx parameter set to this ctx. This allows taking additional locks as required. πŸ”’

RETURNS:

drm_connector_status indicating the connector's status, or the error code returned by drm_modeset_lock, -EDEADLK.


πŸ¦‹ mode_valid πŸ¦‹

Callback to validate a mode for a connector, irrespective of the specific display configuration. Just the mode itself, no context, no drama.

This callback is used by the probe helpers to filter the mode list (which is usually derived from the EDID data block from the sink). See e.g. drm_helper_probe_single_connector_modes.

This function is optional.

NOTE: This only filters the mode list supplied to userspace in the GETCONNECTOR IOCTL. Compared to drm_encoder_helper_funcs.mode_valid, drm_crtc_helper_funcs.mode_valid and drm_bridge_funcs.mode_valid, which are also called by the atomic helpers from drm_atomic_helper_check_modeset. This allows userspace to force and ignore sink constraint (like the pixel clock limits in the screen's EDID), which is useful for e.g. testing, or working around a broken EDID. Any source hardware constraint (which always need to be enforced) therefore should be checked in one of the above callbacks, and not this one here. Don't get it twisted!! 😭

To avoid races with concurrent connector state updates, the helper libraries always call this with the drm_mode_config.connection_mutex held. Because of this it's safe to inspect drm_connector->state.

RETURNS:

Either drm_mode_status.MODE_OK or one of the failure reasons in enum drm_mode_status.


🧚 mode_valid_ctx 🧚

Callback to validate a mode for a connector, irrespective of the specific display configuration. (Yes it's the same one-liner as above β€” it's the atomic twin, okay, let it have this.)

This callback is used by the probe helpers to filter the mode list (which is usually derived from the EDID data block from the sink). See e.g. drm_helper_probe_single_connector_modes.

This function is optional, and is the atomic version of drm_connector_helper_funcs.mode_valid.

To allow for accessing the atomic state of modesetting objects, the helper libraries always call this with ctx set to a valid context, and drm_mode_config.connection_mutex will always be locked with the ctx parameter set to ctx. This allows for taking additional locks as required.

Even though additional locks may be acquired, this callback is still expected not to take any constraints into account which would be influenced by the currently set display state β€” such constraints should be handled in the driver's atomic check. For example, if a connector shares display bandwidth with other connectors then it would be ok to validate the minimum bandwidth requirement of a mode against the maximum possible bandwidth of the connector. But it wouldn't be ok to take the current bandwidth usage of other connectors into account, as this would change depending on the display state. Read that twice, it's the whole vibe check of this callback. 🧠✨

Returns: 0 if drm_connector_helper_funcs.mode_valid_ctx succeeded and wrote the enum drm_mode_status value to status, or a negative error code otherwise.


πŸ‘‘ best_encoder πŸ‘‘

This function should select the best encoder for the given connector. Pick your fave. πŸ’…

This function is used by both the atomic helpers (in the drm_atomic_helper_check_modeset function) and in the legacy CRTC helpers.

NOTE: In atomic drivers this function is called in the check phase of an atomic update. The driver is not allowed to change or inspect anything outside of arguments passed-in. Atomic drivers which need to inspect dynamic configuration state should instead use atomic_best_encoder. Stay in your lane, bestie 🚧

You can leave this function to NULL if the connector is only attached to a single encoder. In this case, the core will call drm_connector_get_single_encoder for you. Free labor, we love to see it.

RETURNS:

Encoder that should be used for the given connector and connector state, or NULL if no suitable encoder exists. Note that the helpers will ensure that encoders aren't used twice, drivers should not check for this. They've got it handled fr fr.


⭐ atomic_best_encoder ⭐

This is the atomic version of best_encoder for atomic drivers which need to select the best encoder depending upon the desired configuration and can't select it statically. Dynamic queen behavior.

This function is used by drm_atomic_helper_check_modeset. If it is not implemented, the core will fallback to best_encoder (or drm_connector_get_single_encoder if best_encoder is NULL). Built-in backup plan, we stan. 🫢

NOTE: This function is called in the check phase of an atomic update. The driver is not allowed to change anything outside of the drm_atomic_commit update tracking structure passed in.

RETURNS:

Encoder that should be used for the given connector and connector state, or NULL if no suitable encoder exists. Note that the helpers will ensure that encoders aren't used twice, drivers should not check for this.


🌈 atomic_check 🌈

This hook is used to validate connector state. This function is called from drm_atomic_helper_check_modeset, and is called when a connector property is set, or a modeset on the crtc is forced.

Because drm_atomic_helper_check_modeset may be called multiple times, this function should handle being called multiple times as well. Idempotency is the moment, no cap. πŸ”

This function is also allowed to inspect any other object's state and can add more state objects to the atomic commit if needed. Care must be taken though to ensure that state check and compute functions for these added states are all called, and derived state in other objects all updated. Again the recommendation is to just call check helpers until a maximal configuration is reached. Like, keep going until it's maxed out, then stop. πŸ’―

NOTE: This function is called in the check phase of an atomic update. The driver is not allowed to change anything outside of the free-standing state objects passed-in or assembled in the overall drm_atomic_commit update tracking structure.

RETURNS:

0 on success, -EINVAL if the state or the transition can't be supported, -ENOMEM on memory allocation failure and -EDEADLK if an attempt to obtain another state object ran into a drm_modeset_lock deadlock. All the error codes, all the drama 😭


πŸŽ€ atomic_commit πŸŽ€

This hook is to be used by drivers implementing writeback connectors that need a point when to commit the writeback job to the hardware. The writeback_job to commit is available in the new connector state, in drm_connector_state.writeback_job.

This hook is optional.

This callback is used by the atomic modeset helpers.


πŸ“ prepare_writeback_job πŸ“

As writeback jobs contain a framebuffer, drivers may need to prepare and clean them up the same way they can prepare and clean up framebuffers for planes. This optional connector operation is used to support the preparation of writeback jobs. The job prepare operation is called from drm_atomic_helper_prepare_planes for struct drm_writeback_connector connectors only. Only those ones!! 🚨

This operation is optional.

This callback is used by the atomic modeset helpers.


πŸ¦‹ cleanup_writeback_job πŸ¦‹

This optional connector operation is used to support the cleanup of writeback jobs. The job cleanup operation is called from the existing drm_writeback_cleanup_job function, invoked both when destroying the job as part of an aborted commit, or when the job completes. Both exits, same cleanup, balance restored ✨

This operation is optional.

This callback is used by the atomic modeset helpers.


πŸ”₯ enable_hpd πŸ”₯

Enable hot-plug detection for the connector.

This operation is optional.

This callback is used by the drm_kms_helper_poll_enable helpers.

This operation does not need to perform any hpd state tracking as the DRM core handles that maintenance and ensures the calls to enable and disable hpd are balanced. So like, don't do the bookkeeping yourself, that's the core's job πŸ’…


πŸ’œ disable_hpd πŸ’œ

Disable hot-plug detection for the connector.

This operation is optional.

This callback is used by the drm_kms_helper_poll_disable helpers.

This operation does not need to perform any hpd state tracking as the DRM core handles that maintenance and ensures the calls to enable and disable hpd are balanced. Same deal as enable_hpd, they're a matched set πŸŽ€


🌸 DESCRIPTION 🌸

These functions are used by the atomic and legacy modeset helpers and by the probe helpers. That's the whole family tree right there β€” atomic besties, legacy besties, probe besties, everybody eats. πŸ’–

✨ SEE ALSO ✨

okay bestie, you're literally at the end, and this is the part where the manpage hands you your little reading list 🫢 like a syllabus but make it iconic. Go read these next, they're all in the family:

  • Kernel file ./include/drm/drm_modeset_helper_vtables.h overview(9) β€” the actual mothership file where all these vtables live, lowkey the source of truth πŸ’…
  • struct drm_crtc_helper_funcs(9) β€” the CRT(C) bestie ✨
  • drm_crtc_helper_add(9) β€” how you attach those helpers, no cap
  • struct drm_encoder_helper_funcs(9) β€” encoder helper energy πŸŽ€
  • drm_encoder_helper_add(9) β€” the attach step for encoders, periodt
  • drm_connector_helper_add(9) β€” the one you literally just met, hi again πŸ‘‹
  • struct drm_plane_helper_funcs(9) β€” plane helper vibes, we love her 🌸
  • drm_plane_helper_add(9) β€” attaching the plane helpers, slay
  • struct drm_mode_config_helper_funcs(9) β€” the mode config helper squad, main character energy 🌈

that's it, that's the page! you made it all the way through, bestie πŸ˜­πŸ’– congrats, you're officially a drm_...helper_funcs understander.

and for the cute sign-off: this whole thing lives in the kernel tree at ./include/drm, the manual's version stamp says October 2026, and yes, it's still titled struct drm_...helper_funcs(9) πŸŽ€ go forth and set up your helper vtables correctly, iykyk πŸ¦‹

πŸ“¦ where this page comes from