STRUCT DRM_PLANE_HELPER_FUNCS(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’– struct drm_plane_helper_funcs β€” Kernel API Manual, section 9 πŸ’–

🌸 NAME 🌸

struct drm_plane_helper_funcs - helper operations for planes

✨ SYNOPSIS ✨

       struct drm_plane_helper_funcs {
           int (*prepare_fb)(struct drm_plane *plane, struct drm_plane_state
       *new_state);
           void (*cleanup_fb)(struct drm_plane *plane, struct drm_plane_state
       *old_state);
           int (*begin_fb_access)(struct drm_plane *plane, struct
       drm_plane_state *new_plane_state);
           void (*end_fb_access)(struct drm_plane *plane, struct
       drm_plane_state *new_plane_state);
           int (*atomic_check)(struct drm_plane *plane, struct
       drm_atomic_commit *state);
           void (*atomic_update)(struct drm_plane *plane, struct
       drm_atomic_commit *state);
           void (*atomic_enable)(struct drm_plane *plane, struct
       drm_atomic_commit *state);
           void (*atomic_disable)(struct drm_plane *plane, struct
       drm_atomic_commit *state);
           int (*atomic_async_check)(struct drm_plane *plane, struct
       drm_atomic_commit *state, bool flip);
           void (*atomic_async_update)(struct drm_plane *plane, struct
       drm_atomic_commit *state);
           int (*get_scanout_buffer)(struct drm_plane *plane, struct
       drm_scanout_buffer *sb);
           void (*panic_flush)(struct drm_plane *plane);
        };

πŸŽ€ Members πŸŽ€

Okay so this struct is the plane helper ops menu, and the vibe check is simple: these are the callbacks the atomic modeset helpers can call on your plane. Some are required-ish for certain setups, some are optional, and the details matter a lot. Let’s go member by member, bestie πŸ’…

🧚 prepare_fb

This hook is literally here to prepare a framebuffer for scanout β€” think pinning its backing storage, relocating it into a contiguous block of VRAM, or flushing caches. All the prep-coded stuff.

This function must not block for outstanding rendering, since it is called in the context of the atomic IOCTL even for async commits to be able to return any errors to userspace. Instead the recommended way is to fill out the drm_plane_state.fence of the passed-in drm_plane_state. If the driver doesn't support native fences then equivalent functionality should be implemented through private members in the plane structure.

For GEM drivers who neither have a prepare_fb nor cleanup_fb hook set, drm_gem_plane_helper_prepare_fb is called automatically to implement this. Other drivers which need additional plane processing can call drm_gem_plane_helper_prepare_fb from their prepare_fb hook.

The resources acquired in prepare_fb persist after the end of the atomic commit. Resources that can be released at the commit's end should be acquired in begin_fb_access and released in end_fb_access. For example, a GEM buffer's pin operation belongs into prepare_fb to keep the buffer pinned after the commit. But a vmap operation for shadow-plane helpers belongs into begin_fb_access, so that atomic helpers remove the mapping at the end of the commit.

The helpers will call cleanup_fb with matching arguments for every successful call to this hook.

This callback is used by the atomic modeset helpers, but it is optional. See begin_fb_access for preparing per-commit resources.

RETURNS:

0 on success or one of the following negative error codes allowed by the drm_mode_config_funcs.atomic_commit vfunc. When using helpers this callback is the only one which can fail an atomic commit, everything else must complete successfully.

🧼 cleanup_fb

This hook is called to clean up any resources allocated for the given framebuffer and plane configuration in prepare_fb.

This callback is used by the atomic modeset helpers, but it is optional.

πŸ”“ begin_fb_access

This hook prepares the plane for access during an atomic commit. In contrast to prepare_fb, resources acquired in begin_fb_access are released at the end of the atomic commit in end_fb_access.

For example, with shadow-plane helpers, the GEM buffer's vmap operation belongs into begin_fb_access, so that the buffer's memory will be unmapped at the end of the commit in end_fb_access. But a GEM buffer's pin operation belongs into prepare_fb to keep the buffer pinned after the commit.

The callback is used by the atomic modeset helpers, but it is optional. See end_fb_cleanup for undoing the effects of begin_fb_access and prepare_fb for acquiring resources until the next pageflip.

Returns: 0 on success, or a negative errno code otherwise.

πŸ”’ end_fb_access

This hook cleans up resources allocated by begin_fb_access. It’s called at the end of a commit for the new plane state.

βœ… atomic_check

Drivers should check plane specific constraints in this hook.

When using drm_atomic_helper_check_planes plane's atomic_check hooks are called before the ones for CRTCs, which allows drivers to request shared resources that the CRTC controls here. For more complicated dependencies the driver can call the provided check helpers multiple times until the computed state has a final configuration and everything has been checked.

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.

This callback is used by the atomic modeset helpers, but it is optional.

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.

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.

πŸ”„ atomic_update

Drivers should use this function to update the plane state. This hook is called in-between the drm_crtc_helper_funcs.atomic_begin and drm_crtc_helper_funcs.atomic_flush callbacks.

Note that the power state of the display pipe when this function is called depends upon the exact helpers and calling sequence the driver has picked. See drm_atomic_helper_commit_planes for a discussion of the tradeoffs and variants of plane commit helpers.

This callback is used by the atomic modeset helpers, but it is optional.

🟒 atomic_enable

Drivers should use this function to unconditionally enable a plane. This hook is called in-between the drm_crtc_helper_funcs.atomic_begin and drm_crtc_helper_funcs.atomic_flush callbacks. It is called after atomic_update, which will be called for all enabled planes. Drivers that use atomic_enable should set up a plane in atomic_update and afterwards enable the plane in atomic_enable. If a plane needs to be enabled before installing the scanout buffer, drivers can still do so in atomic_update.

Note that the power state of the display pipe when this function is called depends upon the exact helpers and calling sequence the driver has picked. See drm_atomic_helper_commit_planes for a discussion of the tradeoffs and variants of plane commit helpers.

This callback is used by the atomic modeset helpers, but it is optional. If implemented, atomic_enable should be the inverse of atomic_disable. Drivers that don't want to use either can still implement the complete plane update in atomic_update.

πŸ”΄ atomic_disable

Drivers should use this function to unconditionally disable a plane. This hook is called in-between the drm_crtc_helper_funcs.atomic_begin and drm_crtc_helper_funcs.atomic_flush callbacks. It is an alternative to atomic_update, which will be called for disabling planes, too, if the atomic_disable hook isn't implemented.

This hook is also useful to disable planes in preparation of a modeset, by calling drm_atomic_helper_disable_planes_on_crtc from the drm_crtc_helper_funcs.disable hook.

Note that the power state of the display pipe when this function is called depends upon the exact helpers and calling sequence the driver has picked. See drm_atomic_helper_commit_planes for a discussion of the tradeoffs and variants of plane commit helpers.

This callback is used by the atomic modeset helpers, but it is optional. It's intended to reverse the effects of atomic_enable.

⚑ atomic_async_check

Drivers should set this function pointer to check if the plane's atomic state can be updated in a async fashion. Here async means "not vblank synchronized".

This hook is called by drm_atomic_async_check to establish if a given update can be committed asynchronously, that is, if it can jump ahead of the state currently queued for update.

This function is also used by drm_atomic_set_property to determine if the plane can be flipped in async. The flip flag is used to distinguish if the function is used for just the plane state or for a flip.

RETURNS:

Return 0 on success and any error returned indicates that the update can not be applied in asynchronous manner.

πŸŒ€ atomic_async_update

Drivers should set this function pointer to perform asynchronous updates of planes, that is, jump ahead of the currently queued state and update the plane. Here async means "not vblank synchronized".

This hook is called by drm_atomic_helper_async_commit.

An async update will happen on legacy cursor updates. An async update won't happen if there is an outstanding commit modifying the same plane.

When doing async_update drivers shouldn't replace the drm_plane_state but update the current one with the new plane configurations in the new plane_state.

Drivers should also swap the framebuffers between current plane state (drm_plane.state) and new_state. This is required since cleanup for async commits is performed on the new state, rather than old state like for traditional commits. Since we want to give up the reference on the current (old) fb instead of our brand new one, swap them in the driver during the async commit.

FIXME:

  • It only works for single plane updates
  • Async Pageflips are not supported yet
  • Some hw might still scan out the old buffer until the next vblank, however we let go of the fb references as soon as we run this hook. For now drivers must implement their own workers for deferring if needed, until a common solution is created.

get_scanout_buffer πŸ–ΌοΈ

okay so this one grabs the current scanout buffer so drm_panic can draw a message on it. bestie, the driver should do the minimum changes needed to hand over a buffer that can actually show the panic screen β€” like, low effort on purpose, no overachieving here.

rn only linear buffers are supported. non-linear buffer support is literally on the TODO list πŸ’€ so don't come for her.

dev.mode_config.panic_lock is taken before this function gets called, so you can safely poke at plane.state. 🫢

it gets called from a panic callback, so it has to follow all the panic callback restrictions. please read the docs at drm_panic_trylock for the in-depth tea on what's safe and what's absolutely not allowed πŸ™ˆ

it's a best effort mode β€” so yes, in some complex cases the panic screen just won't show up. that's expected, not a bug.

the returned drm_scanout_buffer.map must be valid if no error code comes back. no cap.

Return: 0 on success, negative errno on failure.


panic_flush πŸ’¨

this one is used by drm_panic and it's called after the panic screen has been drawn to the scanout buffer. in here the driver can send extra commands to the hardware to actually make the scanout buffer visible β€” like the final "go live" moment ✨

it's only called if get_scanout_buffer returned successfully, and dev.mode_config.panic_lock is held during the entire sequence πŸ”’

and same deal as above: it's called from a panic callback, so it must follow the restrictions. go read drm_panic_trylock for the full rundown on what's safe and what's not allowed πŸ‘‘


✨ DESCRIPTION ✨

these functions are used by the atomic helpers. periodt. πŸ’…


πŸ¦‹ SEE ALSO πŸ¦‹


that's a wrap on part 2, bestie πŸŽ€ this lil doc lives at ./include/drm, it's the October 2026 edition, and it's filed under struct drm_...helper_funcs(9). go forth and slay your panic screens πŸŒˆπŸ’–

πŸ“¦ where this page comes from