STRUCT DRM_CRTC(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… struct drm_crtc(9)

okay so bestie, this page lives in the Kernel API Manual, and honestly? it's a whole vibe. it's the manual page for struct drm_crtc β€” the central CRTC control structure. no cap, this is the main character of KMS. let's get into it πŸŽ€


✨ NAME ✨

struct drm_crtc β€” the central CRTC control structure πŸ’–


πŸ¦‹ SYNOPSIS πŸ¦‹

struct drm_crtc {
    struct drm_device *dev;
    struct device_node *port;
    struct list_head head;
    char *name;
    struct drm_modeset_lock mutex;
    struct drm_mode_object base;
    struct drm_plane *primary;
    struct drm_plane *cursor;
    unsigned index;
    int cursor_x;
    int cursor_y;
    bool enabled;
    struct drm_display_mode mode;
    struct drm_display_mode hwmode;
    int x;
    int y;
    const struct drm_crtc_funcs *funcs;
    uint32_t gamma_size;
    uint16_t *gamma_store;
    const struct drm_crtc_helper_funcs *helper_private;
    struct drm_object_properties properties;
    struct drm_property *scaling_filter_property;
    struct drm_property *sharpness_strength_property;
    struct drm_crtc_state *state;
    struct list_head commit_list;
    spinlock_t commit_lock;
    struct dentry *debugfs_entry;
    struct drm_crtc_crc crc;
    unsigned int fence_context;
    spinlock_t fence_lock;
    unsigned long fence_seqno;
    char timeline_name[32];
    struct drm_self_refresh_data *self_refresh_data;
 };

look at all those fields, she's stacked 🫢


🌸 Members 🌸

  • dev β€” the parent DRM device. the mothership, if you will πŸš€
  • port β€” the OF node used by drm_of_find_possible_crtcs.
  • head β€” the list of all CRTCs on dev, linked from drm_mode_config.crtc_list. it's invariant over the lifetime of dev, which means it literally does not need locking. slay, stable data structure πŸ’…
  • name β€” human readable name. can be overwritten by the driver, so drivers get to pick the nickname bestie ✨
  • mutex β€” this provides a read lock for the overall CRTC state (mode, dpms state, ...) and a write lock for everything which can be update without a full modeset (fb, cursor data, CRTC properties ...). a full modeset also need to grab drm_mode_config.connection_mutex.
    • for atomic drivers specifically, this protects state.
  • base β€” the base KMS object for ID tracking etc.
  • primary β€” the Primary plane for this CRTC. note that this is only relevant for legacy IOCTL, it specifies the plane implicitly used by the SETCRTC and PAGE_FLIP IOCTLs. it does not have any significance beyond that. like, that's it, that's her whole job πŸ™ˆ
  • cursor β€” the Cursor plane for this CRTC. note that this is only relevant for legacy IOCTL, it specifies the plane implicitly used by the SETCURSOR and SETCURSOR2 IOCTLs. it does not have any significance beyond that. same deal πŸ’€
  • index β€” position inside the mode_config.list, can be used as an array index. it is invariant over the lifetime of the CRTC. iconic and unchanging fr fr
  • cursor_x β€” current x position of the cursor, used for universal cursor planes because the SETCURSOR IOCTL only can update the framebuffer without supplying the coordinates.
    • drivers should not use this directly. atomic drivers should look at drm_plane_state.crtc_x of the cursor plane instead.
  • cursor_y β€” current y position of the cursor, used for universal cursor planes because the SETCURSOR IOCTL only can update the framebuffer without supplying the coordinates.
    • drivers should not use this directly. atomic drivers should look at drm_plane_state.crtc_y of the cursor plane instead.
  • enabled β€” is this CRTC enabled? should only be used by legacy drivers. atomic drivers should instead consult drm_crtc_state.enable and drm_crtc_state.active. atomic drivers can update this by calling drm_atomic_helper_update_legacy_modeset_state.
  • mode β€” current mode timings. should only be used by legacy drivers, atomic drivers should instead consult drm_crtc_state.mode. atomic drivers can update this by calling drm_atomic_helper_update_legacy_modeset_state.
  • hwmode β€” programmed mode in hw, after adjustments for encoders, crtc, panel scaling etc. should only be used by legacy drivers, for high precision vblank timestamps in drm_crtc_vblank_helper_get_vblank_timestamp.
    • note that atomic drivers should not use this, but instead use drm_crtc_state.adjusted_mode. and for high-precision timestamps drm_crtc_vblank_helper_get_vblank_timestamp used drm_vblank_crtc.hwmode, which is filled out by calling drm_calc_timestamping_constants.
  • x β€” x position on screen. should only be used by legacy drivers, atomic drivers should look at drm_plane_state.crtc_x of the primary plane instead. updated by calling drm_atomic_helper_update_legacy_modeset_state.
  • y β€” y position on screen. should only be used by legacy drivers, atomic drivers should look at drm_plane_state.crtc_y of the primary plane instead. updated by calling drm_atomic_helper_update_legacy_modeset_state.
  • funcs β€” CRTC control functions ✨
  • gamma_size β€” size of legacy gamma ramp reported to userspace. set up by calling drm_mode_crtc_set_gamma_size.
    • note that atomic drivers need to instead use drm_crtc_state.gamma_lut. see drm_crtc_enable_color_mgmt.
  • gamma_store β€” gamma ramp values used by the legacy SETGAMMA and GETGAMMA IOCTls. set up by calling drm_mode_crtc_set_gamma_size.
    • note that atomic drivers need to instead use drm_crtc_state.gamma_lut. see drm_crtc_enable_color_mgmt.
  • helper_private β€” mid-layer private data πŸ•΅οΈβ€β™€οΈ
  • properties β€” property tracking for this CRTC.
  • scaling_filter_property β€” property to apply a particular filter while scaling.
  • sharpness_strength_property β€” property to apply the intensity of the sharpness requested.
  • state β€” current atomic state for this CRTC.
    • this is protected by mutex. note that nonblocking atomic commits access the current CRTC state without taking locks. either by going through the struct drm_atomic_commit pointers, see for_each_oldnew_crtc_in_state, for_each_old_crtc_in_state and for_each_new_crtc_in_state. or through careful ordering of atomic commit operations as implemented in the atomic helpers, see struct drm_crtc_commit. lowkey the most delicate part of this whole page ngl 😭
  • commit_list β€” list of drm_crtc_commit structures tracking pending commits. protected by commit_lock. this list holds its own full reference, as does the ongoing commit.
    • "Note that the commit for a state change is also tracked in drm_crtc_state.commit. For accessing the immediately preceding commit in an atomic update it is recommended to just use that pointer in the old CRTC state, since accessing that doesn't need any locking or list-walking. commit_list should only be used to stall for framebuffer cleanup that's signalled through drm_crtc_commit.cleanup_done."
  • commit_lock β€” spinlock to protect commit_list.
  • debugfs_entry β€” debugfs directory for this CRTC.
  • crc β€” configuration settings of CRC capture.
  • fence_context β€” timeline context used for fence operations.
  • fence_lock β€” spinlock to protect the fences in the fence_context.
  • fence_seqno β€” seqno variable used as monotonic counter for the fences created on the CRTC's timeline.
  • timeline_name β€” the name of the CRTC's fence timeline.
  • self_refresh_data β€” holds the state for the self refresh helpers.
    • initialized via drm_self_refresh_helper_init.

πŸ’œ Description πŸ’œ

each CRTC may have one or more connectors associated with it. this structure allows the CRTC to be controlled. that's the whole description, she's short and she knows it πŸ‘‘


πŸ”₯ SEE ALSO πŸ”₯

kernel file ./include/drm/drm_crtc.h, struct drm_crtc_state(9), struct drm_crtc_funcs(9), struct drm_mode_set(9), drmm_crtc_alloc_with_planes(9), drm_crtc_index(9), drm_crtc_mask(9), drm_crtc_find(9), drm_for_each_crtc(9), drm_for_each_crtc_reverse(9) β€” go read those too bestie, iykyk 🌈


and that's the page! πŸŽ€ this came out of ./include/drm, dated October 2026, and the footer still reads struct drm_crtc(9) β€” go off, documentation. mwah πŸ’‹βœ¨

πŸ“¦ where this page comes from