Mode Setting
Prev | Chapter 2. DRM Internals | Next

## Mode Setting

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.

-     int min_width, min_height;
      int max_width, max_height;

  Minimum and maximum width and height of the frame buffers in pixel units.

-     struct drm_mode_config_funcs *funcs;

  Mode setting functions.

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

Prev | Up | Next
Memory management | Home | KMS Initialization and Cleanup