Mode Setting

Display Modes Function Reference
Atomic Mode Setting Function Reference
Frame Buffer Creation
Dumb Buffer Objects
Output Polling
Locking

Drivers must initialize the mode setting core by calling drm_mode_config_init on the DRM device. The function initializes the drm_device mode_config field and never fails. Once done, mode configuration must be setup by initializing the following fields.

Display Modes Function Reference

drm_mode_is_stereo — check for stereo mode flags
drm_mode_debug_printmodeline — print a mode to dmesg
drm_mode_create — create a new display mode
drm_mode_destroy — remove a mode
drm_mode_probed_add — add a mode to a connector's probed_mode list
drm_cvt_mode — create a modeline based on the CVT algorithm
drm_gtf_mode_complex — create the modeline based on the full GTF algorithm
drm_gtf_mode — create the modeline based on the GTF algorithm
drm_display_mode_from_videomode — fill in dmode using vm,
drm_display_mode_to_videomode — fill in vm using dmode,
of_get_drm_display_mode — get a drm_display_mode from devicetree
drm_mode_set_name — set the name on a mode
drm_mode_vrefresh — get the vrefresh of a mode
drm_mode_set_crtcinfo — set CRTC modesetting timing parameters
drm_mode_copy — copy the mode
drm_mode_duplicate — allocate and duplicate an existing mode
drm_mode_equal — test modes for equality
drm_mode_equal_no_clocks_no_stereo — test modes for equality
drm_mode_validate_basic — make sure the mode is somewhat sane
drm_mode_validate_size — make sure modes adhere to size constraints
drm_mode_prune_invalid — remove invalid modes from mode list
drm_mode_sort — sort mode list
drm_mode_connector_list_update — update the mode list for the connector
drm_mode_parse_command_line_for_connector — parse command line modeline for connector
drm_mode_create_from_cmdline_mode — convert a command line modeline into a DRM display mode

Atomic Mode Setting Function Reference

drm_atomic_state_alloc — allocate atomic state
drm_atomic_state_clear — clear state object
drm_atomic_state_free — free all memory for an atomic state
drm_atomic_get_crtc_state — get crtc state
drm_atomic_crtc_set_property — set property on CRTC
drm_atomic_get_plane_state — get plane state
drm_atomic_plane_set_property — set property on plane
drm_atomic_get_connector_state — get connector state
drm_atomic_connector_set_property — set property on connector.
drm_atomic_set_crtc_for_plane — set crtc for plane
drm_atomic_set_fb_for_plane — set framebuffer for plane
drm_atomic_set_crtc_for_connector — set crtc for connector
drm_atomic_add_affected_connectors — add connectors for crtc
drm_atomic_connectors_for_crtc — count number of connected outputs
drm_atomic_legacy_backoff — locking backoff for legacy ioctls
drm_atomic_check_only — check whether a given config would work
drm_atomic_commit — commit configuration atomically
drm_atomic_async_commit — atomicasync configuration commit

Frame Buffer Creation

struct drm_framebuffer *(*fb_create)(struct drm_device *dev,
				     struct drm_file *file_priv,
				     struct drm_mode_fb_cmd2 *mode_cmd);

Frame buffers are abstract memory objects that provide a source of pixels to scanout to a CRTC. Applications explicitly request the creation of frame buffers through the DRM_IOCTL_MODE_ADDFB(2) ioctls and receive an opaque handle that can be passed to the KMS CRTC control, plane configuration and page flip functions.

Frame buffers rely on the underneath memory manager for low-level memory operations. When creating a frame buffer applications pass a memory handle (or a list of memory handles for multi-planar formats) through the drm_mode_fb_cmd2 argument. For drivers using GEM as their userspace buffer management interface this would be a GEM handle. Drivers are however free to use their own backing storage object handles, e.g. vmwgfx directly exposes special TTM handles to userspace and so expects TTM handles in the create ioctl and not GEM handles.

Drivers must first validate the requested frame buffer parameters passed through the mode_cmd argument. In particular this is where invalid sizes, pixel formats or pitches can be caught.

If the parameters are deemed valid, drivers then create, initialize and return an instance of struct drm_framebuffer. If desired the instance can be embedded in a larger driver-specific structure. Drivers must fill its width, height, pitches, offsets, depth, bits_per_pixel and pixel_format fields from the values passed through the drm_mode_fb_cmd2 argument. They should call the drm_helper_mode_fill_fb_struct helper function to do so.

The initialization of the new framebuffer instance is finalized with a call to drm_framebuffer_init which takes a pointer to DRM frame buffer operations (struct drm_framebuffer_funcs). Note that this function publishes the framebuffer and so from this point on it can be accessed concurrently from other threads. Hence it must be the last step in the driver's framebuffer initialization sequence. Frame buffer operations are

  • int (*create_handle)(struct drm_framebuffer *fb,
    		     struct drm_file *file_priv, unsigned int *handle);

    Create a handle to the frame buffer underlying memory object. If the frame buffer uses a multi-plane format, the handle will reference the memory object associated with the first plane.

    Drivers call drm_gem_handle_create to create the handle.

  • void (*destroy)(struct drm_framebuffer *framebuffer);

    Destroy the frame buffer object and frees all associated resources. Drivers must call drm_framebuffer_cleanup to free resources allocated by the DRM core for the frame buffer object, and must make sure to unreference all memory objects associated with the frame buffer. Handles created by the create_handle operation are released by the DRM core.

  • int (*dirty)(struct drm_framebuffer *framebuffer,
    	     struct drm_file *file_priv, unsigned flags, unsigned color,
    	     struct drm_clip_rect *clips, unsigned num_clips);

    This optional operation notifies the driver that a region of the frame buffer has changed in response to a DRM_IOCTL_MODE_DIRTYFB ioctl call.

The lifetime of a drm framebuffer is controlled with a reference count, drivers can grab additional references with drm_framebuffer_referenceand drop them again with drm_framebuffer_unreference. For driver-private framebuffers for which the last reference is never dropped (e.g. for the fbdev framebuffer when the struct drm_framebuffer is embedded into the fbdev helper struct) drivers can manually clean up a framebuffer at module unload time with drm_framebuffer_unregister_private.

Dumb Buffer Objects

The KMS API doesn't standardize backing storage object creation and leaves it to driver-specific ioctls. Furthermore actually creating a buffer object even for GEM-based drivers is done through a driver-specific ioctl - GEM only has a common userspace interface for sharing and destroying objects. While not an issue for full-fledged graphics stacks that include device-specific userspace components (in libdrm for instance), this limit makes DRM-based early boot graphics unnecessarily complex.

Dumb objects partly alleviate the problem by providing a standard API to create dumb buffers suitable for scanout, which can then be used to create KMS frame buffers.

To support dumb objects drivers must implement the dumb_create, dumb_destroy and dumb_map_offset operations.

  • int (*dumb_create)(struct drm_file *file_priv, struct drm_device *dev,
                       struct drm_mode_create_dumb *args);

    The dumb_create operation creates a driver object (GEM or TTM handle) suitable for scanout based on the width, height and depth from the struct drm_mode_create_dumb argument. It fills the argument's handle, pitch and size fields with a handle for the newly created object and its line pitch and size in bytes.

  • int (*dumb_destroy)(struct drm_file *file_priv, struct drm_device *dev,
                        uint32_t handle);

    The dumb_destroy operation destroys a dumb object created by dumb_create.

  • int (*dumb_map_offset)(struct drm_file *file_priv, struct drm_device *dev,
                           uint32_t handle, uint64_t *offset);

    The dumb_map_offset operation associates an mmap fake offset with the object given by the handle and returns it. Drivers must use the drm_gem_create_mmap_offset function to associate the fake offset as described in the section called “GEM Objects Mapping”.

Note that dumb objects may not be used for gpu acceleration, as has been attempted on some ARM embedded platforms. Such drivers really must have a hardware-specific ioctl to allocate suitable buffer objects.

Output Polling

void (*output_poll_changed)(struct drm_device *dev);

This operation notifies the driver that the status of one or more connectors has changed. Drivers that use the fb helper can just call the drm_fb_helper_hotplug_event function to handle this operation.

Locking

Beside some lookup structures with their own locking (which is hidden behind the interface functions) most of the modeset state is protected by the dev-<mode_config.lock mutex and additionally per-crtc locks to allow cursor updates, pageflips and similar operations to occur concurrently with background tasks like output detection. Operations which cross domains like a full modeset always grab all locks. Drivers there need to protect resources shared between crtcs with additional locking. They also need to be careful to always grab the relevant crtc locks if a modset functions touches crtc state, e.g. for load detection (which does only grab the mode_config.lock to allow concurrent screen updates on live crtcs).