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.
dmode using vm,
 vm using dmode,
 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.
      
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.
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.
      
        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).