STRUCT DRM_VBLANK_CRTC(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

🌸 NAME 🌸

okay bestie, welcome to struct drm_vblank_crtc(9) from the Kernel API Manual β€” this is the page all about vblank tracking for a CRTC. πŸ’–


πŸ¦‹ SYNOPSIS πŸ¦‹

struct drm_vblank_crtc {
    struct drm_device *dev;
    wait_queue_head_t queue;
    struct timer_list disable_timer;
    seqlock_t seqlock;
    atomic64_t count;
    ktime_t time;
    atomic_t refcount;
    u32 last;
    u32 max_vblank_count;
    unsigned int inmodeset;
    unsigned int pipe;
    int framedur_ns;
    int linedur_ns;
    struct drm_display_mode hwmode;
    struct drm_vblank_crtc_config config;
    bool enabled;
    struct kthread_worker *worker;
    struct list_head pending_work;
    wait_queue_head_t work_wait_queue;
    struct drm_vblank_crtc_timer vblank_timer;
 };

πŸ‘‘ Members πŸ‘‘

  • dev β€” Pointer to the drm_device. literally the link back to the big device energy. ✨
  • queue β€” Wait queue for vblank waiters. the little hangout spot where the vblank waiters wait their turn. 🫢
  • disable_timer β€” Disable timer for the delayed vblank disabling hysteresis logic. Vblank disabling is controlled through drm_vblank_crtc_config.offdelay_ms and the setting of the drm_device.max_vblank_count value. yes, it's giving delayed-disabling hysteresis realness. πŸ’…
  • seqlock β€” Protect vblank count and time. no cap, keep count and time safe. πŸ”’
  • count β€” Current software vblank counter.

Note that for a given vblank counter value drm_crtc_handle_vblank and drm_crtc_vblank_count or drm_crtc_vblank_count_and_time provide a barrier: Any writes done before calling drm_crtc_handle_vblank will be visible to callers of the later functions, iff the vblank count is the same or a later one.

IMPORTANT: This guarantee requires barriers, therefore never access this field directly. Use drm_crtc_vblank_count instead. bestie please do not touch the counter with your bare hands 😭
  • time β€” Vblank timestamp corresponding to count. the matching timestamp bestie to the counter's main character moment. ⭐
  • refcount β€” Number of users/waiters of the vblank interrupt. Only when this refcount reaches 0 can the hardware interrupt be disabled using disable_timer. zero means the party's over and the interrupt can finally go night-night. πŸ’€
  • last β€” Protected by drm_device.vbl_lock, used for wraparound handling. wraparound business, handled under lock. πŸ”
  • max_vblank_count β€” Maximum value of the vblank registers for this crtc. This value +1 will result in a wrap-around of the vblank register. It is used by the vblank core to handle wrap-arounds.

If set to zero the vblank core will try to guess the elapsed vblanks between times when the vblank interrupt is disabled through high-precision timestamps. That approach is suffering from small races and imprecision over longer time periods, hence exposing a hardware vblank counter is always recommended.

This is the runtime configurable per-crtc maximum set through drm_crtc_set_max_vblank_count. If this is used the driver must leave the device wide drm_device.max_vblank_count at zero.

If non-zero, drm_crtc_funcs.get_vblank_counter must be set. rule, okay? 🌟

  • inmodeset β€” Tracks whether the vblank is disabled due to a modeset. For legacy driver bit 2 additionally tracks whether an additional temporary vblank reference has been acquired to paper over the hardware counter resetting/jumping. KMS drivers should instead just call drm_crtc_vblank_off and drm_crtc_vblank_on, which explicitly save and restore the vblank count. legacy drivers, this is your lore. 🧚
  • pipe β€” drm_crtc_index of the drm_crtc corresponding to this structure. the CRTC's index, iykyk. πŸ’«
  • framedur_ns β€” Frame/Field duration in ns, used by drm_crtc_vblank_helper_get_vblank_timestamp and computed by drm_calc_timestamping_constants. nanoseconds of frame/field duration, slay. πŸŽ€
  • linedur_ns β€” Line duration in ns, used by drm_crtc_vblank_helper_get_vblank_timestamp and computed by drm_calc_timestamping_constants. nanoseconds of line duration, also slay. πŸŽ€
  • hwmode β€” Cache of the current hardware display mode. Only valid when enabled is set. This is used by helpers like drm_crtc_vblank_helper_get_vblank_timestamp. We can't just access the hardware mode by e.g. looking at drm_crtc_state.adjusted_mode, because that one is really hard to get from interrupt context. so we cache the hardware mode like the organized icon we are. πŸ’…
  • config β€” Stores vblank configuration values for a given CRTC. Also, see drm_crtc_vblank_on_config. πŸ’–
  • enabled β€” Tracks the enabling state of the corresponding drm_crtc to avoid double-disabling and hence corrupting saved state. Needed by drivers not using atomic KMS, since those might go through their CRTC disabling functions multiple times. no double-disabling, no corrupted saved state, periodt. πŸ‘‘
  • worker β€” The kthread_worker used for executing vblank works. the worker bee of vblank works. 🐝
  • pending_work β€” A list of scheduled drm_vblank_work items that are waiting for a future vblank. future-vblank plans, queued up. πŸ¦‹
  • work_wait_queue β€” The wait queue used for signaling that a drm_vblank_work item has either finished executing, or was cancelled. finished or cancelled, the queue lets everyone know. 🫢
  • vblank_timer β€” Holds the state of the vblank timer. yep, timer state lives here. ⏰

πŸ’… Description πŸ’…

This structure tracks the vblank state for one CRTC. one CRTC, one vblank-state situation. 🌈

Note that for historical reasons β€” the vblank handling code is still shared with legacy/non-kms drivers β€” this is a free-standing structure not directly connected to struct drm_crtc. But all public interface functions are taking a struct drm_crtc to hide this implementation detail. so yeah, it's lowkey independent but the public API keeps it covered. πŸ™ˆ


πŸŽ€ SEE ALSO πŸŽ€

  • Kernel file ./include/drm/drm_vblank.h struct drm_pending_vblank_event(9), struct drm_vblank_crtc_config(9), struct drm_vblank_crtc_timer(9)

Source/version: ./include/drm, dated October 2026 β€” mwah bestie, that's the page πŸ’‹πŸ’–

πŸ“¦ where this page comes from