Mode Setting

Frame Buffer Creation
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.

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. This document assumes that the driver uses GEM, those handles thus reference GEM objects.

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 initailization 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_reference

and 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.

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).