Linux GPU Driver Developer’s Guide

Author:Jesse Barnes Initial version
Author:Laurent Pinchart Driver internals
Author:Daniel Vetter Contributions all over the place
Author:Lukas Wunner vga_switcheroo documentation
Date:2015-10-11

This first part of the GPU Driver Developer’s Guide documents core DRM code, helper libraries for writing drivers and generic userspace interfaces exposed by DRM drivers.

Introduction

The Linux DRM layer contains code intended to support the needs of complex graphics devices, usually containing programmable pipelines well suited to 3D graphics acceleration. Graphics drivers in the kernel may make use of DRM functions to make tasks like memory management, interrupt handling and DMA easier, and provide a uniform interface to applications.

A note on versions: this guide covers features found in the DRM tree, including the TTM memory manager, output configuration and mode setting, and the new vblank internals, in addition to all the regular features found in current kernels.

[Insert diagram of typical DRM stack here]

Style Guidelines

For consistency this documentation uses American English. Abbreviations are written as all-uppercase, for example: DRM, KMS, IOCTL, CRTC, and so on. To aid in reading, documentations make full use of the markup characters kerneldoc provides: @parameter for function parameters, @member for structure members, &structure to reference structures and function() for functions. These all get automatically hyperlinked if kerneldoc for the referenced objects exists. When referencing entries in function vtables please use ->vfunc(). Note that kerneldoc does not support referencing struct members directly, so please add a reference to the vtable struct somewhere in the same paragraph or at least section.

Except in special situations (to separate locked from unlocked variants) locking requirements for functions aren’t documented in the kerneldoc. Instead locking should be check at runtime using e.g. WARN_ON(!mutex_is_locked(...));. Since it’s much easier to ignore documentation than runtime noise this provides more value. And on top of that runtime checks do need to be updated when the locking rules change, increasing the chances that they’re correct. Within the documentation the locking rules should be explained in the relevant structures: Either in the comment for the lock explaining what it protects, or data fields need a note about which lock protects them, or both.

Functions which have a non-void return value should have a section called “Returns” explaining the expected return values in different cases and their meanings. Currently there’s no consensus whether that section name should be all upper-case or not, and whether it should end in a colon or not. Go with the file-local style. Other common section names are “Notes” with information for dangerous or tricky corner cases, and “FIXME” where the interface could be cleaned up.

DRM Internals

This chapter documents DRM internals relevant to driver authors and developers working to add support for the latest features to existing drivers.

First, we go over some typical driver initialization requirements, like setting up command buffers, creating an initial output configuration, and initializing core services. Subsequent sections cover core internals in more detail, providing implementation notes and examples.

The DRM layer provides several services to graphics drivers, many of them driven by the application interfaces it provides through libdrm, the library that wraps most of the DRM ioctls. These include vblank event handling, memory management, output management, framebuffer management, command submission & fencing, suspend/resume support, and DMA services.

Driver Initialization

At the core of every DRM driver is a struct drm_driver structure. Drivers typically statically initialize a drm_driver structure, and then pass it to drm_dev_alloc() to allocate a device instance. After the device instance is fully initialized it can be registered (which makes it accessible from userspace) using drm_dev_register().

The struct drm_driver structure contains static information that describes the driver and features it supports, and pointers to methods that the DRM core will call to implement the DRM API. We will first go through the struct drm_driver static information fields, and will then describe individual operations in details as they get used in later sections.

Driver Information

Driver Features

Drivers inform the DRM core about their requirements and supported features by setting appropriate flags in the driver_features field. Since those flags influence the DRM core behaviour since registration time, most of them must be set to registering the struct drm_driver instance.

u32 driver_features;

DRIVER_USE_AGP
Driver uses AGP interface, the DRM core will manage AGP resources.
DRIVER_REQUIRE_AGP
Driver needs AGP interface to function. AGP initialization failure will become a fatal error.
DRIVER_PCI_DMA
Driver is capable of PCI DMA, mapping of PCI DMA buffers to userspace will be enabled. Deprecated.
DRIVER_SG
Driver can perform scatter/gather DMA, allocation and mapping of scatter/gather buffers will be enabled. Deprecated.
DRIVER_HAVE_DMA
Driver supports DMA, the userspace DMA API will be supported. Deprecated.
DRIVER_HAVE_IRQ; DRIVER_IRQ_SHARED

DRIVER_HAVE_IRQ indicates whether the driver has an IRQ handler managed by the DRM Core. The core will support simple IRQ handler installation when the flag is set. The installation process is described in ?.

DRIVER_IRQ_SHARED indicates whether the device & handler support shared IRQs (note that this is required of PCI drivers).

DRIVER_GEM
Driver use the GEM memory manager.
DRIVER_MODESET
Driver supports mode setting interfaces (KMS).
DRIVER_PRIME
Driver implements DRM PRIME buffer sharing.
DRIVER_RENDER
Driver supports dedicated render nodes.
DRIVER_ATOMIC
Driver supports atomic properties. In this case the driver must implement appropriate obj->atomic_get_property() vfuncs for any modeset objects with driver specific properties.
Major, Minor and Patchlevel

int major; int minor; int patchlevel; The DRM core identifies driver versions by a major, minor and patch level triplet. The information is printed to the kernel log at initialization time and passed to userspace through the DRM_IOCTL_VERSION ioctl.

The major and minor numbers are also used to verify the requested driver API version passed to DRM_IOCTL_SET_VERSION. When the driver API changes between minor versions, applications can call DRM_IOCTL_SET_VERSION to select a specific version of the API. If the requested major isn’t equal to the driver major, or the requested minor is larger than the driver minor, the DRM_IOCTL_SET_VERSION call will return an error. Otherwise the driver’s set_version() method will be called with the requested version.

Name, Description and Date

char *name; char *desc; char *date; The driver name is printed to the kernel log at initialization time, used for IRQ registration and passed to userspace through DRM_IOCTL_VERSION.

The driver description is a purely informative string passed to userspace through the DRM_IOCTL_VERSION ioctl and otherwise unused by the kernel.

The driver date, formatted as YYYYMMDD, is meant to identify the date of the latest modification to the driver. However, as most drivers fail to update it, its value is mostly useless. The DRM core prints it to the kernel log at initialization time and passes it to userspace through the DRM_IOCTL_VERSION ioctl.

Device Instance and Driver Handling

A device instance for a drm driver is represented by struct drm_device. This is allocated with drm_dev_alloc(), usually from bus-specific ->:c:func:probe() callbacks implemented by the driver. The driver then needs to initialize all the various subsystems for the drm device like memory management, vblank handling, modesetting support and intial output configuration plus obviously initialize all the corresponding hardware bits. An important part of this is also calling drm_dev_set_unique() to set the userspace-visible unique name of this device instance. Finally when everything is up and running and ready for userspace the device instance can be published using drm_dev_register().

There is also deprecated support for initalizing device instances using bus-specific helpers and the ->:c:func:load() callback. But due to backwards-compatibility needs the device instance have to be published too early, which requires unpretty global locking to make safe and is therefore only support for existing drivers not yet converted to the new scheme.

When cleaning up a device instance everything needs to be done in reverse: First unpublish the device instance with drm_dev_unregister(). Then clean up any other resources allocated at device initialization and drop the driver’s reference to drm_device using drm_dev_unref().

Note that the lifetime rules for drm_device instance has still a lot of historical baggage. Hence use the reference counting provided by drm_dev_ref() and drm_dev_unref() only carefully.

Also note that embedding of drm_device is currently not (yet) supported (but it would be easy to add). Drivers can store driver-private data in the dev_priv field of drm_device.

void drm_put_dev(struct drm_device * dev)

Unregister and release a DRM device

Parameters

struct drm_device * dev
DRM device

Description

Called at module unload time or when a PCI device is unplugged.

Cleans up all DRM device, calling drm_lastclose().

Note

Use of this function is deprecated. It will eventually go away completely. Please use drm_dev_unregister() and drm_dev_unref() explicitly instead to make sure that the device isn’t userspace accessible any more while teardown is in progress, ensuring that userspace can’t access an inconsistent state.

struct drm_device * drm_dev_alloc(struct drm_driver * driver, struct device * parent)

Allocate new DRM device

Parameters

struct drm_driver * driver
DRM driver to allocate device for
struct device * parent
Parent device object

Description

Allocate and initialize a new DRM device. No device registration is done. Call drm_dev_register() to advertice the device to user space and register it with other core subsystems. This should be done last in the device initialization sequence to make sure userspace can’t access an inconsistent state.

The initial ref-count of the object is 1. Use drm_dev_ref() and drm_dev_unref() to take and drop further ref-counts.

Note that for purely virtual devices parent can be NULL.

Return

Pointer to new DRM device, or NULL if out of memory.

void drm_dev_ref(struct drm_device * dev)

Take reference of a DRM device

Parameters

struct drm_device * dev
device to take reference of or NULL

Description

This increases the ref-count of dev by one. You must already own a reference when calling this. Use drm_dev_unref() to drop this reference again.

This function never fails. However, this function does not provide any guarantee whether the device is alive or running. It only provides a reference to the object and the memory associated with it.

void drm_dev_unref(struct drm_device * dev)

Drop reference of a DRM device

Parameters

struct drm_device * dev
device to drop reference of or NULL

Description

This decreases the ref-count of dev by one. The device is destroyed if the ref-count drops to zero.

int drm_dev_register(struct drm_device * dev, unsigned long flags)

Register DRM device

Parameters

struct drm_device * dev
Device to register
unsigned long flags
Flags passed to the driver’s .:c:func:load() function

Description

Register the DRM device dev with the system, advertise device to user-space and start normal device operation. dev must be allocated via drm_dev_alloc() previously. Right after drm_dev_register() the driver should call drm_connector_register_all() to register all connectors in sysfs. This is a separate call for backward compatibility with drivers still using the deprecated ->:c:func:load() callback, where connectors are registered from within the ->:c:func:load() callback.

Never call this twice on any device!

NOTE

To ensure backward compatibility with existing drivers method this function calls the ->:c:func:load() method after registering the device nodes, creating race conditions. Usage of the ->:c:func:load() methods is therefore deprecated, drivers must perform all initialization before calling drm_dev_register().

Return

0 on success, negative error code on failure.

void drm_dev_unregister(struct drm_device * dev)

Unregister DRM device

Parameters

struct drm_device * dev
Device to unregister

Description

Unregister the DRM device from the system. This does the reverse of drm_dev_register() but does not deallocate the device. The caller must call drm_dev_unref() to drop their final reference.

This should be called first in the device teardown code to make sure userspace can’t access the device instance any more.

int drm_dev_set_unique(struct drm_device * dev, const char * name)

Set the unique name of a DRM device

Parameters

struct drm_device * dev
device of which to set the unique name
const char * name
unique name

Description

Sets the unique name of a DRM device using the specified string. Drivers can use this at driver probe time if the unique name of the devices they drive is static.

Return

0 on success or a negative error code on failure.

Driver Load

IRQ Registration

The DRM core tries to facilitate IRQ handler registration and unregistration by providing drm_irq_install() and drm_irq_uninstall() functions. Those functions only support a single interrupt per device, devices that use more than one IRQs need to be handled manually.

Managed IRQ Registration

drm_irq_install() starts by calling the irq_preinstall driver operation. The operation is optional and must make sure that the interrupt will not get fired by clearing all pending interrupt flags or disabling the interrupt.

The passed-in IRQ will then be requested by a call to request_irq(). If the DRIVER_IRQ_SHARED driver feature flag is set, a shared (IRQF_SHARED) IRQ handler will be requested.

The IRQ handler function must be provided as the mandatory irq_handler driver operation. It will get passed directly to request_irq() and thus has the same prototype as all IRQ handlers. It will get called with a pointer to the DRM device as the second argument.

Finally the function calls the optional irq_postinstall driver operation. The operation usually enables interrupts (excluding the vblank interrupt, which is enabled separately), but drivers may choose to enable/disable interrupts at a different time.

drm_irq_uninstall() is similarly used to uninstall an IRQ handler. It starts by waking up all processes waiting on a vblank interrupt to make sure they don’t hang, and then calls the optional irq_uninstall driver operation. The operation must disable all hardware interrupts. Finally the function frees the IRQ by calling free_irq().

Manual IRQ Registration

Drivers that require multiple interrupt handlers can’t use the managed IRQ registration functions. In that case IRQs must be registered and unregistered manually (usually with the request_irq() and free_irq() functions, or their devm_* equivalent).

When manually registering IRQs, drivers must not set the DRIVER_HAVE_IRQ driver feature flag, and must not provide the irq_handler driver operation. They must set the struct drm_device irq_enabled field to 1 upon registration of the IRQs, and clear it to 0 after unregistering the IRQs.

Memory Manager Initialization

Every DRM driver requires a memory manager which must be initialized at load time. DRM currently contains two memory managers, the Translation Table Manager (TTM) and the Graphics Execution Manager (GEM). This document describes the use of the GEM memory manager only. See ? for details.

Miscellaneous Device Configuration

Another task that may be necessary for PCI devices during configuration is mapping the video BIOS. On many devices, the VBIOS describes device configuration, LCD panel timings (if any), and contains flags indicating device state. Mapping the BIOS can be done using the pci_map_rom() call, a convenience function that takes care of mapping the actual ROM, whether it has been shadowed into memory (typically at address 0xc0000) or exists on the PCI device in the ROM BAR. Note that after the ROM has been mapped and any necessary information has been extracted, it should be unmapped; on many devices, the ROM address decoder is shared with other BARs, so leaving it mapped could cause undesired behaviour like hangs or memory corruption.

Bus-specific Device Registration and PCI Support

A number of functions are provided to help with device registration. The functions deal with PCI and platform devices respectively and are only provided for historical reasons. These are all deprecated and shouldn’t be used in new drivers. Besides that there’s a few helpers for pci drivers.

drm_dma_handle_t * drm_pci_alloc(struct drm_device * dev, size_t size, size_t align)

Allocate a PCI consistent memory block, for DMA.

Parameters

struct drm_device * dev
DRM device
size_t size
size of block to allocate
size_t align
alignment of block

Return

A handle to the allocated memory block on success or NULL on failure.

void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)

Free a PCI consistent memory block

Parameters

struct drm_device * dev
DRM device
drm_dma_handle_t * dmah
handle to memory block
int drm_get_pci_dev(struct pci_dev * pdev, const struct pci_device_id * ent, struct drm_driver * driver)

Register a PCI device with the DRM subsystem

Parameters

struct pci_dev * pdev
PCI device
const struct pci_device_id * ent
entry from the PCI ID table that matches pdev
struct drm_driver * driver
DRM device driver

Description

Attempt to gets inter module “drm” information. If we are first then register the character device and inter module information. Try and register, if we fail to register, backout previous work.

NOTE

This function is deprecated, please use drm_dev_alloc() and drm_dev_register() instead and remove your ->:c:func:load() callback.

Return

0 on success or a negative error code on failure.

int drm_pci_init(struct drm_driver * driver, struct pci_driver * pdriver)

Register matching PCI devices with the DRM subsystem

Parameters

struct drm_driver * driver
DRM device driver
struct pci_driver * pdriver
PCI device driver

Description

Initializes a drm_device structures, registering the stubs and initializing the AGP device.

NOTE

This function is deprecated. Modern modesetting drm drivers should use pci_register_driver() directly, this function only provides shadow-binding support for old legacy drivers on top of that core pci function.

Return

0 on success or a negative error code on failure.

void drm_pci_exit(struct drm_driver * driver, struct pci_driver * pdriver)

Unregister matching PCI devices from the DRM subsystem

Parameters

struct drm_driver * driver
DRM device driver
struct pci_driver * pdriver
PCI device driver

Description

Unregisters one or more devices matched by a PCI driver from the DRM subsystem.

NOTE

This function is deprecated. Modern modesetting drm drivers should use pci_unregister_driver() directly, this function only provides shadow-binding support for old legacy drivers on top of that core pci function.

int drm_platform_init(struct drm_driver * driver, struct platform_device * platform_device)

Register a platform device with the DRM subsystem

Parameters

struct drm_driver * driver
DRM device driver
struct platform_device * platform_device
platform device to register

Description

Registers the specified DRM device driver and platform device with the DRM subsystem, initializing a drm_device structure and calling the driver’s .:c:func:load() function.

NOTE

This function is deprecated, please use drm_dev_alloc() and drm_dev_register() instead and remove your ->:c:func:load() callback.

Return

0 on success or a negative error code on failure.

Memory management

Modern Linux systems require large amount of graphics memory to store frame buffers, textures, vertices and other graphics-related data. Given the very dynamic nature of many of that data, managing graphics memory efficiently is thus crucial for the graphics stack and plays a central role in the DRM infrastructure.

The DRM core includes two memory managers, namely Translation Table Maps (TTM) and Graphics Execution Manager (GEM). TTM was the first DRM memory manager to be developed and tried to be a one-size-fits-them all solution. It provides a single userspace API to accommodate the need of all hardware, supporting both Unified Memory Architecture (UMA) devices and devices with dedicated video RAM (i.e. most discrete video cards). This resulted in a large, complex piece of code that turned out to be hard to use for driver development.

GEM started as an Intel-sponsored project in reaction to TTM’s complexity. Its design philosophy is completely different: instead of providing a solution to every graphics memory-related problems, GEM identified common code between drivers and created a support library to share it. GEM has simpler initialization and execution requirements than TTM, but has no video RAM management capabilities and is thus limited to UMA devices.

The Translation Table Manager (TTM)

TTM design background and information belongs here.

TTM initialization

Warning

This section is outdated.

Drivers wishing to support TTM must fill out a drm_bo_driver structure. The structure contains several fields with function pointers for initializing the TTM, allocating and freeing memory, waiting for command completion and fence synchronization, and memory migration. See the radeon_ttm.c file for an example of usage.

The ttm_global_reference structure is made up of several fields:

struct ttm_global_reference {
        enum ttm_global_types global_type;
        size_t size;
        void *object;
        int (*init) (struct ttm_global_reference *);
        void (*release) (struct ttm_global_reference *);
};

There should be one global reference structure for your memory manager as a whole, and there will be others for each object created by the memory manager at runtime. Your global TTM should have a type of TTM_GLOBAL_TTM_MEM. The size field for the global object should be sizeof(struct ttm_mem_global), and the init and release hooks should point at your driver-specific init and release routines, which probably eventually call ttm_mem_global_init and ttm_mem_global_release, respectively.

Once your global TTM accounting structure is set up and initialized by calling ttm_global_item_ref() on it, you need to create a buffer object TTM to provide a pool for buffer object allocation by clients and the kernel itself. The type of this object should be TTM_GLOBAL_TTM_BO, and its size should be sizeof(struct ttm_bo_global). Again, driver-specific init and release functions may be provided, likely eventually calling ttm_bo_global_init() and ttm_bo_global_release(), respectively. Also, like the previous object, ttm_global_item_ref() is used to create an initial reference count for the TTM, which will call your initialization function.

The Graphics Execution Manager (GEM)

The GEM design approach has resulted in a memory manager that doesn’t provide full coverage of all (or even all common) use cases in its userspace or kernel API. GEM exposes a set of standard memory-related operations to userspace and a set of helper functions to drivers, and let drivers implement hardware-specific operations with their own private API.

The GEM userspace API is described in the GEM - the Graphics Execution Manager article on LWN. While slightly outdated, the document provides a good overview of the GEM API principles. Buffer allocation and read and write operations, described as part of the common GEM API, are currently implemented using driver-specific ioctls.

GEM is data-agnostic. It manages abstract buffer objects without knowing what individual buffers contain. APIs that require knowledge of buffer contents or purpose, such as buffer allocation or synchronization primitives, are thus outside of the scope of GEM and must be implemented using driver-specific ioctls.

On a fundamental level, GEM involves several operations:

  • Memory allocation and freeing
  • Command execution
  • Aperture management at command execution time

Buffer object allocation is relatively straightforward and largely provided by Linux’s shmem layer, which provides memory to back each object.

Device-specific operations, such as command execution, pinning, buffer read & write, mapping, and domain ownership transfers are left to driver-specific ioctls.

GEM Initialization

Drivers that use GEM must set the DRIVER_GEM bit in the struct struct drm_driver driver_features field. The DRM core will then automatically initialize the GEM core before calling the load operation. Behind the scene, this will create a DRM Memory Manager object which provides an address space pool for object allocation.

In a KMS configuration, drivers need to allocate and initialize a command ring buffer following core GEM initialization if required by the hardware. UMA devices usually have what is called a “stolen” memory region, which provides space for the initial framebuffer and large, contiguous memory regions required by the device. This space is typically not managed by GEM, and must be initialized separately into its own DRM MM object.

GEM Objects Creation

GEM splits creation of GEM objects and allocation of the memory that backs them in two distinct operations.

GEM objects are represented by an instance of struct struct drm_gem_object. Drivers usually need to extend GEM objects with private information and thus create a driver-specific GEM object structure type that embeds an instance of struct struct drm_gem_object.

To create a GEM object, a driver allocates memory for an instance of its specific GEM object type and initializes the embedded struct struct drm_gem_object with a call to drm_gem_object_init(). The function takes a pointer to the DRM device, a pointer to the GEM object and the buffer object size in bytes.

GEM uses shmem to allocate anonymous pageable memory. drm_gem_object_init() will create an shmfs file of the requested size and store it into the struct struct drm_gem_object filp field. The memory is used as either main storage for the object when the graphics hardware uses system memory directly or as a backing store otherwise.

Drivers are responsible for the actual physical pages allocation by calling shmem_read_mapping_page_gfp() for each page. Note that they can decide to allocate pages when initializing the GEM object, or to delay allocation until the memory is needed (for instance when a page fault occurs as a result of a userspace memory access or when the driver needs to start a DMA transfer involving the memory).

Anonymous pageable memory allocation is not always desired, for instance when the hardware requires physically contiguous system memory as is often the case in embedded devices. Drivers can create GEM objects with no shmfs backing (called private GEM objects) by initializing them with a call to drm_gem_private_object_init() instead of drm_gem_object_init(). Storage for private GEM objects must be managed by drivers.

GEM Objects Lifetime

All GEM objects are reference-counted by the GEM core. References can be acquired and release by calling drm_gem_object_reference() and drm_gem_object_unreference() respectively. The caller must hold the struct drm_device struct_mutex lock when calling drm_gem_object_reference(). As a convenience, GEM provides drm_gem_object_unreference_unlocked() functions that can be called without holding the lock.

When the last reference to a GEM object is released the GEM core calls the struct drm_driver gem_free_object operation. That operation is mandatory for GEM-enabled drivers and must free the GEM object and all associated resources.

void (*gem_free_object) (struct drm_gem_object *obj); Drivers are responsible for freeing all GEM object resources. This includes the resources created by the GEM core, which need to be released with drm_gem_object_release().

GEM Objects Naming

Communication between userspace and the kernel refers to GEM objects using local handles, global names or, more recently, file descriptors. All of those are 32-bit integer values; the usual Linux kernel limits apply to the file descriptors.

GEM handles are local to a DRM file. Applications get a handle to a GEM object through a driver-specific ioctl, and can use that handle to refer to the GEM object in other standard or driver-specific ioctls. Closing a DRM file handle frees all its GEM handles and dereferences the associated GEM objects.

To create a handle for a GEM object drivers call drm_gem_handle_create(). The function takes a pointer to the DRM file and the GEM object and returns a locally unique handle. When the handle is no longer needed drivers delete it with a call to drm_gem_handle_delete(). Finally the GEM object associated with a handle can be retrieved by a call to drm_gem_object_lookup().

Handles don’t take ownership of GEM objects, they only take a reference to the object that will be dropped when the handle is destroyed. To avoid leaking GEM objects, drivers must make sure they drop the reference(s) they own (such as the initial reference taken at object creation time) as appropriate, without any special consideration for the handle. For example, in the particular case of combined GEM object and handle creation in the implementation of the dumb_create operation, drivers must drop the initial reference to the GEM object before returning the handle.

GEM names are similar in purpose to handles but are not local to DRM files. They can be passed between processes to reference a GEM object globally. Names can’t be used directly to refer to objects in the DRM API, applications must convert handles to names and names to handles using the DRM_IOCTL_GEM_FLINK and DRM_IOCTL_GEM_OPEN ioctls respectively. The conversion is handled by the DRM core without any driver-specific support.

GEM also supports buffer sharing with dma-buf file descriptors through PRIME. GEM-based drivers must use the provided helpers functions to implement the exporting and importing correctly. See ?. Since sharing file descriptors is inherently more secure than the easily guessable and global GEM names it is the preferred buffer sharing mechanism. Sharing buffers through GEM names is only supported for legacy userspace. Furthermore PRIME also allows cross-device buffer sharing since it is based on dma-bufs.

GEM Objects Mapping

Because mapping operations are fairly heavyweight GEM favours read/write-like access to buffers, implemented through driver-specific ioctls, over mapping buffers to userspace. However, when random access to the buffer is needed (to perform software rendering for instance), direct access to the object can be more efficient.

The mmap system call can’t be used directly to map GEM objects, as they don’t have their own file handle. Two alternative methods currently co-exist to map GEM objects to userspace. The first method uses a driver-specific ioctl to perform the mapping operation, calling do_mmap() under the hood. This is often considered dubious, seems to be discouraged for new GEM-enabled drivers, and will thus not be described here.

The second method uses the mmap system call on the DRM file handle. void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); DRM identifies the GEM object to be mapped by a fake offset passed through the mmap offset argument. Prior to being mapped, a GEM object must thus be associated with a fake offset. To do so, drivers must call drm_gem_create_mmap_offset() on the object.

Once allocated, the fake offset value must be passed to the application in a driver-specific way and can then be used as the mmap offset argument.

The GEM core provides a helper method drm_gem_mmap() to handle object mapping. The method can be set directly as the mmap file operation handler. It will look up the GEM object based on the offset value and set the VMA operations to the struct drm_driver gem_vm_ops field. Note that drm_gem_mmap() doesn’t map memory to userspace, but relies on the driver-provided fault handler to map pages individually.

To use drm_gem_mmap(), drivers must fill the struct struct drm_driver gem_vm_ops field with a pointer to VM operations.

struct vm_operations_struct *gem_vm_ops struct vm_operations_struct { void (*open)(struct vm_area_struct * area); void (*close)(struct vm_area_struct * area); int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf); };

The open and close operations must update the GEM object reference count. Drivers can use the drm_gem_vm_open() and drm_gem_vm_close() helper functions directly as open and close handlers.

The fault operation handler is responsible for mapping individual pages to userspace when a page fault occurs. Depending on the memory allocation scheme, drivers can allocate pages at fault time, or can decide to allocate memory for the GEM object at the time the object is created.

Drivers that want to map the GEM object upfront instead of handling page faults can implement their own mmap file operation handler.

Memory Coherency

When mapped to the device or used in a command buffer, backing pages for an object are flushed to memory and marked write combined so as to be coherent with the GPU. Likewise, if the CPU accesses an object after the GPU has finished rendering to the object, then the object must be made coherent with the CPU’s view of memory, usually involving GPU cache flushing of various kinds. This core CPU<->GPU coherency management is provided by a device-specific ioctl, which evaluates an object’s current domain and performs any necessary flushing or synchronization to put the object into the desired coherency domain (note that the object may be busy, i.e. an active render target; in that case, setting the domain blocks the client and waits for rendering to complete before performing any necessary flushing operations).

Command Execution

Perhaps the most important GEM function for GPU devices is providing a command execution interface to clients. Client programs construct command buffers containing references to previously allocated memory objects, and then submit them to GEM. At that point, GEM takes care to bind all the objects into the GTT, execute the buffer, and provide necessary synchronization between clients accessing the same buffers. This often involves evicting some objects from the GTT and re-binding others (a fairly expensive operation), and providing relocation support which hides fixed GTT offsets from clients. Clients must take care not to submit command buffers that reference more objects than can fit in the GTT; otherwise, GEM will reject them and no rendering will occur. Similarly, if several objects in the buffer require fence registers to be allocated for correct rendering (e.g. 2D blits on pre-965 chips), care must be taken not to require more fence registers than are available to the client. Such resource management should be abstracted from the client in libdrm.

GEM Function Reference

int drm_gem_object_init(struct drm_device * dev, struct drm_gem_object * obj, size_t size)

initialize an allocated shmem-backed GEM object

Parameters

struct drm_device * dev
drm_device the object should be initialized for
struct drm_gem_object * obj
drm_gem_object to initialize
size_t size
object size

Description

Initialize an already allocated GEM object of the specified size with shmfs backing store.

void drm_gem_private_object_init(struct drm_device * dev, struct drm_gem_object * obj, size_t size)

initialize an allocated private GEM object

Parameters

struct drm_device * dev
drm_device the object should be initialized for
struct drm_gem_object * obj
drm_gem_object to initialize
size_t size
object size

Description

Initialize an already allocated GEM object of the specified size with no GEM provided backing store. Instead the caller is responsible for backing the object and handling it.

int drm_gem_handle_delete(struct drm_file * filp, u32 handle)

deletes the given file-private handle

Parameters

struct drm_file * filp
drm file-private structure to use for the handle look up
u32 handle
userspace handle to delete

Description

Removes the GEM handle from the filp lookup table which has been added with drm_gem_handle_create(). If this is the last handle also cleans up linked resources like GEM names.

int drm_gem_dumb_destroy(struct drm_file * file, struct drm_device * dev, uint32_t handle)

dumb fb callback helper for gem based drivers

Parameters

struct drm_file * file
drm file-private structure to remove the dumb handle from
struct drm_device * dev
corresponding drm_device
uint32_t handle
the dumb handle to remove

Description

This implements the ->dumb_destroy kms driver callback for drivers which use gem to manage their backing storage.

int drm_gem_handle_create(struct drm_file * file_priv, struct drm_gem_object * obj, u32 * handlep)

create a gem handle for an object

Parameters

struct drm_file * file_priv
drm file-private structure to register the handle for
struct drm_gem_object * obj
object to register
u32 * handlep
pionter to return the created handle to the caller

Description

Create a handle for this object. This adds a handle reference to the object, which includes a regular reference count. Callers will likely want to dereference the object afterwards.

void drm_gem_free_mmap_offset(struct drm_gem_object * obj)

release a fake mmap offset for an object

Parameters

struct drm_gem_object * obj
obj in question

Description

This routine frees fake offsets allocated by drm_gem_create_mmap_offset().

Note that drm_gem_object_release() already calls this function, so drivers don’t have to take care of releasing the mmap offset themselves when freeing the GEM object.

int drm_gem_create_mmap_offset_size(struct drm_gem_object * obj, size_t size)

create a fake mmap offset for an object

Parameters

struct drm_gem_object * obj
obj in question
size_t size
the virtual size

Description

GEM memory mapping works by handing back to userspace a fake mmap offset it can use in a subsequent mmap(2) call. The DRM core code then looks up the object based on the offset and sets up the various memory mapping structures.

This routine allocates and attaches a fake offset for obj, in cases where the virtual size differs from the physical size (ie. obj->size). Otherwise just use drm_gem_create_mmap_offset().

This function is idempotent and handles an already allocated mmap offset transparently. Drivers do not need to check for this case.

int drm_gem_create_mmap_offset(struct drm_gem_object * obj)

create a fake mmap offset for an object

Parameters

struct drm_gem_object * obj
obj in question

Description

GEM memory mapping works by handing back to userspace a fake mmap offset it can use in a subsequent mmap(2) call. The DRM core code then looks up the object based on the offset and sets up the various memory mapping structures.

This routine allocates and attaches a fake offset for obj.

Drivers can call drm_gem_free_mmap_offset() before freeing obj to release the fake offset again.

struct page ** drm_gem_get_pages(struct drm_gem_object * obj)

helper to allocate backing pages for a GEM object from shmem

Parameters

struct drm_gem_object * obj
obj in question

Description

This reads the page-array of the shmem-backing storage of the given gem object. An array of pages is returned. If a page is not allocated or swapped-out, this will allocate/swap-in the required pages. Note that the whole object is covered by the page-array and pinned in memory.

Use drm_gem_put_pages() to release the array and unpin all pages.

This uses the GFP-mask set on the shmem-mapping (see mapping_set_gfp_mask()). If you require other GFP-masks, you have to do those allocations yourself.

Note that you are not allowed to change gfp-zones during runtime. That is, shmem_read_mapping_page_gfp() must be called with the same gfp_zone(gfp) as set during initialization. If you have special zone constraints, set them after drm_gem_init_object() via mapping_set_gfp_mask(). shmem-core takes care to keep pages in the required zone during swap-in.

void drm_gem_put_pages(struct drm_gem_object * obj, struct page ** pages, bool dirty, bool accessed)

helper to free backing pages for a GEM object

Parameters

struct drm_gem_object * obj
obj in question
struct page ** pages
pages to free
bool dirty
if true, pages will be marked as dirty
bool accessed
if true, the pages will be marked as accessed
struct drm_gem_object * drm_gem_object_lookup(struct drm_file * filp, u32 handle)

look up a GEM object from it’s handle

Parameters

struct drm_file * filp
DRM file private date
u32 handle
userspace handle

Return

A reference to the object named by the handle if such exists on filp, NULL otherwise.

void drm_gem_object_release(struct drm_gem_object * obj)

release GEM buffer object resources

Parameters

struct drm_gem_object * obj
GEM buffer object

Description

This releases any structures and resources used by obj and is the invers of drm_gem_object_init().

void drm_gem_object_free(struct kref * kref)

free a GEM object

Parameters

struct kref * kref
kref of the object to free

Description

Called after the last reference to the object has been lost. Must be called holding struct_ mutex

Frees the object

void drm_gem_object_unreference_unlocked(struct drm_gem_object * obj)

release a GEM BO reference

Parameters

struct drm_gem_object * obj
GEM buffer object

Description

This releases a reference to obj. Callers must not hold the dev->struct_mutex lock when calling this function.

See also __drm_gem_object_unreference().

void drm_gem_object_unreference(struct drm_gem_object * obj)

release a GEM BO reference

Parameters

struct drm_gem_object * obj
GEM buffer object

Description

This releases a reference to obj. Callers must hold the dev->struct_mutex lock when calling this function, even when the driver doesn’t use dev->struct_mutex for anything.

For drivers not encumbered with legacy locking use drm_gem_object_unreference_unlocked() instead.

void drm_gem_vm_open(struct vm_area_struct * vma)

vma->ops->open implementation for GEM

Parameters

struct vm_area_struct * vma
VM area structure

Description

This function implements the #vm_operations_struct open() callback for GEM drivers. This must be used together with drm_gem_vm_close().

void drm_gem_vm_close(struct vm_area_struct * vma)

vma->ops->close implementation for GEM

Parameters

struct vm_area_struct * vma
VM area structure

Description

This function implements the #vm_operations_struct close() callback for GEM drivers. This must be used together with drm_gem_vm_open().

int drm_gem_mmap_obj(struct drm_gem_object * obj, unsigned long obj_size, struct vm_area_struct * vma)

memory map a GEM object

Parameters

struct drm_gem_object * obj
the GEM object to map
unsigned long obj_size
the object size to be mapped, in bytes
struct vm_area_struct * vma
VMA for the area to be mapped

Description

Set up the VMA to prepare mapping of the GEM object using the gem_vm_ops provided by the driver. Depending on their requirements, drivers can either provide a fault handler in their gem_vm_ops (in which case any accesses to the object will be trapped, to perform migration, GTT binding, surface register allocation, or performance monitoring), or mmap the buffer memory synchronously after calling drm_gem_mmap_obj.

This function is mainly intended to implement the DMABUF mmap operation, when the GEM object is not looked up based on its fake offset. To implement the DRM mmap operation, drivers should use the drm_gem_mmap() function.

drm_gem_mmap_obj() assumes the user is granted access to the buffer while drm_gem_mmap() prevents unprivileged users from mapping random objects. So callers must verify access restrictions before calling this helper.

Return 0 or success or -EINVAL if the object size is smaller than the VMA size, or if no gem_vm_ops are provided.

int drm_gem_mmap(struct file * filp, struct vm_area_struct * vma)

memory map routine for GEM objects

Parameters

struct file * filp
DRM file pointer
struct vm_area_struct * vma
VMA for the area to be mapped

Description

If a driver supports GEM object mapping, mmap calls on the DRM file descriptor will end up here.

Look up the GEM object based on the offset passed in (vma->vm_pgoff will contain the fake offset we created when the GTT map ioctl was called on the object) and map it with a call to drm_gem_mmap_obj().

If the caller is not granted access to the buffer object, the mmap will fail with EACCES. Please see the vma manager for more information.

struct drm_gem_object

GEM buffer object

Definition

struct drm_gem_object {
  struct kref refcount;
  unsigned handle_count;
  struct drm_device * dev;
  struct file * filp;
  struct drm_vma_offset_node vma_node;
  size_t size;
  int name;
  uint32_t read_domains;
  uint32_t write_domain;
  uint32_t pending_read_domains;
  uint32_t pending_write_domain;
  struct dma_buf * dma_buf;
  struct dma_buf_attachment * import_attach;
};

Members

struct kref refcount

Reference count of this object

Please use drm_gem_object_reference() to acquire and drm_gem_object_unreference() or drm_gem_object_unreference_unlocked() to release a reference to a GEM buffer object.

unsigned handle_count

This is the GEM file_priv handle count of this object.

Each handle also holds a reference. Note that when the handle_count drops to 0 any global names (e.g. the id in the flink namespace) will be cleared.

Protected by dev->object_name_lock.

struct drm_device * dev
DRM dev this object belongs to.
struct file * filp
SHMEM file node used as backing storage for swappable buffer objects. GEM also supports driver private objects with driver-specific backing storage (contiguous CMA memory, special reserved blocks). In this case filp is NULL.
struct drm_vma_offset_node vma_node

Mapping info for this object to support mmap. Drivers are supposed to allocate the mmap offset using drm_gem_create_mmap_offset(). The offset itself can be retrieved using drm_vma_node_offset_addr().

Memory mapping itself is handled by drm_gem_mmap(), which also checks that userspace is allowed to access the object.

size_t size
Size of the object, in bytes. Immutable over the object’s lifetime.
int name
Global name for this object, starts at 1. 0 means unnamed. Access is covered by dev->object_name_lock. This is used by the GEM_FLINK and GEM_OPEN ioctls.
uint32_t read_domains
Read memory domains. These monitor which caches contain read/write data related to the object. When transitioning from one set of domains to another, the driver is called to ensure that caches are suitably flushed and invalidated.
uint32_t write_domain
Corresponding unique write memory domain.
uint32_t pending_read_domains
While validating an exec operation, the new read/write domain values are computed here. They will be transferred to the above values at the point that any cache flushing occurs
uint32_t pending_write_domain
Write domain similar to pending_read_domains.
struct dma_buf * dma_buf

dma-buf associated with this GEM object.

Pointer to the dma-buf associated with this gem object (either through importing or exporting). We break the resulting reference loop when the last gem handle for this object is released.

Protected by obj->object_name_lock.

struct dma_buf_attachment * import_attach

dma-buf attachment backing this object.

Any foreign dma_buf imported as a gem object has this set to the attachment point for the device. This is invariant over the lifetime of a gem object.

The driver’s ->gem_free_object callback is responsible for cleaning up the dma_buf attachment and references acquired at import time.

Note that the drm gem/prime core does not depend upon drivers setting this field any more. So for drivers where this doesn’t make sense (e.g. virtual devices or a displaylink behind an usb bus) they can simply leave it as NULL.

Description

This structure defines the generic parts for GEM buffer objects, which are mostly around handling mmap and userspace handles.

Buffer objects are often abbreviated to BO.

void drm_gem_object_reference(struct drm_gem_object * obj)

acquire a GEM BO reference

Parameters

struct drm_gem_object * obj
GEM buffer object

Description

This acquires additional reference to obj. It is illegal to call this without already holding a reference. No locks required.

void __drm_gem_object_unreference(struct drm_gem_object * obj)

raw function to release a GEM BO reference

Parameters

struct drm_gem_object * obj
GEM buffer object

Description

This function is meant to be used by drivers which are not encumbered with dev->struct_mutex legacy locking and which are using the gem_free_object_unlocked callback. It avoids all the locking checks and locking overhead of drm_gem_object_unreference() and drm_gem_object_unreference_unlocked().

Drivers should never call this directly in their code. Instead they should wrap it up into a driver_gem_object_unreference(struct driver_gem_object *obj) wrapper function, and use that. Shared code should never call this, to avoid breaking drivers by accident which still depend upon dev->struct_mutex locking.

VMA Offset Manager

The vma-manager is responsible to map arbitrary driver-dependent memory regions into the linear user address-space. It provides offsets to the caller which can then be used on the address_space of the drm-device. It takes care to not overlap regions, size them appropriately and to not confuse mm-core by inconsistent fake vm_pgoff fields. Drivers shouldn’t use this for object placement in VMEM. This manager should only be used to manage mappings into linear user-space VMs.

We use drm_mm as backend to manage object allocations. But it is highly optimized for alloc/free calls, not lookups. Hence, we use an rb-tree to speed up offset lookups.

You must not use multiple offset managers on a single address_space. Otherwise, mm-core will be unable to tear down memory mappings as the VM will no longer be linear.

This offset manager works on page-based addresses. That is, every argument and return code (with the exception of drm_vma_node_offset_addr()) is given in number of pages, not number of bytes. That means, object sizes and offsets must always be page-aligned (as usual). If you want to get a valid byte-based user-space address for a given offset, please see drm_vma_node_offset_addr().

Additionally to offset management, the vma offset manager also handles access management. For every open-file context that is allowed to access a given node, you must call drm_vma_node_allow(). Otherwise, an mmap() call on this open-file with the offset of the node will fail with -EACCES. To revoke access again, use drm_vma_node_revoke(). However, the caller is responsible for destroying already existing mappings, if required.

void drm_vma_offset_manager_init(struct drm_vma_offset_manager * mgr, unsigned long page_offset, unsigned long size)

Initialize new offset-manager

Parameters

struct drm_vma_offset_manager * mgr
Manager object
unsigned long page_offset
Offset of available memory area (page-based)
unsigned long size
Size of available address space range (page-based)

Description

Initialize a new offset-manager. The offset and area size available for the manager are given as page_offset and size. Both are interpreted as page-numbers, not bytes.

Adding/removing nodes from the manager is locked internally and protected against concurrent access. However, node allocation and destruction is left for the caller. While calling into the vma-manager, a given node must always be guaranteed to be referenced.

void drm_vma_offset_manager_destroy(struct drm_vma_offset_manager * mgr)

Destroy offset manager

Parameters

struct drm_vma_offset_manager * mgr
Manager object

Description

Destroy an object manager which was previously created via drm_vma_offset_manager_init(). The caller must remove all allocated nodes before destroying the manager. Otherwise, drm_mm will refuse to free the requested resources.

The manager must not be accessed after this function is called.

struct drm_vma_offset_node * drm_vma_offset_lookup_locked(struct drm_vma_offset_manager * mgr, unsigned long start, unsigned long pages)

Find node in offset space

Parameters

struct drm_vma_offset_manager * mgr
Manager object
unsigned long start
Start address for object (page-based)
unsigned long pages
Size of object (page-based)

Description

Find a node given a start address and object size. This returns the _best_ match for the given node. That is, start may point somewhere into a valid region and the given node will be returned, as long as the node spans the whole requested area (given the size in number of pages as pages).

Note that before lookup the vma offset manager lookup lock must be acquired with drm_vma_offset_lock_lookup(). See there for an example. This can then be used to implement weakly referenced lookups using kref_get_unless_zero().

Example

drm_vma_offset_lock_lookup(mgr); node = drm_vma_offset_lookup_locked(mgr); if (node)

kref_get_unless_zero(container_of(node, sth, entr));

drm_vma_offset_unlock_lookup(mgr);

Return

Returns NULL if no suitable node can be found. Otherwise, the best match is returned. It’s the caller’s responsibility to make sure the node doesn’t get destroyed before the caller can access it.

int drm_vma_offset_add(struct drm_vma_offset_manager * mgr, struct drm_vma_offset_node * node, unsigned long pages)

Add offset node to manager

Parameters

struct drm_vma_offset_manager * mgr
Manager object
struct drm_vma_offset_node * node
Node to be added
unsigned long pages
Allocation size visible to user-space (in number of pages)

Description

Add a node to the offset-manager. If the node was already added, this does nothing and return 0. pages is the size of the object given in number of pages. After this call succeeds, you can access the offset of the node until it is removed again.

If this call fails, it is safe to retry the operation or call drm_vma_offset_remove(), anyway. However, no cleanup is required in that case.

pages is not required to be the same size as the underlying memory object that you want to map. It only limits the size that user-space can map into their address space.

Return

0 on success, negative error code on failure.

void drm_vma_offset_remove(struct drm_vma_offset_manager * mgr, struct drm_vma_offset_node * node)

Remove offset node from manager

Parameters

struct drm_vma_offset_manager * mgr
Manager object
struct drm_vma_offset_node * node
Node to be removed

Description

Remove a node from the offset manager. If the node wasn’t added before, this does nothing. After this call returns, the offset and size will be 0 until a new offset is allocated via drm_vma_offset_add() again. Helper functions like drm_vma_node_start() and drm_vma_node_offset_addr() will return 0 if no offset is allocated.

int drm_vma_node_allow(struct drm_vma_offset_node * node, struct file * filp)

Add open-file to list of allowed users

Parameters

struct drm_vma_offset_node * node
Node to modify
struct file * filp
Open file to add

Description

Add filp to the list of allowed open-files for this node. If filp is already on this list, the ref-count is incremented.

The list of allowed-users is preserved across drm_vma_offset_add() and drm_vma_offset_remove() calls. You may even call it if the node is currently not added to any offset-manager.

You must remove all open-files the same number of times as you added them before destroying the node. Otherwise, you will leak memory.

This is locked against concurrent access internally.

Return

0 on success, negative error code on internal failure (out-of-mem)

void drm_vma_node_revoke(struct drm_vma_offset_node * node, struct file * filp)

Remove open-file from list of allowed users

Parameters

struct drm_vma_offset_node * node
Node to modify
struct file * filp
Open file to remove

Description

Decrement the ref-count of filp in the list of allowed open-files on node. If the ref-count drops to zero, remove filp from the list. You must call this once for every drm_vma_node_allow() on filp.

This is locked against concurrent access internally.

If filp is not on the list, nothing is done.

bool drm_vma_node_is_allowed(struct drm_vma_offset_node * node, struct file * filp)

Check whether an open-file is granted access

Parameters

struct drm_vma_offset_node * node
Node to check
struct file * filp
Open-file to check for

Description

Search the list in node whether filp is currently on the list of allowed open-files (see drm_vma_node_allow()).

This is locked against concurrent access internally.

Return

true iff filp is on the list

struct drm_vma_offset_node * drm_vma_offset_exact_lookup_locked(struct drm_vma_offset_manager * mgr, unsigned long start, unsigned long pages)

Look up node by exact address

Parameters

struct drm_vma_offset_manager * mgr
Manager object
unsigned long start
Start address (page-based, not byte-based)
unsigned long pages
Size of object (page-based)

Description

Same as drm_vma_offset_lookup_locked() but does not allow any offset into the node. It only returns the exact object with the given start address.

Return

Node at exact start address start.

void drm_vma_offset_lock_lookup(struct drm_vma_offset_manager * mgr)

Lock lookup for extended private use

Parameters

struct drm_vma_offset_manager * mgr
Manager object

Description

Lock VMA manager for extended lookups. Only locked VMA function calls are allowed while holding this lock. All other contexts are blocked from VMA until the lock is released via drm_vma_offset_unlock_lookup().

Use this if you need to take a reference to the objects returned by drm_vma_offset_lookup_locked() before releasing this lock again.

This lock must not be used for anything else than extended lookups. You must not call any other VMA helpers while holding this lock.

Note

You’re in atomic-context while holding this lock!

void drm_vma_offset_unlock_lookup(struct drm_vma_offset_manager * mgr)

Unlock lookup for extended private use

Parameters

struct drm_vma_offset_manager * mgr
Manager object

Description

Release lookup-lock. See drm_vma_offset_lock_lookup() for more information.

void drm_vma_node_reset(struct drm_vma_offset_node * node)

Initialize or reset node object

Parameters

struct drm_vma_offset_node * node
Node to initialize or reset

Description

Reset a node to its initial state. This must be called before using it with any VMA offset manager.

This must not be called on an already allocated node, or you will leak memory.

unsigned long drm_vma_node_start(struct drm_vma_offset_node * node)

Return start address for page-based addressing

Parameters

struct drm_vma_offset_node * node
Node to inspect

Description

Return the start address of the given node. This can be used as offset into the linear VM space that is provided by the VMA offset manager. Note that this can only be used for page-based addressing. If you need a proper offset for user-space mappings, you must apply “<< PAGE_SHIFT” or use the drm_vma_node_offset_addr() helper instead.

Return

Start address of node for page-based addressing. 0 if the node does not have an offset allocated.

unsigned long drm_vma_node_size(struct drm_vma_offset_node * node)

Return size (page-based)

Parameters

struct drm_vma_offset_node * node
Node to inspect

Description

Return the size as number of pages for the given node. This is the same size that was passed to drm_vma_offset_add(). If no offset is allocated for the node, this is 0.

Return

Size of node as number of pages. 0 if the node does not have an offset allocated.

__u64 drm_vma_node_offset_addr(struct drm_vma_offset_node * node)

Return sanitized offset for user-space mmaps

Parameters

struct drm_vma_offset_node * node
Linked offset node

Description

Same as drm_vma_node_start() but returns the address as a valid offset that can be used for user-space mappings during mmap(). This must not be called on unlinked nodes.

Return

Offset of node for byte-based addressing. 0 if the node does not have an object allocated.

void drm_vma_node_unmap(struct drm_vma_offset_node * node, struct address_space * file_mapping)

Unmap offset node

Parameters

struct drm_vma_offset_node * node
Offset node
struct address_space * file_mapping
Address space to unmap node from

Description

Unmap all userspace mappings for a given offset node. The mappings must be associated with the file_mapping address-space. If no offset exists nothing is done.

This call is unlocked. The caller must guarantee that drm_vma_offset_remove() is not called on this node concurrently.

int drm_vma_node_verify_access(struct drm_vma_offset_node * node, struct file * filp)

Access verification helper for TTM

Parameters

struct drm_vma_offset_node * node
Offset node
struct file * filp
Open-file

Description

This checks whether filp is granted access to node. It is the same as drm_vma_node_is_allowed() but suitable as drop-in helper for TTM verify_access() callbacks.

Return

0 if access is granted, -EACCES otherwise.

PRIME Buffer Sharing

PRIME is the cross device buffer sharing framework in drm, originally created for the OPTIMUS range of multi-gpu platforms. To userspace PRIME buffers are dma-buf based file descriptors.

Overview and Driver Interface

Similar to GEM global names, PRIME file descriptors are also used to share buffer objects across processes. They offer additional security: as file descriptors must be explicitly sent over UNIX domain sockets to be shared between applications, they can’t be guessed like the globally unique GEM names.

Drivers that support the PRIME API must set the DRIVER_PRIME bit in the struct struct drm_driver driver_features field, and implement the prime_handle_to_fd and prime_fd_to_handle operations.

int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv, uint32_t handle, uint32_t flags, int *prime_fd); int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv, int prime_fd, uint32_t *handle); Those two operations convert a handle to a PRIME file descriptor and vice versa. Drivers must use the kernel dma-buf buffer sharing framework to manage the PRIME file descriptors. Similar to the mode setting API PRIME is agnostic to the underlying buffer object manager, as long as handles are 32bit unsigned integers.

While non-GEM drivers must implement the operations themselves, GEM drivers must use the drm_gem_prime_handle_to_fd() and drm_gem_prime_fd_to_handle() helper functions. Those helpers rely on the driver gem_prime_export and gem_prime_import operations to create a dma-buf instance from a GEM object (dma-buf exporter role) and to create a GEM object from a dma-buf instance (dma-buf importer role).

struct dma_buf * (*gem_prime_export)(struct drm_device *dev, struct drm_gem_object *obj, int flags); struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev, struct dma_buf *dma_buf); These two operations are mandatory for GEM drivers that support PRIME.

PRIME Helper Functions

Drivers can implement gem_prime_export and gem_prime_import in terms of simpler APIs by using the helper functions drm_gem_prime_export and drm_gem_prime_import. These functions implement dma-buf support in terms of six lower-level driver callbacks:

Export callbacks:

  • gem_prime_pin (optional): prepare a GEM object for exporting
  • gem_prime_get_sg_table: provide a scatter/gather table of pinned pages
  • gem_prime_vmap: vmap a buffer exported by your driver
  • gem_prime_vunmap: vunmap a buffer exported by your driver
  • gem_prime_mmap (optional): mmap a buffer exported by your driver

Import callback:

  • gem_prime_import_sg_table (import): produce a GEM object from another driver’s scatter/gather table

PRIME Function References

void drm_gem_dmabuf_release(struct dma_buf * dma_buf)

dma_buf release implementation for GEM

Parameters

struct dma_buf * dma_buf
buffer to be released

Description

Generic release function for dma_bufs exported as PRIME buffers. GEM drivers must use this in their dma_buf ops structure as the release callback.

struct dma_buf * drm_gem_prime_export(struct drm_device * dev, struct drm_gem_object * obj, int flags)

helper library implementation of the export callback

Parameters

struct drm_device * dev
drm_device to export from
struct drm_gem_object * obj
GEM object to export
int flags
flags like DRM_CLOEXEC and DRM_RDWR

Description

This is the implementation of the gem_prime_export functions for GEM drivers using the PRIME helpers.

int drm_gem_prime_handle_to_fd(struct drm_device * dev, struct drm_file * file_priv, uint32_t handle, uint32_t flags, int * prime_fd)

PRIME export function for GEM drivers

Parameters

struct drm_device * dev
dev to export the buffer from
struct drm_file * file_priv
drm file-private structure
uint32_t handle
buffer handle to export
uint32_t flags
flags like DRM_CLOEXEC
int * prime_fd
pointer to storage for the fd id of the create dma-buf

Description

This is the PRIME export function which must be used mandatorily by GEM drivers to ensure correct lifetime management of the underlying GEM object. The actual exporting from GEM object to a dma-buf is done through the gem_prime_export driver callback.

struct drm_gem_object * drm_gem_prime_import(struct drm_device * dev, struct dma_buf * dma_buf)

helper library implementation of the import callback

Parameters

struct drm_device * dev
drm_device to import into
struct dma_buf * dma_buf
dma-buf object to import

Description

This is the implementation of the gem_prime_import functions for GEM drivers using the PRIME helpers.

int drm_gem_prime_fd_to_handle(struct drm_device * dev, struct drm_file * file_priv, int prime_fd, uint32_t * handle)

PRIME import function for GEM drivers

Parameters

struct drm_device * dev
dev to export the buffer from
struct drm_file * file_priv
drm file-private structure
int prime_fd
fd id of the dma-buf which should be imported
uint32_t * handle
pointer to storage for the handle of the imported buffer object

Description

This is the PRIME import function which must be used mandatorily by GEM drivers to ensure correct lifetime management of the underlying GEM object. The actual importing of GEM object from the dma-buf is done through the gem_import_export driver callback.

struct sg_table * drm_prime_pages_to_sg(struct page ** pages, unsigned int nr_pages)

converts a page array into an sg list

Parameters

struct page ** pages
pointer to the array of page pointers to convert
unsigned int nr_pages
length of the page vector

Description

This helper creates an sg table object from a set of pages the driver is responsible for mapping the pages into the importers address space for use with dma_buf itself.

int drm_prime_sg_to_page_addr_arrays(struct sg_table * sgt, struct page ** pages, dma_addr_t * addrs, int max_pages)

convert an sg table into a page array

Parameters

struct sg_table * sgt
scatter-gather table to convert
struct page ** pages
array of page pointers to store the page array in
dma_addr_t * addrs
optional array to store the dma bus address of each page
int max_pages
size of both the passed-in arrays

Description

Exports an sg table into an array of pages and addresses. This is currently required by the TTM driver in order to do correct fault handling.

void drm_prime_gem_destroy(struct drm_gem_object * obj, struct sg_table * sg)

helper to clean up a PRIME-imported GEM object

Parameters

struct drm_gem_object * obj
GEM object which was created from a dma-buf
struct sg_table * sg
the sg-table which was pinned at import time

Description

This is the cleanup functions which GEM drivers need to call when they use drm_gem_prime_import to import dma-bufs.

DRM MM Range Allocator

Overview

drm_mm provides a simple range allocator. The drivers are free to use the resource allocator from the linux core if it suits them, the upside of drm_mm is that it’s in the DRM core. Which means that it’s easier to extend for some of the crazier special purpose needs of gpus.

The main data struct is drm_mm, allocations are tracked in drm_mm_node. Drivers are free to embed either of them into their own suitable datastructures. drm_mm itself will not do any allocations of its own, so if drivers choose not to embed nodes they need to still allocate them themselves.

The range allocator also supports reservation of preallocated blocks. This is useful for taking over initial mode setting configurations from the firmware, where an object needs to be created which exactly matches the firmware’s scanout target. As long as the range is still free it can be inserted anytime after the allocator is initialized, which helps with avoiding looped depencies in the driver load sequence.

drm_mm maintains a stack of most recently freed holes, which of all simplistic datastructures seems to be a fairly decent approach to clustering allocations and avoiding too much fragmentation. This means free space searches are O(num_holes). Given that all the fancy features drm_mm supports something better would be fairly complex and since gfx thrashing is a fairly steep cliff not a real concern. Removing a node again is O(1).

drm_mm supports a few features: Alignment and range restrictions can be supplied. Further more every drm_mm_node has a color value (which is just an opaqua unsigned long) which in conjunction with a driver callback can be used to implement sophisticated placement restrictions. The i915 DRM driver uses this to implement guard pages between incompatible caching domains in the graphics TT.

Two behaviors are supported for searching and allocating: bottom-up and top-down. The default is bottom-up. Top-down allocation can be used if the memory area has different restrictions, or just to reduce fragmentation.

Finally iteration helpers to walk all nodes and all holes are provided as are some basic allocator dumpers for debugging.

LRU Scan/Eviction Support

Very often GPUs need to have continuous allocations for a given object. When evicting objects to make space for a new one it is therefore not most efficient when we simply start to select all objects from the tail of an LRU until there’s a suitable hole: Especially for big objects or nodes that otherwise have special allocation constraints there’s a good chance we evict lots of (smaller) objects unecessarily.

The DRM range allocator supports this use-case through the scanning interfaces. First a scan operation needs to be initialized with drm_mm_init_scan() or drm_mm_init_scan_with_range(). The the driver adds objects to the roaster (probably by walking an LRU list, but this can be freely implemented) until a suitable hole is found or there’s no further evitable object.

The the driver must walk through all objects again in exactly the reverse order to restore the allocator state. Note that while the allocator is used in the scan mode no other operation is allowed.

Finally the driver evicts all objects selected in the scan. Adding and removing an object is O(1), and since freeing a node is also O(1) the overall complexity is O(scanned_objects). So like the free stack which needs to be walked before a scan operation even begins this is linear in the number of objects. It doesn’t seem to hurt badly.

DRM MM Range Allocator Function References

int drm_mm_reserve_node(struct drm_mm * mm, struct drm_mm_node * node)

insert an pre-initialized node

Parameters

struct drm_mm * mm
drm_mm allocator to insert node into
struct drm_mm_node * node
drm_mm_node to insert

Description

This functions inserts an already set-up drm_mm_node into the allocator, meaning that start, size and color must be set by the caller. This is useful to initialize the allocator with preallocated objects which must be set-up before the range allocator can be set-up, e.g. when taking over a firmware framebuffer.

Return

0 on success, -ENOSPC if there’s no hole where node is.

int drm_mm_insert_node_generic(struct drm_mm * mm, struct drm_mm_node * node, u64 size, unsigned alignment, unsigned long color, enum drm_mm_search_flags sflags, enum drm_mm_allocator_flags aflags)

search for space and insert node

Parameters

struct drm_mm * mm
drm_mm to allocate from
struct drm_mm_node * node
preallocate node to insert
u64 size
size of the allocation
unsigned alignment
alignment of the allocation
unsigned long color
opaque tag value to use for this node
enum drm_mm_search_flags sflags
flags to fine-tune the allocation search
enum drm_mm_allocator_flags aflags
flags to fine-tune the allocation behavior

Description

The preallocated node must be cleared to 0.

Return

0 on success, -ENOSPC if there’s no suitable hole.

int drm_mm_insert_node_in_range_generic(struct drm_mm * mm, struct drm_mm_node * node, u64 size, unsigned alignment, unsigned long color, u64 start, u64 end, enum drm_mm_search_flags sflags, enum drm_mm_allocator_flags aflags)

ranged search for space and insert node

Parameters

struct drm_mm * mm
drm_mm to allocate from
struct drm_mm_node * node
preallocate node to insert
u64 size
size of the allocation
unsigned alignment
alignment of the allocation
unsigned long color
opaque tag value to use for this node
u64 start
start of the allowed range for this node
u64 end
end of the allowed range for this node
enum drm_mm_search_flags sflags
flags to fine-tune the allocation search
enum drm_mm_allocator_flags aflags
flags to fine-tune the allocation behavior

Description

The preallocated node must be cleared to 0.

Return

0 on success, -ENOSPC if there’s no suitable hole.

void drm_mm_remove_node(struct drm_mm_node * node)

Remove a memory node from the allocator.

Parameters

struct drm_mm_node * node
drm_mm_node to remove

Description

This just removes a node from its drm_mm allocator. The node does not need to be cleared again before it can be re-inserted into this or any other drm_mm allocator. It is a bug to call this function on a un-allocated node.

void drm_mm_replace_node(struct drm_mm_node * old, struct drm_mm_node * new)

move an allocation from old to new

Parameters

struct drm_mm_node * old
drm_mm_node to remove from the allocator
struct drm_mm_node * new
drm_mm_node which should inherit old‘s allocation

Description

This is useful for when drivers embed the drm_mm_node structure and hence can’t move allocations by reassigning pointers. It’s a combination of remove and insert with the guarantee that the allocation start will match.

void drm_mm_init_scan(struct drm_mm * mm, u64 size, unsigned alignment, unsigned long color)

initialize lru scanning

Parameters

struct drm_mm * mm
drm_mm to scan
u64 size
size of the allocation
unsigned alignment
alignment of the allocation
unsigned long color
opaque tag value to use for the allocation

Description

This simply sets up the scanning routines with the parameters for the desired hole. Note that there’s no need to specify allocation flags, since they only change the place a node is allocated from within a suitable hole.

Warning: As long as the scan list is non-empty, no other operations than adding/removing nodes to/from the scan list are allowed.

void drm_mm_init_scan_with_range(struct drm_mm * mm, u64 size, unsigned alignment, unsigned long color, u64 start, u64 end)

initialize range-restricted lru scanning

Parameters

struct drm_mm * mm
drm_mm to scan
u64 size
size of the allocation
unsigned alignment
alignment of the allocation
unsigned long color
opaque tag value to use for the allocation
u64 start
start of the allowed range for the allocation
u64 end
end of the allowed range for the allocation

Description

This simply sets up the scanning routines with the parameters for the desired hole. Note that there’s no need to specify allocation flags, since they only change the place a node is allocated from within a suitable hole.

Warning: As long as the scan list is non-empty, no other operations than adding/removing nodes to/from the scan list are allowed.

bool drm_mm_scan_add_block(struct drm_mm_node * node)

add a node to the scan list

Parameters

struct drm_mm_node * node
drm_mm_node to add

Description

Add a node to the scan list that might be freed to make space for the desired hole.

Return

True if a hole has been found, false otherwise.

bool drm_mm_scan_remove_block(struct drm_mm_node * node)

remove a node from the scan list

Parameters

struct drm_mm_node * node
drm_mm_node to remove

Description

Nodes _must_ be removed in the exact same order from the scan list as they have been added, otherwise the internal state of the memory manager will be corrupted.

When the scan list is empty, the selected memory nodes can be freed. An immediately following drm_mm_search_free with !DRM_MM_SEARCH_BEST will then return the just freed block (because its at the top of the free_stack list).

Return

True if this block should be evicted, false otherwise. Will always return false when no hole has been found.

bool drm_mm_clean(struct drm_mm * mm)

checks whether an allocator is clean

Parameters

struct drm_mm * mm
drm_mm allocator to check

Return

True if the allocator is completely free, false if there’s still a node allocated in it.

void drm_mm_init(struct drm_mm * mm, u64 start, u64 size)

initialize a drm-mm allocator

Parameters

struct drm_mm * mm
the drm_mm structure to initialize
u64 start
start of the range managed by mm
u64 size
end of the range managed by mm

Description

Note that mm must be cleared to 0 before calling this function.

void drm_mm_takedown(struct drm_mm * mm)

clean up a drm_mm allocator

Parameters

struct drm_mm * mm
drm_mm allocator to clean up

Description

Note that it is a bug to call this function on an allocator which is not clean.

void drm_mm_debug_table(struct drm_mm * mm, const char * prefix)

dump allocator state to dmesg

Parameters

struct drm_mm * mm
drm_mm allocator to dump
const char * prefix
prefix to use for dumping to dmesg
int drm_mm_dump_table(struct seq_file * m, struct drm_mm * mm)

dump allocator state to a seq_file

Parameters

struct seq_file * m
seq_file to dump to
struct drm_mm * mm
drm_mm allocator to dump
bool drm_mm_node_allocated(struct drm_mm_node * node)

checks whether a node is allocated

Parameters

struct drm_mm_node * node
drm_mm_node to check

Description

Drivers should use this helpers for proper encapusulation of drm_mm internals.

Return

True if the node is allocated.

bool drm_mm_initialized(struct drm_mm * mm)

checks whether an allocator is initialized

Parameters

struct drm_mm * mm
drm_mm to check

Description

Drivers should use this helpers for proper encapusulation of drm_mm internals.

Return

True if the mm is initialized.

u64 drm_mm_hole_node_start(struct drm_mm_node * hole_node)

computes the start of the hole following node

Parameters

struct drm_mm_node * hole_node
drm_mm_node which implicitly tracks the following hole

Description

This is useful for driver-sepific debug dumpers. Otherwise drivers should not inspect holes themselves. Drivers must check first whether a hole indeed follows by looking at node->hole_follows.

Return

Start of the subsequent hole.

u64 drm_mm_hole_node_end(struct drm_mm_node * hole_node)

computes the end of the hole following node

Parameters

struct drm_mm_node * hole_node
drm_mm_node which implicitly tracks the following hole

Description

This is useful for driver-sepific debug dumpers. Otherwise drivers should not inspect holes themselves. Drivers must check first whether a hole indeed follows by looking at node->hole_follows.

Return

End of the subsequent hole.

drm_mm_for_each_node(entry, mm)

iterator to walk over all allocated nodes

Parameters

entry
drm_mm_node structure to assign to in each iteration step
mm
drm_mm allocator to walk

Description

This iterator walks over all nodes in the range allocator. It is implemented with list_for_each, so not save against removal of elements.

drm_mm_for_each_hole(entry, mm, hole_start, hole_end)

iterator to walk over all holes

Parameters

entry
drm_mm_node used internally to track progress
mm
drm_mm allocator to walk
hole_start
ulong variable to assign the hole start to on each iteration
hole_end
ulong variable to assign the hole end to on each iteration

Description

This iterator walks over all holes in the range allocator. It is implemented with list_for_each, so not save against removal of elements. entry is used internally and will not reflect a real drm_mm_node for the very first hole. Hence users of this iterator may not access it.

Implementation Note: We need to inline list_for_each_entry in order to be able to set hole_start and hole_end on each iteration while keeping the macro sane.

The __drm_mm_for_each_hole version is similar, but with added support for going backwards.

int drm_mm_insert_node(struct drm_mm * mm, struct drm_mm_node * node, u64 size, unsigned alignment, enum drm_mm_search_flags flags)

search for space and insert node

Parameters

struct drm_mm * mm
drm_mm to allocate from
struct drm_mm_node * node
preallocate node to insert
u64 size
size of the allocation
unsigned alignment
alignment of the allocation
enum drm_mm_search_flags flags
flags to fine-tune the allocation

Description

This is a simplified version of drm_mm_insert_node_generic() with color set to 0.

The preallocated node must be cleared to 0.

Return

0 on success, -ENOSPC if there’s no suitable hole.

int drm_mm_insert_node_in_range(struct drm_mm * mm, struct drm_mm_node * node, u64 size, unsigned alignment, u64 start, u64 end, enum drm_mm_search_flags flags)

ranged search for space and insert node

Parameters

struct drm_mm * mm
drm_mm to allocate from
struct drm_mm_node * node
preallocate node to insert
u64 size
size of the allocation
unsigned alignment
alignment of the allocation
u64 start
start of the allowed range for this node
u64 end
end of the allowed range for this node
enum drm_mm_search_flags flags
flags to fine-tune the allocation

Description

This is a simplified version of drm_mm_insert_node_in_range_generic() with color set to 0.

The preallocated node must be cleared to 0.

Return

0 on success, -ENOSPC if there’s no suitable hole.

CMA Helper Functions Reference

The Contiguous Memory Allocator reserves a pool of memory at early boot that is used to service requests for large blocks of contiguous memory.

The DRM GEM/CMA helpers use this allocator as a means to provide buffer objects that are physically contiguous in memory. This is useful for display drivers that are unable to map scattered buffers via an IOMMU.

struct drm_gem_cma_object * drm_gem_cma_create(struct drm_device * drm, size_t size)

allocate an object with the given size

Parameters

struct drm_device * drm
DRM device
size_t size
size of the object to allocate

Description

This function creates a CMA GEM object and allocates a contiguous chunk of memory as backing store. The backing memory has the writecombine attribute set.

Return

A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative error code on failure.

void drm_gem_cma_free_object(struct drm_gem_object * gem_obj)

free resources associated with a CMA GEM object

Parameters

struct drm_gem_object * gem_obj
GEM object to free

Description

This function frees the backing memory of the CMA GEM object, cleans up the GEM object state and frees the memory used to store the object itself. Drivers using the CMA helpers should set this as their DRM driver’s ->:c:func:gem_free_object() callback.

int drm_gem_cma_dumb_create_internal(struct drm_file * file_priv, struct drm_device * drm, struct drm_mode_create_dumb * args)

create a dumb buffer object

Parameters

struct drm_file * file_priv
DRM file-private structure to create the dumb buffer for
struct drm_device * drm
DRM device
struct drm_mode_create_dumb * args
IOCTL data

Description

This aligns the pitch and size arguments to the minimum required. This is an internal helper that can be wrapped by a driver to account for hardware with more specific alignment requirements. It should not be used directly as the ->:c:func:dumb_create() callback in a DRM driver.

Return

0 on success or a negative error code on failure.

int drm_gem_cma_dumb_create(struct drm_file * file_priv, struct drm_device * drm, struct drm_mode_create_dumb * args)

create a dumb buffer object

Parameters

struct drm_file * file_priv
DRM file-private structure to create the dumb buffer for
struct drm_device * drm
DRM device
struct drm_mode_create_dumb * args
IOCTL data

Description

This function computes the pitch of the dumb buffer and rounds it up to an integer number of bytes per pixel. Drivers for hardware that doesn’t have any additional restrictions on the pitch can directly use this function as their ->:c:func:dumb_create() callback.

For hardware with additional restrictions, drivers can adjust the fields set up by userspace and pass the IOCTL data along to the drm_gem_cma_dumb_create_internal() function.

Return

0 on success or a negative error code on failure.

int drm_gem_cma_dumb_map_offset(struct drm_file * file_priv, struct drm_device * drm, u32 handle, u64 * offset)

return the fake mmap offset for a CMA GEM object

Parameters

struct drm_file * file_priv
DRM file-private structure containing the GEM object
struct drm_device * drm
DRM device
u32 handle
GEM object handle
u64 * offset
return location for the fake mmap offset

Description

This function look up an object by its handle and returns the fake mmap offset associated with it. Drivers using the CMA helpers should set this as their DRM driver’s ->:c:func:dumb_map_offset() callback.

Return

0 on success or a negative error code on failure.

int drm_gem_cma_mmap(struct file * filp, struct vm_area_struct * vma)

memory-map a CMA GEM object

Parameters

struct file * filp
file object
struct vm_area_struct * vma
VMA for the area to be mapped

Description

This function implements an augmented version of the GEM DRM file mmap operation for CMA objects: In addition to the usual GEM VMA setup it immediately faults in the entire object instead of using on-demaind faulting. Drivers which employ the CMA helpers should use this function as their ->:c:func:mmap() handler in the DRM device file’s file_operations structure.

Return

0 on success or a negative error code on failure.

void drm_gem_cma_describe(struct drm_gem_cma_object * cma_obj, struct seq_file * m)

describe a CMA GEM object for debugfs

Parameters

struct drm_gem_cma_object * cma_obj
CMA GEM object
struct seq_file * m
debugfs file handle

Description

This function can be used to dump a human-readable representation of the CMA GEM object into a synthetic file.

struct sg_table * drm_gem_cma_prime_get_sg_table(struct drm_gem_object * obj)

provide a scatter/gather table of pinned pages for a CMA GEM object

Parameters

struct drm_gem_object * obj
GEM object

Description

This function exports a scatter/gather table suitable for PRIME usage by calling the standard DMA mapping API. Drivers using the CMA helpers should set this as their DRM driver’s ->:c:func:gem_prime_get_sg_table() callback.

Return

A pointer to the scatter/gather table of pinned pages or NULL on failure.

struct drm_gem_object * drm_gem_cma_prime_import_sg_table(struct drm_device * dev, struct dma_buf_attachment * attach, struct sg_table * sgt)

produce a CMA GEM object from another driver’s scatter/gather table of pinned pages

Parameters

struct drm_device * dev
device to import into
struct dma_buf_attachment * attach
DMA-BUF attachment
struct sg_table * sgt
scatter/gather table of pinned pages

Description

This function imports a scatter/gather table exported via DMA-BUF by another driver. Imported buffers must be physically contiguous in memory (i.e. the scatter/gather table must contain a single entry). Drivers that use the CMA helpers should set this as their DRM driver’s ->:c:func:gem_prime_import_sg_table() callback.

Return

A pointer to a newly created GEM object or an ERR_PTR-encoded negative error code on failure.

int drm_gem_cma_prime_mmap(struct drm_gem_object * obj, struct vm_area_struct * vma)

memory-map an exported CMA GEM object

Parameters

struct drm_gem_object * obj
GEM object
struct vm_area_struct * vma
VMA for the area to be mapped

Description

This function maps a buffer imported via DRM PRIME into a userspace process’s address space. Drivers that use the CMA helpers should set this as their DRM driver’s ->:c:func:gem_prime_mmap() callback.

Return

0 on success or a negative error code on failure.

void * drm_gem_cma_prime_vmap(struct drm_gem_object * obj)

map a CMA GEM object into the kernel’s virtual address space

Parameters

struct drm_gem_object * obj
GEM object

Description

This function maps a buffer exported via DRM PRIME into the kernel’s virtual address space. Since the CMA buffers are already mapped into the kernel virtual address space this simply returns the cached virtual address. Drivers using the CMA helpers should set this as their DRM driver’s ->:c:func:gem_prime_vmap() callback.

Return

The kernel virtual address of the CMA GEM object’s backing store.

void drm_gem_cma_prime_vunmap(struct drm_gem_object * obj, void * vaddr)

unmap a CMA GEM object from the kernel’s virtual address space

Parameters

struct drm_gem_object * obj
GEM object
void * vaddr
kernel virtual address where the CMA GEM object was mapped

Description

This function removes a buffer exported via DRM PRIME from the kernel’s virtual address space. This is a no-op because CMA buffers cannot be unmapped from kernel space. Drivers using the CMA helpers should set this as their DRM driver’s ->:c:func:gem_prime_vunmap() callback.

struct drm_gem_cma_object

GEM object backed by CMA memory allocations

Definition

struct drm_gem_cma_object {
  struct drm_gem_object base;
  dma_addr_t paddr;
  struct sg_table * sgt;
  void * vaddr;
};

Members

struct drm_gem_object base
base GEM object
dma_addr_t paddr
physical address of the backing memory
struct sg_table * sgt
scatter/gather table for imported PRIME buffers
void * vaddr
kernel virtual address of the backing memory

Mode Setting

Drivers must initialize the mode setting core by calling drm_mode_config_init() on the DRM device. The function initializes the struct 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.

Display Modes Function Reference

enum drm_mode_status

hardware support status of a mode

Constants

MODE_OK
Mode OK
MODE_HSYNC
hsync out of range
MODE_VSYNC
vsync out of range
MODE_H_ILLEGAL
mode has illegal horizontal timings
MODE_V_ILLEGAL
mode has illegal horizontal timings
MODE_BAD_WIDTH
requires an unsupported linepitch
MODE_NOMODE
no mode with a matching name
MODE_NO_INTERLACE
interlaced mode not supported
MODE_NO_DBLESCAN
doublescan mode not supported
MODE_NO_VSCAN
multiscan mode not supported
MODE_MEM
insufficient video memory
MODE_VIRTUAL_X
mode width too large for specified virtual size
MODE_VIRTUAL_Y
mode height too large for specified virtual size
MODE_MEM_VIRT
insufficient video memory given virtual size
MODE_NOCLOCK
no fixed clock available
MODE_CLOCK_HIGH
clock required is too high
MODE_CLOCK_LOW
clock required is too low
MODE_CLOCK_RANGE
clock/mode isn’t in a ClockRange
MODE_BAD_HVALUE
horizontal timing was out of range
MODE_BAD_VVALUE
vertical timing was out of range
MODE_BAD_VSCAN
VScan value out of range
MODE_HSYNC_NARROW
horizontal sync too narrow
MODE_HSYNC_WIDE
horizontal sync too wide
MODE_HBLANK_NARROW
horizontal blanking too narrow
MODE_HBLANK_WIDE
horizontal blanking too wide
MODE_VSYNC_NARROW
vertical sync too narrow
MODE_VSYNC_WIDE
vertical sync too wide
MODE_VBLANK_NARROW
vertical blanking too narrow
MODE_VBLANK_WIDE
vertical blanking too wide
MODE_PANEL
exceeds panel dimensions
MODE_INTERLACE_WIDTH
width too large for interlaced mode
MODE_ONE_WIDTH
only one width is supported
MODE_ONE_HEIGHT
only one height is supported
MODE_ONE_SIZE
only one resolution is supported
MODE_NO_REDUCED
monitor doesn’t accept reduced blanking
MODE_NO_STEREO
stereo modes not supported
MODE_STALE
mode has become stale
MODE_BAD
unspecified reason
MODE_ERROR
error condition

Description

This enum is used to filter out modes not supported by the driver/hardware combination.

struct drm_display_mode

DRM kernel-internal display mode structure

Definition

struct drm_display_mode {
  struct list_head head;
  struct drm_mode_object base;
  char name[DRM_DISPLAY_MODE_LEN];
  enum drm_mode_status status;
  unsigned int type;
  int clock;
  int hdisplay;
  int hsync_start;
  int hsync_end;
  int htotal;
  int hskew;
  int vdisplay;
  int vsync_start;
  int vsync_end;
  int vtotal;
  int vscan;
  unsigned int flags;
  int width_mm;
  int height_mm;
  int crtc_clock;
  int crtc_hdisplay;
  int crtc_hblank_start;
  int crtc_hblank_end;
  int crtc_hsync_start;
  int crtc_hsync_end;
  int crtc_htotal;
  int crtc_hskew;
  int crtc_vdisplay;
  int crtc_vblank_start;
  int crtc_vblank_end;
  int crtc_vsync_start;
  int crtc_vsync_end;
  int crtc_vtotal;
  int * private;
  int private_flags;
  int vrefresh;
  int hsync;
  enum hdmi_picture_aspect picture_aspect_ratio;
};

Members

struct list_head head
struct list_head for mode lists.
struct drm_mode_object base

A display mode is a normal modeset object, possibly including public userspace id.

FIXME:

This can probably be removed since the entire concept of userspace managing modes explicitly has never landed in upstream kernel mode setting support.

char name[DRM_DISPLAY_MODE_LEN]
Human-readable name of the mode, filled out with drm_mode_set_name().
enum drm_mode_status status
Status of the mode, used to filter out modes not supported by the hardware. See enum drm_mode_status.
unsigned int type

A bitmask of flags, mostly about the source of a mode. Possible flags are:

  • DRM_MODE_TYPE_BUILTIN: Meant for hard-coded modes, effectively unused.
  • DRM_MODE_TYPE_PREFERRED: Preferred mode, usually the native resolution of an LCD panel. There should only be one preferred mode per connector at any given time.
  • DRM_MODE_TYPE_DRIVER: Mode created by the driver, which is all of them really. Drivers must set this bit for all modes they create and expose to userspace.

Plus a big list of flags which shouldn’t be used at all, but are still around since these flags are also used in the userspace ABI:

  • DRM_MODE_TYPE_DEFAULT: Again a leftover, use DRM_MODE_TYPE_PREFERRED instead.
  • DRM_MODE_TYPE_CLOCK_C and DRM_MODE_TYPE_CRTC_C: Define leftovers which are stuck around for hysterical raisins only. No one has an idea what they were meant for. Don’t use.
  • DRM_MODE_TYPE_USERDEF: Mode defined by userspace, again a vestige from older kms designs where userspace had to first add a custom mode to the kernel’s mode list before it could use it. Don’t use.
int clock
Pixel clock in kHz.
int hdisplay
horizontal display size
int hsync_start
horizontal sync start
int hsync_end
horizontal sync end
int htotal
horizontal total size
int hskew
horizontal skew?!
int vdisplay
vertical display size
int vsync_start
vertical sync start
int vsync_end
vertical sync end
int vtotal
vertical total size
int vscan
vertical scan?!
unsigned int flags

Sync and timing flags:

  • DRM_MODE_FLAG_PHSYNC: horizontal sync is active high.
  • DRM_MODE_FLAG_NHSYNC: horizontal sync is active low.
  • DRM_MODE_FLAG_PVSYNC: vertical sync is active high.
  • DRM_MODE_FLAG_NVSYNC: vertical sync is active low.
  • DRM_MODE_FLAG_INTERLACE: mode is interlaced.
  • DRM_MODE_FLAG_DBLSCAN: mode uses doublescan.
  • DRM_MODE_FLAG_CSYNC: mode uses composite sync.
  • DRM_MODE_FLAG_PCSYNC: composite sync is active high.
  • DRM_MODE_FLAG_NCSYNC: composite sync is active low.
  • DRM_MODE_FLAG_HSKEW: hskew provided (not used?).
  • DRM_MODE_FLAG_BCAST: not used?
  • DRM_MODE_FLAG_PIXMUX: not used?
  • DRM_MODE_FLAG_DBLCLK: double-clocked mode.
  • DRM_MODE_FLAG_CLKDIV2: half-clocked mode.

Additionally there’s flags to specify how 3D modes are packed:

  • DRM_MODE_FLAG_3D_NONE: normal, non-3D mode.
  • DRM_MODE_FLAG_3D_FRAME_PACKING: 2 full frames for left and right.
  • DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE: interleaved like fields.
  • DRM_MODE_FLAG_3D_LINE_ALTERNATIVE: interleaved lines.
  • DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL: side-by-side full frames.
  • DRM_MODE_FLAG_3D_L_DEPTH: ?
  • DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH: ?
  • DRM_MODE_FLAG_3D_TOP_AND_BOTTOM: frame split into top and bottom parts.
  • DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF: frame split into left and right parts.
int width_mm
Addressable size of the output in mm, projectors should set this to 0.
int height_mm
Addressable size of the output in mm, projectors should set this to 0.
int crtc_clock

Actual pixel or dot clock in the hardware. This differs from the logical clock when e.g. using interlacing, double-clocking, stereo modes or other fancy stuff that changes the timings and signals actually sent over the wire.

This is again in kHz.

Note that with digital outputs like HDMI or DP there’s usually a massive confusion between the dot clock and the signal clock at the bit encoding level. Especially when a 8b/10b encoding is used and the difference is exactly a factor of 10.

int crtc_hdisplay
hardware mode horizontal display size
int crtc_hblank_start
hardware mode horizontal blank start
int crtc_hblank_end
hardware mode horizontal blank end
int crtc_hsync_start
hardware mode horizontal sync start
int crtc_hsync_end
hardware mode horizontal sync end
int crtc_htotal
hardware mode horizontal total size
int crtc_hskew
hardware mode horizontal skew?!
int crtc_vdisplay
hardware mode vertical display size
int crtc_vblank_start
hardware mode vertical blank start
int crtc_vblank_end
hardware mode vertical blank end
int crtc_vsync_start
hardware mode vertical sync start
int crtc_vsync_end
hardware mode vertical sync end
int crtc_vtotal
hardware mode vertical total size
int * private
Pointer for driver private data. This can only be used for mode objects passed to drivers in modeset operations. It shouldn’t be used by atomic drivers since they can store any additional data by subclassing state structures.
int private_flags
Similar to private, but just an integer.
int vrefresh

Vertical refresh rate, for debug output in human readable form. Not used in a functional way.

This value is in Hz.

int hsync

Horizontal refresh rate, for debug output in human readable form. Not used in a functional way.

This value is in kHz.

enum hdmi_picture_aspect picture_aspect_ratio
Field for setting the HDMI picture aspect ratio of a mode.

Description

The horizontal and vertical timings are defined per the following diagram.

Active Front Sync Back

Region Porch Porch

<———————–><—————-><————-><————–>
//////////////////////|

////////////////////// |

////////////////////// |.................. ................

<—– [hv]display —–> <————- [hv]sync_start ————> <——————— [hv]sync_end ———————> <——————————– [hv]total —————————–>*

This structure contains two copies of timings. First are the plain timings, which specify the logical mode, as it would be for a progressive 1:1 scanout at the refresh rate userspace can observe through vblank timestamps. Then there’s the hardware timings, which are corrected for interlacing, double-clocking and similar things. They are provided as a convenience, and can be appropriately computed using drm_mode_set_crtcinfo().

bool drm_mode_is_stereo(const struct drm_display_mode * mode)

check for stereo mode flags

Parameters

const struct drm_display_mode * mode
drm_display_mode to check

Return

True if the mode is one of the stereo modes (like side-by-side), false if not.

void drm_mode_debug_printmodeline(const struct drm_display_mode * mode)

print a mode to dmesg

Parameters

const struct drm_display_mode * mode
mode to print

Description

Describe mode using DRM_DEBUG.

struct drm_display_mode * drm_mode_create(struct drm_device * dev)

create a new display mode

Parameters

struct drm_device * dev
DRM device

Description

Create a new, cleared drm_display_mode with kzalloc, allocate an ID for it and return it.

Return

Pointer to new mode on success, NULL on error.

void drm_mode_destroy(struct drm_device * dev, struct drm_display_mode * mode)

remove a mode

Parameters

struct drm_device * dev
DRM device
struct drm_display_mode * mode
mode to remove

Description

Release mode‘s unique ID, then free it mode structure itself using kfree.

void drm_mode_probed_add(struct drm_connector * connector, struct drm_display_mode * mode)

add a mode to a connector’s probed_mode list

Parameters

struct drm_connector * connector
connector the new mode
struct drm_display_mode * mode
mode data

Description

Add mode to connector‘s probed_mode list for later use. This list should then in a second step get filtered and all the modes actually supported by the hardware moved to the connector‘s modes list.

struct drm_display_mode * drm_cvt_mode(struct drm_device * dev, int hdisplay, int vdisplay, int vrefresh, bool reduced, bool interlaced, bool margins)

create a modeline based on the CVT algorithm

Parameters

struct drm_device * dev
drm device
int hdisplay
hdisplay size
int vdisplay
vdisplay size
int vrefresh
vrefresh rate
bool reduced
whether to use reduced blanking
bool interlaced
whether to compute an interlaced mode
bool margins
whether to add margins (borders)

Description

This function is called to generate the modeline based on CVT algorithm according to the hdisplay, vdisplay, vrefresh. It is based from the VESA(TM) Coordinated Video Timing Generator by Graham Loveridge April 9, 2003 available at http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls

And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c. What I have done is to translate it by using integer calculation.

Return

The modeline based on the CVT algorithm stored in a drm_display_mode object. The display mode object is allocated with drm_mode_create(). Returns NULL when no mode could be allocated.

struct drm_display_mode * drm_gtf_mode_complex(struct drm_device * dev, int hdisplay, int vdisplay, int vrefresh, bool interlaced, int margins, int GTF_M, int GTF_2C, int GTF_K, int GTF_2J)

create the modeline based on the full GTF algorithm

Parameters

struct drm_device * dev
drm device
int hdisplay
hdisplay size
int vdisplay
vdisplay size
int vrefresh
vrefresh rate.
bool interlaced
whether to compute an interlaced mode
int margins
desired margin (borders) size
int GTF_M
extended GTF formula parameters
int GTF_2C
extended GTF formula parameters
int GTF_K
extended GTF formula parameters
int GTF_2J
extended GTF formula parameters

Description

GTF feature blocks specify C and J in multiples of 0.5, so we pass them in here multiplied by two. For a C of 40, pass in 80.

Return

The modeline based on the full GTF algorithm stored in a drm_display_mode object. The display mode object is allocated with drm_mode_create(). Returns NULL when no mode could be allocated.

struct drm_display_mode * drm_gtf_mode(struct drm_device * dev, int hdisplay, int vdisplay, int vrefresh, bool interlaced, int margins)

create the modeline based on the GTF algorithm

Parameters

struct drm_device * dev
drm device
int hdisplay
hdisplay size
int vdisplay
vdisplay size
int vrefresh
vrefresh rate.
bool interlaced
whether to compute an interlaced mode
int margins
desired margin (borders) size

Description

return the modeline based on GTF algorithm

This function is to create the modeline based on the GTF algorithm. Generalized Timing Formula is derived from:

GTF Spreadsheet by Andy Morrish (1/5/97) available at http://www.vesa.org

And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c. What I have done is to translate it by using integer calculation. I also refer to the function of fb_get_mode in the file of drivers/video/fbmon.c

Standard GTF parameters:
M = 600 C = 40 K = 128 J = 20

Return

The modeline based on the GTF algorithm stored in a drm_display_mode object. The display mode object is allocated with drm_mode_create(). Returns NULL when no mode could be allocated.

void drm_display_mode_from_videomode(const struct videomode * vm, struct drm_display_mode * dmode)

fill in dmode using vm,

Parameters

const struct videomode * vm
videomode structure to use as source
struct drm_display_mode * dmode
drm_display_mode structure to use as destination

Description

Fills out dmode using the display mode specified in vm.

void drm_display_mode_to_videomode(const struct drm_display_mode * dmode, struct videomode * vm)

fill in vm using dmode,

Parameters

const struct drm_display_mode * dmode
drm_display_mode structure to use as source
struct videomode * vm
videomode structure to use as destination

Description

Fills out vm using the display mode specified in dmode.

int of_get_drm_display_mode(struct device_node * np, struct drm_display_mode * dmode, int index)

get a drm_display_mode from devicetree

Parameters

struct device_node * np
device_node with the timing specification
struct drm_display_mode * dmode
will be set to the return value
int index
index into the list of display timings in devicetree

Description

This function is expensive and should only be used, if only one mode is to be read from DT. To get multiple modes start with of_get_display_timings and work with that instead.

Return

0 on success, a negative errno code when no of videomode node was found.

void drm_mode_set_name(struct drm_display_mode * mode)

set the name on a mode

Parameters

struct drm_display_mode * mode
name will be set in this mode

Description

Set the name of mode to a standard format which is <hdisplay>x<vdisplay> with an optional ‘i’ suffix for interlaced modes.

int drm_mode_hsync(const struct drm_display_mode * mode)

get the hsync of a mode

Parameters

const struct drm_display_mode * mode
mode

Return

modes‘s hsync rate in kHz, rounded to the nearest integer. Calculates the value first if it is not yet set.

int drm_mode_vrefresh(const struct drm_display_mode * mode)

get the vrefresh of a mode

Parameters

const struct drm_display_mode * mode
mode

Return

modes‘s vrefresh rate in Hz, rounded to the nearest integer. Calculates the value first if it is not yet set.

void drm_mode_set_crtcinfo(struct drm_display_mode * p, int adjust_flags)

set CRTC modesetting timing parameters

Parameters

struct drm_display_mode * p
mode
int adjust_flags
a combination of adjustment flags

Description

Setup the CRTC modesetting timing parameters for p, adjusting if necessary.

  • The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of interlaced modes.
  • The CRTC_STEREO_DOUBLE flag can be used to compute the timings for buffers containing two eyes (only adjust the timings when needed, eg. for “frame packing” or “side by side full”).
  • The CRTC_NO_DBLSCAN and CRTC_NO_VSCAN flags request that adjustment not be performed for doublescan and vscan > 1 modes respectively.
void drm_mode_copy(struct drm_display_mode * dst, const struct drm_display_mode * src)

copy the mode

Parameters

struct drm_display_mode * dst
mode to overwrite
const struct drm_display_mode * src
mode to copy

Description

Copy an existing mode into another mode, preserving the object id and list head of the destination mode.

struct drm_display_mode * drm_mode_duplicate(struct drm_device * dev, const struct drm_display_mode * mode)

allocate and duplicate an existing mode

Parameters

struct drm_device * dev
drm_device to allocate the duplicated mode for
const struct drm_display_mode * mode
mode to duplicate

Description

Just allocate a new mode, copy the existing mode into it, and return a pointer to it. Used to create new instances of established modes.

Return

Pointer to duplicated mode on success, NULL on error.

bool drm_mode_equal(const struct drm_display_mode * mode1, const struct drm_display_mode * mode2)

test modes for equality

Parameters

const struct drm_display_mode * mode1
first mode
const struct drm_display_mode * mode2
second mode

Description

Check to see if mode1 and mode2 are equivalent.

Return

True if the modes are equal, false otherwise.

bool drm_mode_equal_no_clocks(const struct drm_display_mode * mode1, const struct drm_display_mode * mode2)

test modes for equality

Parameters

const struct drm_display_mode * mode1
first mode
const struct drm_display_mode * mode2
second mode

Description

Check to see if mode1 and mode2 are equivalent, but don’t check the pixel clocks.

Return

True if the modes are equal, false otherwise.

bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode * mode1, const struct drm_display_mode * mode2)

test modes for equality

Parameters

const struct drm_display_mode * mode1
first mode
const struct drm_display_mode * mode2
second mode

Description

Check to see if mode1 and mode2 are equivalent, but don’t check the pixel clocks nor the stereo layout.

Return

True if the modes are equal, false otherwise.

enum drm_mode_status drm_mode_validate_basic(const struct drm_display_mode * mode)

make sure the mode is somewhat sane

Parameters

const struct drm_display_mode * mode
mode to check

Description

Check that the mode timings are at least somewhat reasonable. Any hardware specific limits are left up for each driver to check.

Return

The mode status

enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode * mode, int maxX, int maxY)

make sure modes adhere to size constraints

Parameters

const struct drm_display_mode * mode
mode to check
int maxX
maximum width
int maxY
maximum height

Description

This function is a helper which can be used to validate modes against size limitations of the DRM device/connector. If a mode is too big its status member is updated with the appropriate validation failure code. The list itself is not changed.

Return

The mode status

void drm_mode_prune_invalid(struct drm_device * dev, struct list_head * mode_list, bool verbose)

remove invalid modes from mode list

Parameters

struct drm_device * dev
DRM device
struct list_head * mode_list
list of modes to check
bool verbose
be verbose about it

Description

This helper function can be used to prune a display mode list after validation has been completed. All modes who’s status is not MODE_OK will be removed from the list, and if verbose the status code and mode name is also printed to dmesg.

void drm_mode_sort(struct list_head * mode_list)

sort mode list

Parameters

struct list_head * mode_list
list of drm_display_mode structures to sort

Description

Sort mode_list by favorability, moving good modes to the head of the list.

void drm_mode_connector_list_update(struct drm_connector * connector)

update the mode list for the connector

Parameters

struct drm_connector * connector
the connector to update

Description

This moves the modes from the connector probed_modes list to the actual mode list. It compares the probed mode against the current list and only adds different/new modes.

This is just a helper functions doesn’t validate any modes itself and also doesn’t prune any invalid modes. Callers need to do that themselves.

bool drm_mode_parse_command_line_for_connector(const char * mode_option, struct drm_connector * connector, struct drm_cmdline_mode * mode)

parse command line modeline for connector

Parameters

const char * mode_option
optional per connector mode option
struct drm_connector * connector
connector to parse modeline for
struct drm_cmdline_mode * mode
preallocated drm_cmdline_mode structure to fill out

Description

This parses mode_option command line modeline for modes and options to configure the connector. If mode_option is NULL the default command line modeline in fb_mode_option will be parsed instead.

This uses the same parameters as the fb modedb.c, except for an extra force-enable, force-enable-digital and force-disable bit at the end:

<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]

The intermediate drm_cmdline_mode structure is required to store additional options from the command line modline like the force-enable/disable flag.

Return

True if a valid modeline has been parsed, false otherwise.

struct drm_display_mode * drm_mode_create_from_cmdline_mode(struct drm_device * dev, struct drm_cmdline_mode * cmd)

convert a command line modeline into a DRM display mode

Parameters

struct drm_device * dev
DRM device to create the new mode for
struct drm_cmdline_mode * cmd
input command line modeline

Return

Pointer to converted mode on success, NULL on error.

Atomic Mode Setting Function Reference

void drm_atomic_state_default_release(struct drm_atomic_state * state)

release memory initialized by drm_atomic_state_init

Parameters

struct drm_atomic_state * state
atomic state

Description

Free all the memory allocated by drm_atomic_state_init. This is useful for drivers that subclass the atomic state.

int drm_atomic_state_init(struct drm_device * dev, struct drm_atomic_state * state)

init new atomic state

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * state
atomic state

Description

Default implementation for filling in a new atomic state. This is useful for drivers that subclass the atomic state.

struct drm_atomic_state * drm_atomic_state_alloc(struct drm_device * dev)

allocate atomic state

Parameters

struct drm_device * dev
DRM device

Description

This allocates an empty atomic state to track updates.

void drm_atomic_state_default_clear(struct drm_atomic_state * state)

clear base atomic state

Parameters

struct drm_atomic_state * state
atomic state

Description

Default implementation for clearing atomic state. This is useful for drivers that subclass the atomic state.

void drm_atomic_state_clear(struct drm_atomic_state * state)

clear state object

Parameters

struct drm_atomic_state * state
atomic state

Description

When the w/w mutex algorithm detects a deadlock we need to back off and drop all locks. So someone else could sneak in and change the current modeset configuration. Which means that all the state assembled in state is no longer an atomic update to the current state, but to some arbitrary earlier state. Which could break assumptions the driver’s ->atomic_check likely relies on.

Hence we must clear all cached state and completely start over, using this function.

void drm_atomic_state_free(struct drm_atomic_state * state)

free all memory for an atomic state

Parameters

struct drm_atomic_state * state
atomic state to deallocate

Description

This frees all memory associated with an atomic state, including all the per-object state for planes, crtcs and connectors.

struct drm_crtc_state * drm_atomic_get_crtc_state(struct drm_atomic_state * state, struct drm_crtc * crtc)

get crtc state

Parameters

struct drm_atomic_state * state
global atomic state object
struct drm_crtc * crtc
crtc to get state object for

Description

This function returns the crtc state for the given crtc, allocating it if needed. It will also grab the relevant crtc lock to make sure that the state is consistent.

Return

Either the allocated state or the error code encoded into the pointer. When the error is EDEADLK then the w/w mutex code has detected a deadlock and the entire atomic sequence must be restarted. All other errors are fatal.

int drm_atomic_set_mode_for_crtc(struct drm_crtc_state * state, struct drm_display_mode * mode)

set mode for CRTC

Parameters

struct drm_crtc_state * state
the CRTC whose incoming state to update
struct drm_display_mode * mode
kernel-internal mode to use for the CRTC, or NULL to disable

Description

Set a mode (originating from the kernel) on the desired CRTC state. Does not change any other state properties, including enable, active, or mode_changed.

Return

Zero on success, error code on failure. Cannot return -EDEADLK.

int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state * state, struct drm_property_blob * blob)

set mode for CRTC

Parameters

struct drm_crtc_state * state
the CRTC whose incoming state to update
struct drm_property_blob * blob
pointer to blob property to use for mode

Description

Set a mode (originating from a blob property) on the desired CRTC state. This function will take a reference on the blob property for the CRTC state, and release the reference held on the state’s existing mode property, if any was set.

Return

Zero on success, error code on failure. Cannot return -EDEADLK.

int drm_atomic_crtc_set_property(struct drm_crtc * crtc, struct drm_crtc_state * state, struct drm_property * property, uint64_t val)

set property on CRTC

Parameters

struct drm_crtc * crtc
the drm CRTC to set a property on
struct drm_crtc_state * state
the state object to update with the new property value
struct drm_property * property
the property to set
uint64_t val
the new property value

Description

Use this instead of calling crtc->atomic_set_property directly. This function handles generic/core properties and calls out to driver’s ->:c:func:atomic_set_property() for driver properties. To ensure consistent behavior you must call this function rather than the driver hook directly.

Return

Zero on success, error code on failure

struct drm_plane_state * drm_atomic_get_plane_state(struct drm_atomic_state * state, struct drm_plane * plane)

get plane state

Parameters

struct drm_atomic_state * state
global atomic state object
struct drm_plane * plane
plane to get state object for

Description

This function returns the plane state for the given plane, allocating it if needed. It will also grab the relevant plane lock to make sure that the state is consistent.

Return

Either the allocated state or the error code encoded into the pointer. When the error is EDEADLK then the w/w mutex code has detected a deadlock and the entire atomic sequence must be restarted. All other errors are fatal.

int drm_atomic_plane_set_property(struct drm_plane * plane, struct drm_plane_state * state, struct drm_property * property, uint64_t val)

set property on plane

Parameters

struct drm_plane * plane
the drm plane to set a property on
struct drm_plane_state * state
the state object to update with the new property value
struct drm_property * property
the property to set
uint64_t val
the new property value

Description

Use this instead of calling plane->atomic_set_property directly. This function handles generic/core properties and calls out to driver’s ->:c:func:atomic_set_property() for driver properties. To ensure consistent behavior you must call this function rather than the driver hook directly.

Return

Zero on success, error code on failure

struct drm_connector_state * drm_atomic_get_connector_state(struct drm_atomic_state * state, struct drm_connector * connector)

get connector state

Parameters

struct drm_atomic_state * state
global atomic state object
struct drm_connector * connector
connector to get state object for

Description

This function returns the connector state for the given connector, allocating it if needed. It will also grab the relevant connector lock to make sure that the state is consistent.

Return

Either the allocated state or the error code encoded into the pointer. When the error is EDEADLK then the w/w mutex code has detected a deadlock and the entire atomic sequence must be restarted. All other errors are fatal.

int drm_atomic_connector_set_property(struct drm_connector * connector, struct drm_connector_state * state, struct drm_property * property, uint64_t val)

set property on connector.

Parameters

struct drm_connector * connector
the drm connector to set a property on
struct drm_connector_state * state
the state object to update with the new property value
struct drm_property * property
the property to set
uint64_t val
the new property value

Description

Use this instead of calling connector->atomic_set_property directly. This function handles generic/core properties and calls out to driver’s ->:c:func:atomic_set_property() for driver properties. To ensure consistent behavior you must call this function rather than the driver hook directly.

Return

Zero on success, error code on failure

int drm_atomic_set_crtc_for_plane(struct drm_plane_state * plane_state, struct drm_crtc * crtc)

set crtc for plane

Parameters

struct drm_plane_state * plane_state
the plane whose incoming state to update
struct drm_crtc * crtc
crtc to use for the plane

Description

Changing the assigned crtc for a plane requires us to grab the lock and state for the new crtc, as needed. This function takes care of all these details besides updating the pointer in the state object itself.

Return

0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK then the w/w mutex code has detected a deadlock and the entire atomic sequence must be restarted. All other errors are fatal.

void drm_atomic_set_fb_for_plane(struct drm_plane_state * plane_state, struct drm_framebuffer * fb)

set framebuffer for plane

Parameters

struct drm_plane_state * plane_state
atomic state object for the plane
struct drm_framebuffer * fb
fb to use for the plane

Description

Changing the assigned framebuffer for a plane requires us to grab a reference to the new fb and drop the reference to the old fb, if there is one. This function takes care of all these details besides updating the pointer in the state object itself.

int drm_atomic_set_crtc_for_connector(struct drm_connector_state * conn_state, struct drm_crtc * crtc)

set crtc for connector

Parameters

struct drm_connector_state * conn_state
atomic state object for the connector
struct drm_crtc * crtc
crtc to use for the connector

Description

Changing the assigned crtc for a connector requires us to grab the lock and state for the new crtc, as needed. This function takes care of all these details besides updating the pointer in the state object itself.

Return

0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK then the w/w mutex code has detected a deadlock and the entire atomic sequence must be restarted. All other errors are fatal.

int drm_atomic_add_affected_connectors(struct drm_atomic_state * state, struct drm_crtc * crtc)

add connectors for crtc

Parameters

struct drm_atomic_state * state
atomic state
struct drm_crtc * crtc
DRM crtc

Description

This function walks the current configuration and adds all connectors currently using crtc to the atomic configuration state. Note that this function must acquire the connection mutex. This can potentially cause unneeded seralization if the update is just for the planes on one crtc. Hence drivers and helpers should only call this when really needed (e.g. when a full modeset needs to happen due to some change).

Return

0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK then the w/w mutex code has detected a deadlock and the entire atomic sequence must be restarted. All other errors are fatal.

int drm_atomic_add_affected_planes(struct drm_atomic_state * state, struct drm_crtc * crtc)

add planes for crtc

Parameters

struct drm_atomic_state * state
atomic state
struct drm_crtc * crtc
DRM crtc

Description

This function walks the current configuration and adds all planes currently used by crtc to the atomic configuration state. This is useful when an atomic commit also needs to check all currently enabled plane on crtc, e.g. when changing the mode. It’s also useful when re-enabling a CRTC to avoid special code to force-enable all planes.

Since acquiring a plane state will always also acquire the w/w mutex of the current CRTC for that plane (if there is any) adding all the plane states for a CRTC will not reduce parallism of atomic updates.

Return

0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK then the w/w mutex code has detected a deadlock and the entire atomic sequence must be restarted. All other errors are fatal.

void drm_atomic_legacy_backoff(struct drm_atomic_state * state)

locking backoff for legacy ioctls

Parameters

struct drm_atomic_state * state
atomic state

Description

This function should be used by legacy entry points which don’t understand -EDEADLK semantics. For simplicity this one will grab all modeset locks after the slowpath completed.

int drm_atomic_check_only(struct drm_atomic_state * state)

check whether a given config would work

Parameters

struct drm_atomic_state * state
atomic configuration to check

Description

Note that this function can return -EDEADLK if the driver needed to acquire more locks but encountered a deadlock. The caller must then do the usual w/w backoff dance and restart. All other errors are fatal.

Return

0 on success, negative error code on failure.

int drm_atomic_commit(struct drm_atomic_state * state)

commit configuration atomically

Parameters

struct drm_atomic_state * state
atomic configuration to check

Description

Note that this function can return -EDEADLK if the driver needed to acquire more locks but encountered a deadlock. The caller must then do the usual w/w backoff dance and restart. All other errors are fatal.

Also note that on successful execution ownership of state is transferred from the caller of this function to the function itself. The caller must not free or in any other way access state. If the function fails then the caller must clean up state itself.

Return

0 on success, negative error code on failure.

int drm_atomic_nonblocking_commit(struct drm_atomic_state * state)

atomic:c:type:nonblocking configuration commit

Parameters

struct drm_atomic_state * state
atomic configuration to check

Description

Note that this function can return -EDEADLK if the driver needed to acquire more locks but encountered a deadlock. The caller must then do the usual w/w backoff dance and restart. All other errors are fatal.

Also note that on successful execution ownership of state is transferred from the caller of this function to the function itself. The caller must not free or in any other way access state. If the function fails then the caller must clean up state itself.

Return

0 on success, negative error code on failure.

void drm_atomic_clean_old_fb(struct drm_device * dev, unsigned plane_mask, int ret)
  • Unset old_fb pointers and set plane->fb pointers.

Parameters

struct drm_device * dev
drm device to check.
unsigned plane_mask
plane mask for planes that were updated.
int ret
return value, can be -EDEADLK for a retry.

Description

Before doing an update plane->old_fb is set to plane->fb, but before dropping the locks old_fb needs to be set to NULL and plane->fb updated. This is a common operation for each atomic update, so this call is split off as a helper.

void drm_atomic_replace_property_blob(struct drm_property_blob ** blob, struct drm_property_blob * new_blob, bool * replaced)

replace a blob property

Parameters

struct drm_property_blob ** blob
a pointer to the member blob to be replaced
struct drm_property_blob * new_blob
the new blob to replace with
bool * replaced
whether the blob has been replaced

Return

Zero on success, error code on failure

int drm_atomic_crtc_get_property(struct drm_crtc * crtc, const struct drm_crtc_state * state, struct drm_property * property, uint64_t * val)

get property value from CRTC state

Parameters

struct drm_crtc * crtc
the drm CRTC to set a property on
const struct drm_crtc_state * state
the state object to get the property value from
struct drm_property * property
the property to set
uint64_t * val
return location for the property value

Description

This function handles generic/core properties and calls out to driver’s ->:c:func:atomic_get_property() for driver properties. To ensure consistent behavior you must call this function rather than the driver hook directly.

Return

Zero on success, error code on failure

int drm_atomic_crtc_check(struct drm_crtc * crtc, struct drm_crtc_state * state)

check crtc state

Parameters

struct drm_crtc * crtc
crtc to check
struct drm_crtc_state * state
crtc state to check

Description

Provides core sanity checks for crtc state.

Return

Zero on success, error code on failure

int drm_atomic_plane_get_property(struct drm_plane * plane, const struct drm_plane_state * state, struct drm_property * property, uint64_t * val)

get property value from plane state

Parameters

struct drm_plane * plane
the drm plane to set a property on
const struct drm_plane_state * state
the state object to get the property value from
struct drm_property * property
the property to set
uint64_t * val
return location for the property value

Description

This function handles generic/core properties and calls out to driver’s ->:c:func:atomic_get_property() for driver properties. To ensure consistent behavior you must call this function rather than the driver hook directly.

Return

Zero on success, error code on failure

int drm_atomic_plane_check(struct drm_plane * plane, struct drm_plane_state * state)

check plane state

Parameters

struct drm_plane * plane
plane to check
struct drm_plane_state * state
plane state to check

Description

Provides core sanity checks for plane state.

Return

Zero on success, error code on failure

int drm_atomic_connector_get_property(struct drm_connector * connector, const struct drm_connector_state * state, struct drm_property * property, uint64_t * val)

get property value from connector state

Parameters

struct drm_connector * connector
the drm connector to set a property on
const struct drm_connector_state * state
the state object to get the property value from
struct drm_property * property
the property to set
uint64_t * val
return location for the property value

Description

This function handles generic/core properties and calls out to driver’s ->:c:func:atomic_get_property() for driver properties. To ensure consistent behavior you must call this function rather than the driver hook directly.

Return

Zero on success, error code on failure

Frame Buffer Abstraction

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.

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 :c:func:`drm_framebuffer_unreference(). For driver-private framebuffers for which the last reference is never dropped (e.g. for the fbdev framebuffer when the struct 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 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 ?.

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

KMS Initialization and Cleanup

A KMS device is abstracted and exposed as a set of planes, CRTCs, encoders and connectors. KMS drivers must thus create and initialize all those objects at load time after initializing mode setting.

CRTCs (struct drm_crtc)

A CRTC is an abstraction representing a part of the chip that contains a pointer to a scanout buffer. Therefore, the number of CRTCs available determines how many independent scanout buffers can be active at any given time. The CRTC structure contains several fields to support this: a pointer to some video memory (abstracted as a frame buffer object), a display mode, and an (x, y) offset into the video memory to support panning or configurations where one piece of video memory spans multiple CRTCs.

CRTC Initialization

A KMS device must create and register at least one struct struct drm_crtc instance. The instance is allocated and zeroed by the driver, possibly as part of a larger structure, and registered with a call to drm_crtc_init() with a pointer to CRTC functions.

Planes (struct drm_plane)

A plane represents an image source that can be blended with or overlayed on top of a CRTC during the scanout process. Planes are associated with a frame buffer to crop a portion of the image memory (source) and optionally scale it to a destination size. The result is then blended with or overlayed on top of a CRTC.

The DRM core recognizes three types of planes:

  • DRM_PLANE_TYPE_PRIMARY represents a “main” plane for a CRTC. Primary planes are the planes operated upon by CRTC modesetting and flipping operations described in the page_flip hook in struct drm_crtc_funcs.
  • DRM_PLANE_TYPE_CURSOR represents a “cursor” plane for a CRTC. Cursor planes are the planes operated upon by the DRM_IOCTL_MODE_CURSOR and DRM_IOCTL_MODE_CURSOR2 ioctls.
  • DRM_PLANE_TYPE_OVERLAY represents all non-primary, non-cursor planes. Some drivers refer to these types of planes as “sprites” internally.

For compatibility with legacy userspace, only overlay planes are made available to userspace by default. Userspace clients may set the DRM_CLIENT_CAP_UNIVERSAL_PLANES client capability bit to indicate that they wish to receive a universal plane list containing all plane types.

Plane Initialization

To create a plane, a KMS drivers allocates and zeroes an instances of struct drm_plane (possibly as part of a larger structure) and registers it with a call to drm_universal_plane_init(). The function takes a bitmask of the CRTCs that can be associated with the plane, a pointer to the plane functions, a list of format supported formats, and the type of plane (primary, cursor, or overlay) being initialized.

Cursor and overlay planes are optional. All drivers should provide one primary plane per CRTC (although this requirement may change in the future); drivers that do not wish to provide special handling for primary planes may make use of the helper functions described in ? to create and register a primary plane with standard capabilities.

Encoders (struct drm_encoder)

An encoder takes pixel data from a CRTC and converts it to a format suitable for any attached connectors. On some devices, it may be possible to have a CRTC send data to more than one encoder. In that case, both encoders would receive data from the same scanout buffer, resulting in a “cloned” display configuration across the connectors attached to each encoder.

Encoder Initialization

As for CRTCs, a KMS driver must create, initialize and register at least one struct drm_encoder instance. The instance is allocated and zeroed by the driver, possibly as part of a larger structure.

Drivers must initialize the struct drm_encoder possible_crtcs and possible_clones fields before registering the encoder. Both fields are bitmasks of respectively the CRTCs that the encoder can be connected to, and sibling encoders candidate for cloning.

After being initialized, the encoder must be registered with a call to drm_encoder_init(). The function takes a pointer to the encoder functions and an encoder type. Supported types are

  • DRM_MODE_ENCODER_DAC for VGA and analog on DVI-I/DVI-A
  • DRM_MODE_ENCODER_TMDS for DVI, HDMI and (embedded) DisplayPort
  • DRM_MODE_ENCODER_LVDS for display panels
  • DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video, Component, SCART)
  • DRM_MODE_ENCODER_VIRTUAL for virtual machine displays

Encoders must be attached to a CRTC to be used. DRM drivers leave encoders unattached at initialization time. Applications (or the fbdev compatibility layer when implemented) are responsible for attaching the encoders they want to use to a CRTC.

Connectors (struct drm_connector)

A connector is the final destination for pixel data on a device, and usually connects directly to an external display device like a monitor or laptop panel. A connector can only be attached to one encoder at a time. The connector is also the structure where information about the attached display is kept, so it contains fields for display data, EDID data, DPMS & connection status, and information about modes supported on the attached displays.

Connector Initialization

Finally a KMS driver must create, initialize, register and attach at least one struct drm_connector instance. The instance is created as other KMS objects and initialized by setting the following fields.

interlace_allowed
Whether the connector can handle interlaced modes.
doublescan_allowed
Whether the connector can handle doublescan.
display_info
Display information is filled from EDID information when a display is detected. For non hot-pluggable displays such as flat panels in embedded systems, the driver should initialize the display_info.width_mm and display_info.height_mm fields with the physical size of the display.
polled

Connector polling mode, a combination of

DRM_CONNECTOR_POLL_HPD
The connector generates hotplug events and doesn’t need to be periodically polled. The CONNECT and DISCONNECT flags must not be set together with the HPD flag.
DRM_CONNECTOR_POLL_CONNECT
Periodically poll the connector for connection.
DRM_CONNECTOR_POLL_DISCONNECT
Periodically poll the connector for disconnection.

Set to 0 for connectors that don’t support connection status discovery.

The connector is then registered with a call to drm_connector_init() with a pointer to the connector functions and a connector type, and exposed through sysfs with a call to drm_connector_register().

Supported connector types are

  • DRM_MODE_CONNECTOR_VGA
  • DRM_MODE_CONNECTOR_DVII
  • DRM_MODE_CONNECTOR_DVID
  • DRM_MODE_CONNECTOR_DVIA
  • DRM_MODE_CONNECTOR_Composite
  • DRM_MODE_CONNECTOR_SVIDEO
  • DRM_MODE_CONNECTOR_LVDS
  • DRM_MODE_CONNECTOR_Component
  • DRM_MODE_CONNECTOR_9PinDIN
  • DRM_MODE_CONNECTOR_DisplayPort
  • DRM_MODE_CONNECTOR_HDMIA
  • DRM_MODE_CONNECTOR_HDMIB
  • DRM_MODE_CONNECTOR_TV
  • DRM_MODE_CONNECTOR_eDP
  • DRM_MODE_CONNECTOR_VIRTUAL

Connectors must be attached to an encoder to be used. For devices that map connectors to encoders 1:1, the connector should be attached at initialization time with a call to drm_mode_connector_attach_encoder(). The driver must also set the struct drm_connector encoder field to point to the attached encoder.

Finally, drivers must initialize the connectors state change detection with a call to drm_kms_helper_poll_init(). If at least one connector is pollable but can’t generate hotplug interrupts (indicated by the DRM_CONNECTOR_POLL_CONNECT and DRM_CONNECTOR_POLL_DISCONNECT connector flags), a delayed work will automatically be queued to periodically poll for changes. Connectors that can generate hotplug interrupts must be marked with the DRM_CONNECTOR_POLL_HPD flag instead, and their interrupt handler must call drm_helper_hpd_irq_event(). The function will queue a delayed work to check the state of all connectors, but no periodic polling will be done.

Connector Operations

Note

Unless otherwise state, all operations are mandatory.

DPMS

void (*dpms)(struct drm_connector *connector, int mode); The DPMS operation sets the power state of a connector. The mode argument is one of

  • DRM_MODE_DPMS_ON
  • DRM_MODE_DPMS_STANDBY
  • DRM_MODE_DPMS_SUSPEND
  • DRM_MODE_DPMS_OFF

In all but DPMS_ON mode the encoder to which the connector is attached should put the display in low-power mode by driving its signals appropriately. If more than one connector is attached to the encoder care should be taken not to change the power state of other displays as a side effect. Low-power mode should be propagated to the encoders and CRTCs when all related connectors are put in low-power mode.

Modes

int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); Fill the mode list with all supported modes for the connector. If the max_width and max_height arguments are non-zero, the implementation must ignore all modes wider than max_width or higher than max_height.

The connector must also fill in this operation its display_info width_mm and height_mm fields with the connected display physical size in millimeters. The fields should be set to 0 if the value isn’t known or is not applicable (for instance for projector devices).

Connection Status

The connection status is updated through polling or hotplug events when supported (see ?). The status value is reported to userspace through ioctls and must not be used inside the driver, as it only gets initialized by a call to drm_mode_getconnector() from userspace.

enum drm_connector_status (*detect)(struct drm_connector *connector, bool force); Check to see if anything is attached to the connector. The force parameter is set to false whilst polling or to true when checking the connector due to user request. force can be used by the driver to avoid expensive, destructive operations during automated probing.

Return connector_status_connected if something is connected to the connector, connector_status_disconnected if nothing is connected and connector_status_unknown if the connection state isn’t known.

Drivers should only return connector_status_connected if the connection status has really been probed as connected. Connectors that can’t detect the connection status, or failed connection status probes, should return connector_status_unknown.

Cleanup

The DRM core manages its objects’ lifetime. When an object is not needed anymore the core calls its destroy function, which must clean up and free every resource allocated for the object. Every drm_*_init() call must be matched with a corresponding drm_*_cleanup() call to cleanup CRTCs (drm_crtc_cleanup()), planes (drm_plane_cleanup()), encoders (drm_encoder_cleanup()) and connectors (drm_connector_cleanup()). Furthermore, connectors that have been added to sysfs must be removed by a call to drm_connector_unregister() before calling drm_connector_cleanup().

Connectors state change detection must be cleanup up with a call to drm_kms_helper_poll_fini().

Output discovery and initialization example

void intel_crt_init(struct drm_device *dev)
{
    struct drm_connector *connector;
    struct intel_output *intel_output;

    intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
    if (!intel_output)
        return;

    connector = &intel_output->base;
    drm_connector_init(dev, &intel_output->base,
               &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);

    drm_encoder_init(dev, &intel_output->enc, &intel_crt_enc_funcs,
             DRM_MODE_ENCODER_DAC);

    drm_mode_connector_attach_encoder(&intel_output->base,
                      &intel_output->enc);

    /* Set up the DDC bus. */
    intel_output->ddc_bus = intel_i2c_create(dev, GPIOA, "CRTDDC_A");
    if (!intel_output->ddc_bus) {
        dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
               "failed.\n");
        return;
    }

    intel_output->type = INTEL_OUTPUT_ANALOG;
    connector->interlace_allowed = 0;
    connector->doublescan_allowed = 0;

    drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs);
    drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);

    drm_connector_register(connector);
}

In the example above (taken from the i915 driver), a CRTC, connector and encoder combination is created. A device-specific i2c bus is also created for fetching EDID data and performing monitor detection. Once the process is complete, the new connector is registered with sysfs to make its properties available to applications.

KMS API Functions

const char * drm_get_connector_status_name(enum drm_connector_status status)

return a string for connector status

Parameters

enum drm_connector_status status
connector status to compute name of

Description

In contrast to the other drm_get_*_name functions this one here returns a const pointer and hence is threadsafe.

const char * drm_get_subpixel_order_name(enum subpixel_order order)

return a string for a given subpixel enum

Parameters

enum subpixel_order order
enum of subpixel_order

Description

Note you could abuse this and return something out of bounds, but that would be a caller error. No unscrubbed user data should make it here.

const char * drm_get_format_name(uint32_t format)

return a string for drm fourcc format

Parameters

uint32_t format
format to compute name of

Description

Note that the buffer used by this function is globally shared and owned by the function itself.

FIXME: This isn’t really multithreading safe.

struct drm_mode_object * drm_mode_object_find(struct drm_device * dev, uint32_t id, uint32_t type)

look up a drm object with static lifetime

Parameters

struct drm_device * dev
drm device
uint32_t id
id of the mode object
uint32_t type
type of the mode object

Description

This function is used to look up a modeset object. It will acquire a reference for reference counted objects. This reference must be dropped again by callind drm_mode_object_unreference().

void drm_mode_object_unreference(struct drm_mode_object * obj)

decr the object refcnt

Parameters

struct drm_mode_object * obj
mode_object

Description

This functions decrements the object’s refcount if it is a refcounted modeset object. It is a no-op on any other object. This is used to drop references acquired with drm_mode_object_reference().

void drm_mode_object_reference(struct drm_mode_object * obj)

incr the object refcnt

Parameters

struct drm_mode_object * obj
mode_object

Description

This functions increments the object’s refcount if it is a refcounted modeset object. It is a no-op on any other object. References should be dropped again by calling drm_mode_object_unreference().

int drm_framebuffer_init(struct drm_device * dev, struct drm_framebuffer * fb, const struct drm_framebuffer_funcs * funcs)

initialize a framebuffer

Parameters

struct drm_device * dev
DRM device
struct drm_framebuffer * fb
framebuffer to be initialized
const struct drm_framebuffer_funcs * funcs
... with these functions

Description

Allocates an ID for the framebuffer’s parent mode object, sets its mode functions & device file and adds it to the master fd list.

IMPORTANT: This functions publishes the fb and makes it available for concurrent access by other users. Which means by this point the fb _must_ be fully set up - since all the fb attributes are invariant over its lifetime, no further locking but only correct reference counting is required.

Return

Zero on success, error code on failure.

struct drm_framebuffer * drm_framebuffer_lookup(struct drm_device * dev, uint32_t id)

look up a drm framebuffer and grab a reference

Parameters

struct drm_device * dev
drm device
uint32_t id
id of the fb object

Description

If successful, this grabs an additional reference to the framebuffer - callers need to make sure to eventually unreference the returned framebuffer again, using drm_framebuffer_unreference.

void drm_framebuffer_unregister_private(struct drm_framebuffer * fb)

unregister a private fb from the lookup idr

Parameters

struct drm_framebuffer * fb
fb to unregister

Description

Drivers need to call this when cleaning up driver-private framebuffers, e.g. those used for fbdev. Note that the caller must hold a reference of it’s own, i.e. the object may not be destroyed through this call (since it’ll lead to a locking inversion).

void drm_framebuffer_cleanup(struct drm_framebuffer * fb)

remove a framebuffer object

Parameters

struct drm_framebuffer * fb
framebuffer to remove

Description

Cleanup framebuffer. This function is intended to be used from the drivers ->destroy callback. It can also be used to clean up driver private

framebuffers embedded into a larger structure.

Note that this function does not remove the fb from active usuage - if it is still used anywhere, hilarity can ensue since userspace could call getfb on the id and get back -EINVAL. Obviously no concern at driver unload time.

Also, the framebuffer will not be removed from the lookup idr - for user-created framebuffers this will happen in in the rmfb ioctl. For driver-private objects (e.g. for fbdev) drivers need to explicitly call drm_framebuffer_unregister_private.

void drm_framebuffer_remove(struct drm_framebuffer * fb)

remove and unreference a framebuffer object

Parameters

struct drm_framebuffer * fb
framebuffer to remove

Description

Scans all the CRTCs and planes in dev‘s mode_config. If they’re using fb, removes it, setting it to NULL. Then drops the reference to the passed-in framebuffer. Might take the modeset locks.

Note that this function optimizes the cleanup away if the caller holds the last reference to the framebuffer. It is also guaranteed to not take the modeset locks in this case.

int drm_crtc_init_with_planes(struct drm_device * dev, struct drm_crtc * crtc, struct drm_plane * primary, struct drm_plane * cursor, const struct drm_crtc_funcs * funcs, const char * name, ...)

Initialise a new CRTC object with specified primary and cursor planes.

Parameters

struct drm_device * dev
DRM device
struct drm_crtc * crtc
CRTC object to init
struct drm_plane * primary
Primary plane for CRTC
struct drm_plane * cursor
Cursor plane for CRTC
const struct drm_crtc_funcs * funcs
callbacks for the new CRTC
const char * name
printf style format string for the CRTC name, or NULL for default name
...
variable arguments

Description

Inits a new object created as base part of a driver crtc object.

Return

Zero on success, error code on failure.

void drm_crtc_cleanup(struct drm_crtc * crtc)

Clean up the core crtc usage

Parameters

struct drm_crtc * crtc
CRTC to cleanup

Description

This function cleans up crtc and removes it from the DRM mode setting core. Note that the function does not free the crtc structure itself, this is the responsibility of the caller.

unsigned int drm_crtc_index(struct drm_crtc * crtc)

find the index of a registered CRTC

Parameters

struct drm_crtc * crtc
CRTC to find index for

Description

Given a registered CRTC, return the index of that CRTC within a DRM device’s list of CRTCs.

int drm_display_info_set_bus_formats(struct drm_display_info * info, const u32 * formats, unsigned int num_formats)

set the supported bus formats

Parameters

struct drm_display_info * info
display info to store bus formats in
const u32 * formats
array containing the supported bus formats
unsigned int num_formats
the number of entries in the fmts array

Description

Store the supported bus formats in display info structure. See MEDIA_BUS_FMT_* definitions in include/uapi/linux/media-bus-format.h for a full list of available formats.

int drm_connector_init(struct drm_device * dev, struct drm_connector * connector, const struct drm_connector_funcs * funcs, int connector_type)

Init a preallocated connector

Parameters

struct drm_device * dev
DRM device
struct drm_connector * connector
the connector to init
const struct drm_connector_funcs * funcs
callbacks for this connector
int connector_type
user visible type of the connector

Description

Initialises a preallocated connector. Connectors should be subclassed as part of driver connector objects.

Return

Zero on success, error code on failure.

void drm_connector_cleanup(struct drm_connector * connector)

cleans up an initialised connector

Parameters

struct drm_connector * connector
connector to cleanup

Description

Cleans up the connector but doesn’t free the object.

int drm_connector_register(struct drm_connector * connector)

register a connector

Parameters

struct drm_connector * connector
the connector to register

Description

Register userspace interfaces for a connector

Return

Zero on success, error code on failure.

void drm_connector_unregister(struct drm_connector * connector)

unregister a connector

Parameters

struct drm_connector * connector
the connector to unregister

Description

Unregister userspace interfaces for a connector

int drm_connector_register_all(struct drm_device * dev)

register all connectors

Parameters

struct drm_device * dev
drm device

Description

This function registers all connectors in sysfs and other places so that userspace can start to access them. Drivers can call it after calling drm_dev_register() to complete the device registration, if they don’t call drm_connector_register() on each connector individually.

When a device is unplugged and should be removed from userspace access, call drm_connector_unregister_all(), which is the inverse of this function.

Return

Zero on success, error code on failure.

void drm_connector_unregister_all(struct drm_device * dev)

unregister connector userspace interfaces

Parameters

struct drm_device * dev
drm device

Description

This functions unregisters all connectors from sysfs and other places so that userspace can no longer access them. Drivers should call this as the first step tearing down the device instace, or when the underlying physical device disappeared (e.g. USB unplug), right before calling drm_dev_unregister().

int drm_encoder_init(struct drm_device * dev, struct drm_encoder * encoder, const struct drm_encoder_funcs * funcs, int encoder_type, const char * name, ...)

Init a preallocated encoder

Parameters

struct drm_device * dev
drm device
struct drm_encoder * encoder
the encoder to init
const struct drm_encoder_funcs * funcs
callbacks for this encoder
int encoder_type
user visible type of the encoder
const char * name
printf style format string for the encoder name, or NULL for default name
...
variable arguments

Description

Initialises a preallocated encoder. Encoder should be subclassed as part of driver encoder objects.

Return

Zero on success, error code on failure.

unsigned int drm_encoder_index(struct drm_encoder * encoder)

find the index of a registered encoder

Parameters

struct drm_encoder * encoder
encoder to find index for

Description

Given a registered encoder, return the index of that encoder within a DRM device’s list of encoders.

void drm_encoder_cleanup(struct drm_encoder * encoder)

cleans up an initialised encoder

Parameters

struct drm_encoder * encoder
encoder to cleanup

Description

Cleans up the encoder but doesn’t free the object.

int drm_universal_plane_init(struct drm_device * dev, struct drm_plane * plane, unsigned long possible_crtcs, const struct drm_plane_funcs * funcs, const uint32_t * formats, unsigned int format_count, enum drm_plane_type type, const char * name, ...)

Initialize a new universal plane object

Parameters

struct drm_device * dev
DRM device
struct drm_plane * plane
plane object to init
unsigned long possible_crtcs
bitmask of possible CRTCs
const struct drm_plane_funcs * funcs
callbacks for the new plane
const uint32_t * formats
array of supported formats (``DRM_FORMAT_``*)
unsigned int format_count
number of elements in formats
enum drm_plane_type type
type of plane (overlay, primary, cursor)
const char * name
printf style format string for the plane name, or NULL for default name
...
variable arguments

Description

Initializes a plane object of type type.

Return

Zero on success, error code on failure.

int drm_plane_init(struct drm_device * dev, struct drm_plane * plane, unsigned long possible_crtcs, const struct drm_plane_funcs * funcs, const uint32_t * formats, unsigned int format_count, bool is_primary)

Initialize a legacy plane

Parameters

struct drm_device * dev
DRM device
struct drm_plane * plane
plane object to init
unsigned long possible_crtcs
bitmask of possible CRTCs
const struct drm_plane_funcs * funcs
callbacks for the new plane
const uint32_t * formats
array of supported formats (``DRM_FORMAT_``*)
unsigned int format_count
number of elements in formats
bool is_primary
plane type (primary vs overlay)

Description

Legacy API to initialize a DRM plane.

New drivers should call drm_universal_plane_init() instead.

Return

Zero on success, error code on failure.

void drm_plane_cleanup(struct drm_plane * plane)

Clean up the core plane usage

Parameters

struct drm_plane * plane
plane to cleanup

Description

This function cleans up plane and removes it from the DRM mode setting core. Note that the function does not free the plane structure itself, this is the responsibility of the caller.

unsigned int drm_plane_index(struct drm_plane * plane)

find the index of a registered plane

Parameters

struct drm_plane * plane
plane to find index for

Description

Given a registered plane, return the index of that CRTC within a DRM device’s list of planes.

struct drm_plane * drm_plane_from_index(struct drm_device * dev, int idx)

find the registered plane at an index

Parameters

struct drm_device * dev
DRM device
int idx
index of registered plane to find for

Description

Given a plane index, return the registered plane from DRM device’s list of planes with matching index.

void drm_plane_force_disable(struct drm_plane * plane)

Forcibly disable a plane

Parameters

struct drm_plane * plane
plane to disable

Description

Forces the plane to be disabled.

Used when the plane’s current framebuffer is destroyed, and when restoring fbdev mode.

int drm_mode_create_dvi_i_properties(struct drm_device * dev)

create DVI-I specific connector properties

Parameters

struct drm_device * dev
DRM device

Description

Called by a driver the first time a DVI-I connector is made.

int drm_mode_create_tv_properties(struct drm_device * dev, unsigned int num_modes, const char *const modes[])

create TV specific connector properties

Parameters

struct drm_device * dev
DRM device
unsigned int num_modes
number of different TV formats (modes) supported
const char *const modes[]
undescribed

Description

Called by a driver’s TV initialization routine, this function creates the TV specific connector properties for a given device. Caller is responsible for allocating a list of format names and passing them to this routine.

int drm_mode_create_scaling_mode_property(struct drm_device * dev)

create scaling mode property

Parameters

struct drm_device * dev
DRM device

Description

Called by a driver the first time it’s needed, must be attached to desired connectors.

int drm_mode_create_aspect_ratio_property(struct drm_device * dev)

create aspect ratio property

Parameters

struct drm_device * dev
DRM device

Description

Called by a driver the first time it’s needed, must be attached to desired connectors.

Return

Zero on success, negative errno on failure.

int drm_mode_create_dirty_info_property(struct drm_device * dev)

create dirty property

Parameters

struct drm_device * dev
DRM device

Description

Called by a driver the first time it’s needed, must be attached to desired connectors.

int drm_mode_create_suggested_offset_properties(struct drm_device * dev)

create suggests offset properties

Parameters

struct drm_device * dev
DRM device

Description

Create the the suggested x/y offset property for connectors.

int drm_mode_set_config_internal(struct drm_mode_set * set)

helper to call ->set_config

Parameters

struct drm_mode_set * set
modeset config to set

Description

This is a little helper to wrap internal calls to the ->set_config driver interface. The only thing it adds is correct refcounting dance.

Return

Zero on success, negative errno on failure.

void drm_crtc_get_hv_timing(const struct drm_display_mode * mode, int * hdisplay, int * vdisplay)

Fetches hdisplay/vdisplay for given mode

Parameters

const struct drm_display_mode * mode
mode to query
int * hdisplay
hdisplay value to fill in
int * vdisplay
vdisplay value to fill in

Description

The vdisplay value will be doubled if the specified mode is a stereo mode of the appropriate layout.

int drm_crtc_check_viewport(const struct drm_crtc * crtc, int x, int y, const struct drm_display_mode * mode, const struct drm_framebuffer * fb)

Checks that a framebuffer is big enough for the CRTC viewport

Parameters

const struct drm_crtc * crtc
CRTC that framebuffer will be displayed on
int x
x panning
int y
y panning
const struct drm_display_mode * mode
mode that framebuffer will be displayed under
const struct drm_framebuffer * fb
framebuffer to check size of
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)

compute drm fourcc code from legacy description

Parameters

uint32_t bpp
bits per pixels
uint32_t depth
bit depth per pixel

Description

Computes a drm fourcc pixel format code for the given bpp/depth values. Useful in fbdev emulation code, since that deals in those values.

struct drm_property * drm_property_create(struct drm_device * dev, int flags, const char * name, int num_values)

create a new property type

Parameters

struct drm_device * dev
drm device
int flags
flags specifying the property type
const char * name
name of the property
int num_values
number of pre-defined values

Description

This creates a new generic drm property which can then be attached to a drm object with drm_object_attach_property. The returned property object must be freed with drm_property_destroy.

Note that the DRM core keeps a per-device list of properties and that, if drm_mode_config_cleanup() is called, it will destroy all properties created by the driver.

Return

A pointer to the newly created property on success, NULL on failure.

struct drm_property * drm_property_create_enum(struct drm_device * dev, int flags, const char * name, const struct drm_prop_enum_list * props, int num_values)

create a new enumeration property type

Parameters

struct drm_device * dev
drm device
int flags
flags specifying the property type
const char * name
name of the property
const struct drm_prop_enum_list * props
enumeration lists with property values
int num_values
number of pre-defined values

Description

This creates a new generic drm property which can then be attached to a drm object with drm_object_attach_property. The returned property object must be freed with drm_property_destroy.

Userspace is only allowed to set one of the predefined values for enumeration properties.

Return

A pointer to the newly created property on success, NULL on failure.

struct drm_property * drm_property_create_bitmask(struct drm_device * dev, int flags, const char * name, const struct drm_prop_enum_list * props, int num_props, uint64_t supported_bits)

create a new bitmask property type

Parameters

struct drm_device * dev
drm device
int flags
flags specifying the property type
const char * name
name of the property
const struct drm_prop_enum_list * props
enumeration lists with property bitflags
int num_props
size of the props array
uint64_t supported_bits
bitmask of all supported enumeration values

Description

This creates a new bitmask drm property which can then be attached to a drm object with drm_object_attach_property. The returned property object must be freed with drm_property_destroy.

Compared to plain enumeration properties userspace is allowed to set any or’ed together combination of the predefined property bitflag values

Return

A pointer to the newly created property on success, NULL on failure.

struct drm_property * drm_property_create_range(struct drm_device * dev, int flags, const char * name, uint64_t min, uint64_t max)

create a new unsigned ranged property type

Parameters

struct drm_device * dev
drm device
int flags
flags specifying the property type
const char * name
name of the property
uint64_t min
minimum value of the property
uint64_t max
maximum value of the property

Description

This creates a new generic drm property which can then be attached to a drm object with drm_object_attach_property. The returned property object must be freed with drm_property_destroy.

Userspace is allowed to set any unsigned integer value in the (min, max) range inclusive.

Return

A pointer to the newly created property on success, NULL on failure.

struct drm_property * drm_property_create_signed_range(struct drm_device * dev, int flags, const char * name, int64_t min, int64_t max)

create a new signed ranged property type

Parameters

struct drm_device * dev
drm device
int flags
flags specifying the property type
const char * name
name of the property
int64_t min
minimum value of the property
int64_t max
maximum value of the property

Description

This creates a new generic drm property which can then be attached to a drm object with drm_object_attach_property. The returned property object must be freed with drm_property_destroy.

Userspace is allowed to set any signed integer value in the (min, max) range inclusive.

Return

A pointer to the newly created property on success, NULL on failure.

struct drm_property * drm_property_create_object(struct drm_device * dev, int flags, const char * name, uint32_t type)

create a new object property type

Parameters

struct drm_device * dev
drm device
int flags
flags specifying the property type
const char * name
name of the property
uint32_t type
object type from DRM_MODE_OBJECT_* defines

Description

This creates a new generic drm property which can then be attached to a drm object with drm_object_attach_property. The returned property object must be freed with drm_property_destroy.

Userspace is only allowed to set this to any property value of the given type. Only useful for atomic properties, which is enforced.

Return

A pointer to the newly created property on success, NULL on failure.

struct drm_property * drm_property_create_bool(struct drm_device * dev, int flags, const char * name)

create a new boolean property type

Parameters

struct drm_device * dev
drm device
int flags
flags specifying the property type
const char * name
name of the property

Description

This creates a new generic drm property which can then be attached to a drm object with drm_object_attach_property. The returned property object must be freed with drm_property_destroy.

This is implemented as a ranged property with only {0, 1} as valid values.

Return

A pointer to the newly created property on success, NULL on failure.

int drm_property_add_enum(struct drm_property * property, int index, uint64_t value, const char * name)

add a possible value to an enumeration property

Parameters

struct drm_property * property
enumeration property to change
int index
index of the new enumeration
uint64_t value
value of the new enumeration
const char * name
symbolic name of the new enumeration

Description

This functions adds enumerations to a property.

It’s use is deprecated, drivers should use one of the more specific helpers to directly create the property with all enumerations already attached.

Return

Zero on success, error code on failure.

void drm_property_destroy(struct drm_device * dev, struct drm_property * property)

destroy a drm property

Parameters

struct drm_device * dev
drm device
struct drm_property * property
property to destry

Description

This function frees a property including any attached resources like enumeration values.

void drm_object_attach_property(struct drm_mode_object * obj, struct drm_property * property, uint64_t init_val)

attach a property to a modeset object

Parameters

struct drm_mode_object * obj
drm modeset object
struct drm_property * property
property to attach
uint64_t init_val
initial value of the property

Description

This attaches the given property to the modeset object with the given initial value. Currently this function cannot fail since the properties are stored in a statically sized array.

int drm_object_property_set_value(struct drm_mode_object * obj, struct drm_property * property, uint64_t val)

set the value of a property

Parameters

struct drm_mode_object * obj
drm mode object to set property value for
struct drm_property * property
property to set
uint64_t val
value the property should be set to

Description

This functions sets a given property on a given object. This function only changes the software state of the property, it does not call into the driver’s ->set_property callback.

Return

Zero on success, error code on failure.

int drm_object_property_get_value(struct drm_mode_object * obj, struct drm_property * property, uint64_t * val)

retrieve the value of a property

Parameters

struct drm_mode_object * obj
drm mode object to get property value from
struct drm_property * property
property to retrieve
uint64_t * val
storage for the property value

Description

This function retrieves the softare state of the given property for the given property. Since there is no driver callback to retrieve the current property value this might be out of sync with the hardware, depending upon the driver and property.

Return

Zero on success, error code on failure.

struct drm_property_blob * drm_property_create_blob(struct drm_device * dev, size_t length, const void * data)

Create new blob property

Parameters

struct drm_device * dev
DRM device to create property for
size_t length
Length to allocate for blob data
const void * data
If specified, copies data into blob

Description

Creates a new blob property for a specified DRM device, optionally copying data.

Return

New blob property with a single reference on success, or an ERR_PTR value on failure.

void drm_property_unreference_blob(struct drm_property_blob * blob)

Unreference a blob property

Parameters

struct drm_property_blob * blob
Pointer to blob property

Description

Drop a reference on a blob property. May free the object.

struct drm_property_blob * drm_property_reference_blob(struct drm_property_blob * blob)

Take a reference on an existing property

Parameters

struct drm_property_blob * blob
Pointer to blob property

Description

Take a new reference on an existing blob property.

struct drm_property_blob * drm_property_lookup_blob(struct drm_device * dev, uint32_t id)

look up a blob property and take a reference

Parameters

struct drm_device * dev
drm device
uint32_t id
id of the blob property

Description

If successful, this takes an additional reference to the blob property. callers need to make sure to eventually unreference the returned property again, using drm_property_unreference_blob.

int drm_mode_connector_set_path_property(struct drm_connector * connector, const char * path)

set tile property on connector

Parameters

struct drm_connector * connector
connector to set property on.
const char * path
path to use for property; must not be NULL.

Description

This creates a property to expose to userspace to specify a connector path. This is mainly used for DisplayPort MST where connectors have a topology and we want to allow userspace to give them more meaningful names.

Return

Zero on success, negative errno on failure.

int drm_mode_connector_set_tile_property(struct drm_connector * connector)

set tile property on connector

Parameters

struct drm_connector * connector
connector to set property on.

Description

This looks up the tile information for a connector, and creates a property for userspace to parse if it exists. The property is of the form of 8 integers using ‘:’ as a separator.

Return

Zero on success, errno on failure.

int drm_mode_connector_update_edid_property(struct drm_connector * connector, const struct edid * edid)

update the edid property of a connector

Parameters

struct drm_connector * connector
drm connector
const struct edid * edid
new value of the edid property

Description

This function creates a new blob modeset object and assigns its id to the connector’s edid property.

Return

Zero on success, negative errno on failure.

int drm_mode_plane_set_obj_prop(struct drm_plane * plane, struct drm_property * property, uint64_t value)

set the value of a property

Parameters

struct drm_plane * plane
drm plane object to set property value for
struct drm_property * property
property to set
uint64_t value
value the property should be set to

Description

This functions sets a given property on a given plane object. This function calls the driver’s ->set_property callback and changes the software state of the property if the callback succeeds.

Return

Zero on success, error code on failure.

int drm_mode_connector_attach_encoder(struct drm_connector * connector, struct drm_encoder * encoder)

attach a connector to an encoder

Parameters

struct drm_connector * connector
connector to attach
struct drm_encoder * encoder
encoder to attach connector to

Description

This function links up a connector to an encoder. Note that the routing restrictions between encoders and crtcs are exposed to userspace through the possible_clones and possible_crtcs bitmasks.

Return

Zero on success, negative errno on failure.

int drm_mode_crtc_set_gamma_size(struct drm_crtc * crtc, int gamma_size)

set the gamma table size

Parameters

struct drm_crtc * crtc
CRTC to set the gamma table size for
int gamma_size
size of the gamma table

Description

Drivers which support gamma tables should set this to the supported gamma table size when initializing the CRTC. Currently the drm core only supports a fixed gamma table size.

Return

Zero on success, negative errno on failure.

void drm_mode_config_reset(struct drm_device * dev)

call ->reset callbacks

Parameters

struct drm_device * dev
drm device

Description

This functions calls all the crtc’s, encoder’s and connector’s ->reset callback. Drivers can use this in e.g. their driver load or resume code to reset hardware and software state.

void drm_fb_get_bpp_depth(uint32_t format, unsigned int * depth, int * bpp)

get the bpp/depth values for format

Parameters

uint32_t format
pixel format (DRM_FORMAT_*)
unsigned int * depth
storage for the depth value
int * bpp
storage for the bpp value

Description

This only supports RGB formats here for compat with code that doesn’t use pixel formats directly yet.

int drm_format_num_planes(uint32_t format)

get the number of planes for format

Parameters

uint32_t format
pixel format (DRM_FORMAT_*)

Return

The number of planes used by the specified pixel format.

int drm_format_plane_cpp(uint32_t format, int plane)

determine the bytes per pixel value

Parameters

uint32_t format
pixel format (DRM_FORMAT_*)
int plane
plane index

Return

The bytes per pixel value for the specified plane.

int drm_format_horz_chroma_subsampling(uint32_t format)

get the horizontal chroma subsampling factor

Parameters

uint32_t format
pixel format (DRM_FORMAT_*)

Return

The horizontal chroma subsampling factor for the specified pixel format.

int drm_format_vert_chroma_subsampling(uint32_t format)

get the vertical chroma subsampling factor

Parameters

uint32_t format
pixel format (DRM_FORMAT_*)

Return

The vertical chroma subsampling factor for the specified pixel format.

int drm_format_plane_width(int width, uint32_t format, int plane)

width of the plane given the first plane

Parameters

int width
width of the first plane
uint32_t format
pixel format
int plane
plane index

Return

The width of plane, given that the width of the first plane is width.

int drm_format_plane_height(int height, uint32_t format, int plane)

height of the plane given the first plane

Parameters

int height
height of the first plane
uint32_t format
pixel format
int plane
plane index

Return

The height of plane, given that the height of the first plane is height.

unsigned int drm_rotation_simplify(unsigned int rotation, unsigned int supported_rotations)

Try to simplify the rotation

Parameters

unsigned int rotation
Rotation to be simplified
unsigned int supported_rotations
Supported rotations

Description

Attempt to simplify the rotation to a form that is supported. Eg. if the hardware supports everything except DRM_REFLECT_X one could call this function like this:

drm_rotation_simplify(rotation, BIT(DRM_ROTATE_0) |
BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_180) | BIT(DRM_ROTATE_270) | BIT(DRM_REFLECT_Y));

to eliminate the DRM_ROTATE_X flag. Depending on what kind of transforms the hardware supports, this function may not be able to produce a supported transform, so the caller should check the result afterwards.

void drm_mode_config_init(struct drm_device * dev)

initialize DRM mode_configuration structure

Parameters

struct drm_device * dev
DRM device

Description

Initialize dev‘s mode_config structure, used for tracking the graphics configuration of dev.

Since this initializes the modeset locks, no locking is possible. Which is no problem, since this should happen single threaded at init time. It is the driver’s problem to ensure this guarantee.

void drm_mode_config_cleanup(struct drm_device * dev)

free up DRM mode_config info

Parameters

struct drm_device * dev
DRM device

Description

Free up all the connectors and CRTCs associated with this DRM device, then free up the framebuffers and associated buffer objects.

Note that since this /should/ happen single-threaded at driver/device teardown time, no locking is required. It’s the driver’s job to ensure that this guarantee actually holds true.

FIXME: cleanup any dangling user buffer objects too

struct drm_tile_group * drm_mode_get_tile_group(struct drm_device * dev, char topology[8])

get a reference to an existing tile group

Parameters

struct drm_device * dev
DRM device
char topology[8]
undescribed

Description

Use the unique bytes to get a reference to an existing tile group.

Return

tile group or NULL if not found.

struct drm_tile_group * drm_mode_create_tile_group(struct drm_device * dev, char topology[8])

create a tile group from a displayid description

Parameters

struct drm_device * dev
DRM device
char topology[8]
undescribed

Description

Create a tile group for the unique monitor, and get a unique identifier for the tile group.

Return

new tile group or error.

KMS Data Structures

struct drm_framebuffer_funcs

framebuffer hooks

Definition

struct drm_framebuffer_funcs {
  void (* destroy) (struct drm_framebuffer *framebuffer);
  int (* create_handle) (struct drm_framebuffer *fb,struct drm_file *file_priv,unsigned int *handle);
  int (* dirty) (struct drm_framebuffer *framebuffer,struct drm_file *file_priv, unsigned flags,unsigned color, struct drm_clip_rect *clips,unsigned num_clips);
};

Members

void (*)(struct drm_framebuffer *framebuffer) destroy
Clean up framebuffer resources, specifically also unreference the backing storage. The core guarantees to call this function for every framebuffer successfully created by ->:c:func:fb_create() in drm_mode_config_funcs. Drivers must also call drm_framebuffer_cleanup() to release DRM core resources for this framebuffer.
int (*)(struct drm_framebuffer *fb,struct drm_file *file_priv,unsigned int *handle) create_handle

Create a buffer handle in the driver-specific buffer manager (either GEM or TTM) valid for the passed-in struct drm_file. This is used by the core to implement the GETFB IOCTL, which returns (for sufficiently priviledged user) also a native buffer handle. This can be used for seamless transitions between modesetting clients by copying the current screen contents to a private buffer and blending between that and the new contents.

GEM based drivers should call drm_gem_handle_create() to create the handle.

RETURNS:

0 on success or a negative error code on failure.

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

Optional callback for the dirty fb IOCTL.

Userspace can notify the driver via this callback that an area of the framebuffer has changed and should be flushed to the display hardware. This can also be used internally, e.g. by the fbdev emulation, though that’s not the case currently.

See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd for more information as all the semantics and arguments have a one to one mapping on this function.

RETURNS:

0 on success or a negative error code on failure.

struct drm_crtc_state

mutable CRTC state

Definition

struct drm_crtc_state {
  struct drm_crtc * crtc;
  bool enable;
  bool active;
  bool planes_changed:1;
  bool mode_changed:1;
  bool active_changed:1;
  bool connectors_changed:1;
  bool color_mgmt_changed:1;
  u32 plane_mask;
  u32 connector_mask;
  u32 encoder_mask;
  u32 last_vblank_count;
  struct drm_display_mode adjusted_mode;
  struct drm_display_mode mode;
  struct drm_property_blob * degamma_lut;
  struct drm_property_blob * ctm;
  struct drm_property_blob * gamma_lut;
  struct drm_pending_vblank_event * event;
  struct drm_atomic_state * state;
};

Members

struct drm_crtc * crtc
backpointer to the CRTC
bool enable
whether the CRTC should be enabled, gates all other state
bool active
whether the CRTC is actively displaying (used for DPMS)
bool:1 planes_changed
planes on this crtc are updated
bool:1 mode_changed
crtc_state->mode or crtc_state->enable has been changed
bool:1 active_changed
crtc_state->active has been toggled.
bool:1 connectors_changed
connectors to this crtc have been updated
bool:1 color_mgmt_changed
color management properties have changed (degamma or gamma LUT or CSC matrix)
u32 plane_mask
bitmask of (1 << drm_plane_index(plane)) of attached planes
u32 connector_mask
bitmask of (1 << drm_connector_index(connector)) of attached connectors
u32 encoder_mask
bitmask of (1 << drm_encoder_index(encoder)) of attached encoders
u32 last_vblank_count
for helpers and drivers to capture the vblank of the update to ensure framebuffer cleanup isn’t done too early
struct drm_display_mode adjusted_mode
for use by helpers and drivers to compute adjusted mode timings
struct drm_display_mode mode
current mode timings
struct drm_property_blob * degamma_lut
Lookup table for converting framebuffer pixel data before apply the conversion matrix
struct drm_property_blob * ctm
Transformation matrix
struct drm_property_blob * gamma_lut
Lookup table for converting pixel data after the conversion matrix
struct drm_pending_vblank_event * event
optional pointer to a DRM event to signal upon completion of the state update
struct drm_atomic_state * state
backpointer to global drm_atomic_state

Description

Note that the distinction between enable and active is rather subtile: Flipping active while enable is set without changing anything else may never return in a failure from the ->atomic_check callback. Userspace assumes that a DPMS On will always succeed. In other words: enable controls resource assignment, active controls the actual hardware state.

struct drm_crtc_funcs

control CRTCs for a given device

Definition

struct drm_crtc_funcs {
  void (* reset) (struct drm_crtc *crtc);
  int (* cursor_set) (struct drm_crtc *crtc, struct drm_file *file_priv,uint32_t handle, uint32_t width, uint32_t height);
  int (* cursor_set2) (struct drm_crtc *crtc, struct drm_file *file_priv,uint32_t handle, uint32_t width, uint32_t height,int32_t hot_x, int32_t hot_y);
  int (* cursor_move) (struct drm_crtc *crtc, int x, int y);
  void (* gamma_set) (struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,uint32_t start, uint32_t size);
  void (* destroy) (struct drm_crtc *crtc);
  int (* set_config) (struct drm_mode_set *set);
  int (* page_flip) (struct drm_crtc *crtc,struct drm_framebuffer *fb,struct drm_pending_vblank_event *event,uint32_t flags);
  int (* set_property) (struct drm_crtc *crtc,struct drm_property *property, uint64_t val);
  struct drm_crtc_state *(* atomic_duplicate_state) (struct drm_crtc *crtc);
  void (* atomic_destroy_state) (struct drm_crtc *crtc,struct drm_crtc_state *state);
  int (* atomic_set_property) (struct drm_crtc *crtc,struct drm_crtc_state *state,struct drm_property *property,uint64_t val);
  int (* atomic_get_property) (struct drm_crtc *crtc,const struct drm_crtc_state *state,struct drm_property *property,uint64_t *val);
};

Members

void (*)(struct drm_crtc *crtc) reset

Reset CRTC hardware and software state to off. This function isn’t called by the core directly, only through drm_mode_config_reset(). It’s not a helper hook only for historical reasons.

Atomic drivers can use drm_atomic_helper_crtc_reset() to reset atomic state using this hook.

int (*)(struct drm_crtc *crtc, struct drm_file *file_priv,uint32_t handle, uint32_t width, uint32_t height) cursor_set

Update the cursor image. The cursor position is relative to the CRTC and can be partially or fully outside of the visible area.

Note that contrary to all other KMS functions the legacy cursor entry points don’t take a framebuffer object, but instead take directly a raw buffer object id from the driver’s buffer manager (which is either GEM or TTM for current drivers).

This entry point is deprecated, drivers should instead implement universal plane support and register a proper cursor plane using drm_crtc_init_with_planes().

This callback is optional

RETURNS:

0 on success or a negative error code on failure.

int (*)(struct drm_crtc *crtc, struct drm_file *file_priv,uint32_t handle, uint32_t width, uint32_t height,int32_t hot_x, int32_t hot_y) cursor_set2

Update the cursor image, including hotspot information. The hotspot must not affect the cursor position in CRTC coordinates, but is only meant as a hint for virtualized display hardware to coordinate the guests and hosts cursor position. The cursor hotspot is relative to the cursor image. Otherwise this works exactly like cursor_set.

This entry point is deprecated, drivers should instead implement universal plane support and register a proper cursor plane using drm_crtc_init_with_planes().

This callback is optional.

RETURNS:

0 on success or a negative error code on failure.

int (*)(struct drm_crtc *crtc, int x, int y) cursor_move

Update the cursor position. The cursor does not need to be visible when this hook is called.

This entry point is deprecated, drivers should instead implement universal plane support and register a proper cursor plane using drm_crtc_init_with_planes().

This callback is optional.

RETURNS:

0 on success or a negative error code on failure.

void (*)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,uint32_t start, uint32_t size) gamma_set

Set gamma on the CRTC.

This callback is optional.

NOTE:

Drivers that support gamma tables and also fbdev emulation through the provided helper library need to take care to fill out the gamma hooks for both. Currently there’s a bit an unfortunate duplication going on, which should eventually be unified to just one set of hooks.

void (*)(struct drm_crtc *crtc) destroy
Clean up plane resources. This is only called at driver unload time through drm_mode_config_cleanup() since a CRTC cannot be hotplugged in DRM.
int (*)(struct drm_mode_set *set) set_config

This is the main legacy entry point to change the modeset state on a CRTC. All the details of the desired configuration are passed in a struct drm_mode_set - see there for details.

Drivers implementing atomic modeset should use drm_atomic_helper_set_config() to implement this hook.

RETURNS:

0 on success or a negative error code on failure.

int (*)(struct drm_crtc *crtc,struct drm_framebuffer *fb,struct drm_pending_vblank_event *event,uint32_t flags) page_flip

Legacy entry point to schedule a flip to the given framebuffer.

Page flipping is a synchronization mechanism that replaces the frame buffer being scanned out by the CRTC with a new frame buffer during vertical blanking, avoiding tearing (except when requested otherwise through the DRM_MODE_PAGE_FLIP_ASYNC flag). When an application requests a page flip the DRM core verifies that the new frame buffer is large enough to be scanned out by the CRTC in the currently configured mode and then calls the CRTC ->:c:func:page_flip() operation with a pointer to the new frame buffer.

The driver must wait for any pending rendering to the new framebuffer to complete before executing the flip. It should also wait for any pending rendering from other drivers if the underlying buffer is a shared dma-buf.

An application can request to be notified when the page flip has completed. The drm core will supply a struct drm_event in the event parameter in this case. This can be handled by the drm_crtc_send_vblank_event() function, which the driver should call on the provided event upon completion of the flip. Note that if the driver supports vblank signalling and timestamping the vblank counters and timestamps must agree with the ones returned from page flip events. With the current vblank helper infrastructure this can be achieved by holding a vblank reference while the page flip is pending, acquired through drm_crtc_vblank_get() and released with drm_crtc_vblank_put(). Drivers are free to implement their own vblank counter and timestamp tracking though, e.g. if they have accurate timestamp registers in hardware.

FIXME:

Up to that point drivers need to manage events themselves and can use even->base.list freely for that. Specifically they need to ensure that they don’t send out page flip (or vblank) events for which the corresponding drm file has been closed already. The drm core unfortunately does not (yet) take care of that. Therefore drivers currently must clean up and release pending events in their ->preclose driver function.

This callback is optional.

NOTE:

Very early versions of the KMS ABI mandated that the driver must block (but not reject) any rendering to the old framebuffer until the flip operation has completed and the old framebuffer is no longer visible. This requirement has been lifted, and userspace is instead expected to request delivery of an event and wait with recycling old buffers until such has been received.

RETURNS:

0 on success or a negative error code on failure. Note that if a ->:c:func:page_flip() operation is already pending the callback should return -EBUSY. Pageflips on a disabled CRTC (either by setting a NULL mode or just runtime disabled through DPMS respectively the new atomic “ACTIVE” state) should result in an -EINVAL error code. Note that drm_atomic_helper_page_flip() checks this already for atomic drivers.

int (*)(struct drm_crtc *crtc,struct drm_property *property, uint64_t val) set_property

This is the legacy entry point to update a property attached to the CRTC.

Drivers implementing atomic modeset should use drm_atomic_helper_crtc_set_property() to implement this hook.

This callback is optional if the driver does not support any legacy driver-private properties.

RETURNS:

0 on success or a negative error code on failure.

struct drm_crtc_state *(*)(struct drm_crtc *crtc) atomic_duplicate_state

Duplicate the current atomic state for this CRTC and return it. The core and helpers gurantee that any atomic state duplicated with this hook and still owned by the caller (i.e. not transferred to the driver by calling ->:c:func:atomic_commit() from struct drm_mode_config_funcs) will be cleaned up by calling the atomic_destroy_state hook in this structure.

Atomic drivers which don’t subclass struct drm_crtc should use drm_atomic_helper_crtc_duplicate_state(). Drivers that subclass the state structure to extend it with driver-private state should use __drm_atomic_helper_crtc_duplicate_state() to make sure shared state is duplicated in a consistent fashion across drivers.

It is an error to call this hook before crtc->state has been initialized correctly.

NOTE:

If the duplicate state references refcounted resources this hook must acquire a reference for each of them. The driver must release these references again in atomic_destroy_state.

RETURNS:

Duplicated atomic state or NULL when the allocation failed.

void (*)(struct drm_crtc *crtc,struct drm_crtc_state *state) atomic_destroy_state
Destroy a state duplicated with atomic_duplicate_state and release or unreference all resources it references
int (*)(struct drm_crtc *crtc,struct drm_crtc_state *state,struct drm_property *property,uint64_t val) atomic_set_property

Decode a driver-private property value and store the decoded value into the passed-in state structure. Since the atomic core decodes all standardized properties (even for extensions beyond the core set of properties which might not be implemented by all drivers) this requires drivers to subclass the state structure.

Such driver-private properties should really only be implemented for truly hardware/vendor specific state. Instead it is preferred to standardize atomic extension and decode the properties used to expose such an extension in the core.

Do not call this function directly, use drm_atomic_crtc_set_property() instead.

This callback is optional if the driver does not support any driver-private atomic properties.

NOTE:

This function is called in the state assembly phase of atomic modesets, which can be aborted for any reason (including on userspace’s request to just check whether a configuration would be possible). Drivers MUST NOT touch any persistent state (hardware or software) or data structures except the passed in state parameter.

Also since userspace controls in which order properties are set this function must not do any input validation (since the state update is incomplete and hence likely inconsistent). Instead any such input validation must be done in the various atomic_check callbacks.

RETURNS:

0 if the property has been found, -EINVAL if the property isn’t implemented by the driver (which should never happen, the core only asks for properties attached to this CRTC). No other validation is allowed by the driver. The core already checks that the property value is within the range (integer, valid enum value, ...) the driver set when registering the property.

int (*)(struct drm_crtc *crtc,const struct drm_crtc_state *state,struct drm_property *property,uint64_t *val) atomic_get_property

Reads out the decoded driver-private property. This is used to implement the GETCRTC IOCTL.

Do not call this function directly, use drm_atomic_crtc_get_property() instead.

This callback is optional if the driver does not support any driver-private atomic properties.

RETURNS:

0 on success, -EINVAL if the property isn’t implemented by the driver (which should never happen, the core only asks for properties attached to this CRTC).

Description

The drm_crtc_funcs structure is the central CRTC management structure in the DRM. Each CRTC controls one or more connectors (note that the name CRTC is simply historical, a CRTC may control LVDS, VGA, DVI, TV out, etc. connectors, not just CRTs).

Each driver is responsible for filling out this structure at startup time, in addition to providing other modesetting features, like i2c and DDC bus accessors.

struct drm_crtc

central CRTC control structure

Definition

struct drm_crtc {
  struct drm_device * dev;
  struct device_node * port;
  struct list_head head;
  struct drm_modeset_lock mutex;
  struct drm_mode_object base;
  struct drm_plane * primary;
  struct drm_plane * cursor;
  int cursor_x;
  int cursor_y;
  bool enabled;
  struct drm_display_mode mode;
  struct drm_display_mode hwmode;
  int x;
  int y;
  const struct drm_crtc_funcs * funcs;
  uint32_t gamma_size;
  uint16_t * gamma_store;
  const struct drm_crtc_helper_funcs * helper_private;
  struct drm_object_properties properties;
  struct drm_crtc_state * state;
  struct drm_modeset_acquire_ctx * acquire_ctx;
};

Members

struct drm_device * dev
parent DRM device
struct device_node * port
OF node used by drm_of_find_possible_crtcs()
struct list_head head
list management
struct drm_modeset_lock mutex
per-CRTC locking
struct drm_mode_object base
base KMS object for ID tracking etc.
struct drm_plane * primary
primary plane for this CRTC
struct drm_plane * cursor
cursor plane for this CRTC
int cursor_x
current x position of the cursor, used for universal cursor planes
int cursor_y
current y position of the cursor, used for universal cursor planes
bool enabled
is this CRTC enabled?
struct drm_display_mode mode
current mode timings
struct drm_display_mode hwmode
mode timings as programmed to hw regs
int x
x position on screen
int y
y position on screen
const struct drm_crtc_funcs * funcs
CRTC control functions
uint32_t gamma_size
size of gamma ramp
uint16_t * gamma_store
gamma ramp values
const struct drm_crtc_helper_funcs * helper_private
mid-layer private data
struct drm_object_properties properties
property tracking for this CRTC
struct drm_crtc_state * state
current atomic state for this CRTC
struct drm_modeset_acquire_ctx * acquire_ctx
per-CRTC implicit acquire context used by atomic drivers for legacy IOCTLs

Description

Each CRTC may have one or more connectors associated with it. This structure allows the CRTC to be controlled.

struct drm_connector_state

mutable connector state

Definition

struct drm_connector_state {
  struct drm_connector * connector;
  struct drm_crtc * crtc;
  struct drm_encoder * best_encoder;
  struct drm_atomic_state * state;
};

Members

struct drm_connector * connector
backpointer to the connector
struct drm_crtc * crtc
CRTC to connect connector to, NULL if disabled
struct drm_encoder * best_encoder
can be used by helpers and drivers to select the encoder
struct drm_atomic_state * state
backpointer to global drm_atomic_state
struct drm_connector_funcs

control connectors on a given device

Definition

struct drm_connector_funcs {
  int (* dpms) (struct drm_connector *connector, int mode);
  void (* reset) (struct drm_connector *connector);
  enum drm_connector_status (* detect) (struct drm_connector *connector,bool force);
  void (* force) (struct drm_connector *connector);
  int (* fill_modes) (struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
  int (* set_property) (struct drm_connector *connector, struct drm_property *property,uint64_t val);
  void (* destroy) (struct drm_connector *connector);
  struct drm_connector_state *(* atomic_duplicate_state) (struct drm_connector *connector);
  void (* atomic_destroy_state) (struct drm_connector *connector,struct drm_connector_state *state);
  int (* atomic_set_property) (struct drm_connector *connector,struct drm_connector_state *state,struct drm_property *property,uint64_t val);
  int (* atomic_get_property) (struct drm_connector *connector,const struct drm_connector_state *state,struct drm_property *property,uint64_t *val);
};

Members

int (*)(struct drm_connector *connector, int mode) dpms

Legacy entry point to set the per-connector DPMS state. Legacy DPMS is exposed as a standard property on the connector, but diverted to this callback in the drm core. Note that atomic drivers don’t implement the 4 level DPMS support on the connector any more, but instead only have an on/off “ACTIVE” property on the CRTC object.

Drivers implementing atomic modeset should use drm_atomic_helper_connector_dpms() to implement this hook.

RETURNS:

0 on success or a negative error code on failure.

void (*)(struct drm_connector *connector) reset

Reset connector hardware and software state to off. This function isn’t called by the core directly, only through drm_mode_config_reset(). It’s not a helper hook only for historical reasons.

Atomic drivers can use drm_atomic_helper_connector_reset() to reset atomic state using this hook.

enum drm_connector_status (*)(struct drm_connector *connector,bool force) detect

Check to see if anything is attached to the connector. The parameter force is set to false whilst polling, true when checking the connector due to a user request. force can be used by the driver to avoid expensive, destructive operations during automated probing.

FIXME:

Note that this hook is only called by the probe helper. It’s not in the helper library vtable purely for historical reasons. The only DRM core entry point to probe connector state is fill_modes.

RETURNS:

drm_connector_status indicating the connector’s status.

void (*)(struct drm_connector *connector) force

This function is called to update internal encoder state when the connector is forced to a certain state by userspace, either through the sysfs interfaces or on the kernel cmdline. In that case the detect callback isn’t called.

FIXME:

Note that this hook is only called by the probe helper. It’s not in the helper library vtable purely for historical reasons. The only DRM core entry point to probe connector state is fill_modes.

int (*)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height) fill_modes

Entry point for output detection and basic mode validation. The driver should reprobe the output if needed (e.g. when hotplug handling is unreliable), add all detected modes to connector->modes and filter out any the device can’t support in any configuration. It also needs to filter out any modes wider or higher than the parameters max_width and max_height indicate.

The drivers must also prune any modes no longer valid from connector->modes. Furthermore it must update connector->status and connector->edid. If no EDID has been received for this output connector->edid must be NULL.

Drivers using the probe helpers should use drm_helper_probe_single_connector_modes() or drm_helper_probe_single_connector_modes_nomerge() to implement this function.

RETURNS:

The number of modes detected and filled into connector->modes.

int (*)(struct drm_connector *connector, struct drm_property *property,uint64_t val) set_property

This is the legacy entry point to update a property attached to the connector.

Drivers implementing atomic modeset should use drm_atomic_helper_connector_set_property() to implement this hook.

This callback is optional if the driver does not support any legacy driver-private properties.

RETURNS:

0 on success or a negative error code on failure.

void (*)(struct drm_connector *connector) destroy
Clean up connector resources. This is called at driver unload time through drm_mode_config_cleanup(). It can also be called at runtime when a connector is being hot-unplugged for drivers that support connector hotplugging (e.g. DisplayPort MST).
struct drm_connector_state *(*)(struct drm_connector *connector) atomic_duplicate_state

Duplicate the current atomic state for this connector and return it. The core and helpers gurantee that any atomic state duplicated with this hook and still owned by the caller (i.e. not transferred to the driver by calling ->:c:func:atomic_commit() from struct drm_mode_config_funcs) will be cleaned up by calling the atomic_destroy_state hook in this structure.

Atomic drivers which don’t subclass struct drm_connector_state should use drm_atomic_helper_connector_duplicate_state(). Drivers that subclass the state structure to extend it with driver-private state should use __drm_atomic_helper_connector_duplicate_state() to make sure shared state is duplicated in a consistent fashion across drivers.

It is an error to call this hook before connector->state has been initialized correctly.

NOTE:

If the duplicate state references refcounted resources this hook must acquire a reference for each of them. The driver must release these references again in atomic_destroy_state.

RETURNS:

Duplicated atomic state or NULL when the allocation failed.

void (*)(struct drm_connector *connector,struct drm_connector_state *state) atomic_destroy_state
Destroy a state duplicated with atomic_duplicate_state and release or unreference all resources it references
int (*)(struct drm_connector *connector,struct drm_connector_state *state,struct drm_property *property,uint64_t val) atomic_set_property

Decode a driver-private property value and store the decoded value into the passed-in state structure. Since the atomic core decodes all standardized properties (even for extensions beyond the core set of properties which might not be implemented by all drivers) this requires drivers to subclass the state structure.

Such driver-private properties should really only be implemented for truly hardware/vendor specific state. Instead it is preferred to standardize atomic extension and decode the properties used to expose such an extension in the core.

Do not call this function directly, use drm_atomic_connector_set_property() instead.

This callback is optional if the driver does not support any driver-private atomic properties.

NOTE:

This function is called in the state assembly phase of atomic modesets, which can be aborted for any reason (including on userspace’s request to just check whether a configuration would be possible). Drivers MUST NOT touch any persistent state (hardware or software) or data structures except the passed in state parameter.

Also since userspace controls in which order properties are set this function must not do any input validation (since the state update is incomplete and hence likely inconsistent). Instead any such input validation must be done in the various atomic_check callbacks.

RETURNS:

0 if the property has been found, -EINVAL if the property isn’t implemented by the driver (which shouldn’t ever happen, the core only asks for properties attached to this connector). No other validation is allowed by the driver. The core already checks that the property value is within the range (integer, valid enum value, ...) the driver set when registering the property.

int (*)(struct drm_connector *connector,const struct drm_connector_state *state,struct drm_property *property,uint64_t *val) atomic_get_property

Reads out the decoded driver-private property. This is used to implement the GETCONNECTOR IOCTL.

Do not call this function directly, use drm_atomic_connector_get_property() instead.

This callback is optional if the driver does not support any driver-private atomic properties.

RETURNS:

0 on success, -EINVAL if the property isn’t implemented by the driver (which shouldn’t ever happen, the core only asks for properties attached to this connector).

Description

Each CRTC may have one or more connectors attached to it. The functions below allow the core DRM code to control connectors, enumerate available modes, etc.

struct drm_encoder_funcs

encoder controls

Definition

struct drm_encoder_funcs {
  void (* reset) (struct drm_encoder *encoder);
  void (* destroy) (struct drm_encoder *encoder);
};

Members

void (*)(struct drm_encoder *encoder) reset
Reset encoder hardware and software state to off. This function isn’t called by the core directly, only through drm_mode_config_reset(). It’s not a helper hook only for historical reasons.
void (*)(struct drm_encoder *encoder) destroy
Clean up encoder resources. This is only called at driver unload time through drm_mode_config_cleanup() since an encoder cannot be hotplugged in DRM.

Description

Encoders sit between CRTCs and connectors.

struct drm_encoder

central DRM encoder structure

Definition

struct drm_encoder {
  struct drm_device * dev;
  struct list_head head;
  struct drm_mode_object base;
  char * name;
  int encoder_type;
  uint32_t possible_crtcs;
  uint32_t possible_clones;
  struct drm_crtc * crtc;
  struct drm_bridge * bridge;
  const struct drm_encoder_funcs * funcs;
  const struct drm_encoder_helper_funcs * helper_private;
};

Members

struct drm_device * dev
parent DRM device
struct list_head head
list management
struct drm_mode_object base
base KMS object
char * name
encoder name
int encoder_type
one of the ``DRM_MODE_ENCODER_``<foo> types in drm_mode.h
uint32_t possible_crtcs
bitmask of potential CRTC bindings
uint32_t possible_clones
bitmask of potential sibling encoders for cloning
struct drm_crtc * crtc
currently bound CRTC
struct drm_bridge * bridge
bridge associated to the encoder
const struct drm_encoder_funcs * funcs
control functions
const struct drm_encoder_helper_funcs * helper_private
mid-layer private data

Description

CRTCs drive pixels to encoders, which convert them into signals appropriate for a given connector or set of connectors.

struct drm_connector

central DRM connector control structure

Definition

struct drm_connector {
  struct drm_device * dev;
  struct device * kdev;
  struct device_attribute * attr;
  struct list_head head;
  struct drm_mode_object base;
  char * name;
  int connector_type;
  int connector_type_id;
  bool interlace_allowed;
  bool doublescan_allowed;
  bool stereo_allowed;
  struct list_head modes;
  enum drm_connector_status status;
  struct list_head probed_modes;
  struct drm_display_info display_info;
  const struct drm_connector_funcs * funcs;
  struct drm_property_blob * edid_blob_ptr;
  struct drm_object_properties properties;
  struct drm_property_blob * path_blob_ptr;
  uint8_t polled;
  int dpms;
  const struct drm_connector_helper_funcs * helper_private;
  struct drm_cmdline_mode cmdline_mode;
  enum drm_connector_force force;
  bool override_edid;
  uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
  struct drm_encoder * encoder;
  uint8_t eld[MAX_ELD_BYTES];
  bool dvi_dual;
  int max_tmds_clock;
  bool latency_present[2];
  int video_latency[2];
  int audio_latency[2];
  int null_edid_counter;
  unsigned bad_edid_counter;
  bool edid_corrupt;
  struct dentry * debugfs_entry;
  struct drm_connector_state * state;
  bool has_tile;
  struct drm_tile_group * tile_group;
  bool tile_is_single_monitor;
  uint8_t num_h_tile;
  uint8_t num_v_tile;
  uint8_t tile_h_loc;
  uint8_t tile_v_loc;
  uint16_t tile_h_size;
  uint16_t tile_v_size;
};

Members

struct drm_device * dev
parent DRM device
struct device * kdev
kernel device for sysfs attributes
struct device_attribute * attr
sysfs attributes
struct list_head head
list management
struct drm_mode_object base
base KMS object
char * name
connector name
int connector_type
one of the ``DRM_MODE_CONNECTOR_``<foo> types from drm_mode.h
int connector_type_id
index into connector type enum
bool interlace_allowed
can this connector handle interlaced modes?
bool doublescan_allowed
can this connector handle doublescan?
bool stereo_allowed
can this connector handle stereo modes?
struct list_head modes
modes available on this connector (from fill_modes() + user)
enum drm_connector_status status
one of the drm_connector_status enums (connected, not, or unknown)
struct list_head probed_modes
list of modes derived directly from the display
struct drm_display_info display_info
information about attached display (e.g. from EDID)
const struct drm_connector_funcs * funcs
connector control functions
struct drm_property_blob * edid_blob_ptr
DRM property containing EDID if present
struct drm_object_properties properties
property tracking for this connector
struct drm_property_blob * path_blob_ptr
DRM blob property data for the DP MST path property
uint8_t polled
a ``DRM_CONNECTOR_POLL_``<foo> value for core driven polling
int dpms
current dpms state
const struct drm_connector_helper_funcs * helper_private
mid-layer private data
struct drm_cmdline_mode cmdline_mode
mode line parsed from the kernel cmdline for this connector
enum drm_connector_force force
a ``DRM_FORCE_``<foo> state for forced mode sets
bool override_edid
has the EDID been overwritten through debugfs for testing?
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]
valid encoders for this connector
struct drm_encoder * encoder
encoder driving this connector, if any
uint8_t eld[MAX_ELD_BYTES]
EDID-like data, if present
bool dvi_dual
dual link DVI, if found
int max_tmds_clock
max clock rate, if found
bool latency_present[2]
AV delay info from ELD, if found
int video_latency[2]
video latency info from ELD, if found
int audio_latency[2]
audio latency info from ELD, if found
int null_edid_counter
track sinks that give us all zeros for the EDID
unsigned bad_edid_counter
track sinks that give us an EDID with invalid checksum
bool edid_corrupt
indicates whether the last read EDID was corrupt
struct dentry * debugfs_entry
debugfs directory for this connector
struct drm_connector_state * state
current atomic state for this connector
bool has_tile
is this connector connected to a tiled monitor
struct drm_tile_group * tile_group
tile group for the connected monitor
bool tile_is_single_monitor
whether the tile is one monitor housing
uint8_t num_h_tile
number of horizontal tiles in the tile group
uint8_t num_v_tile
number of vertical tiles in the tile group
uint8_t tile_h_loc
horizontal location of this tile
uint8_t tile_v_loc
vertical location of this tile
uint16_t tile_h_size
horizontal size of this tile.
uint16_t tile_v_size
vertical size of this tile.

Description

Each connector may be connected to one or more CRTCs, or may be clonable by another connector if they can share a CRTC. Each connector also has a specific position in the broader display (referred to as a ‘screen’ though it could span multiple monitors).

struct drm_plane_state

mutable plane state

Definition

struct drm_plane_state {
  struct drm_plane * plane;
  struct drm_crtc * crtc;
  struct drm_framebuffer * fb;
  struct fence * fence;
  int32_t crtc_x;
  int32_t crtc_y;
  uint32_t crtc_w;
  uint32_t crtc_h;
  uint32_t src_x;
  uint32_t src_y;
  uint32_t src_h;
  uint32_t src_w;
  struct drm_atomic_state * state;
};

Members

struct drm_plane * plane
backpointer to the plane
struct drm_crtc * crtc
currently bound CRTC, NULL if disabled
struct drm_framebuffer * fb
currently bound framebuffer
struct fence * fence
optional fence to wait for before scanning out fb
int32_t crtc_x
left position of visible portion of plane on crtc
int32_t crtc_y
upper position of visible portion of plane on crtc
uint32_t crtc_w
width of visible portion of plane on crtc
uint32_t crtc_h
height of visible portion of plane on crtc
uint32_t src_x
left position of visible portion of plane within plane (in 16.16)
uint32_t src_y
upper position of visible portion of plane within plane (in 16.16)
uint32_t src_h
height of visible portion of plane (in 16.16)
uint32_t src_w
width of visible portion of plane (in 16.16)
struct drm_atomic_state * state
backpointer to global drm_atomic_state
struct drm_plane_funcs

driver plane control functions

Definition

struct drm_plane_funcs {
  int (* update_plane) (struct drm_plane *plane,struct drm_crtc *crtc, struct drm_framebuffer *fb,int crtc_x, int crtc_y,unsigned int crtc_w, unsigned int crtc_h,uint32_t src_x, uint32_t src_y,uint32_t src_w, uint32_t src_h);
  int (* disable_plane) (struct drm_plane *plane);
  void (* destroy) (struct drm_plane *plane);
  void (* reset) (struct drm_plane *plane);
  int (* set_property) (struct drm_plane *plane,struct drm_property *property, uint64_t val);
  struct drm_plane_state *(* atomic_duplicate_state) (struct drm_plane *plane);
  void (* atomic_destroy_state) (struct drm_plane *plane,struct drm_plane_state *state);
  int (* atomic_set_property) (struct drm_plane *plane,struct drm_plane_state *state,struct drm_property *property,uint64_t val);
  int (* atomic_get_property) (struct drm_plane *plane,const struct drm_plane_state *state,struct drm_property *property,uint64_t *val);
};

Members

int (*)(struct drm_plane *plane,struct drm_crtc *crtc, struct drm_framebuffer *fb,int crtc_x, int crtc_y,unsigned int crtc_w, unsigned int crtc_h,uint32_t src_x, uint32_t src_y,uint32_t src_w, uint32_t src_h) update_plane

This is the legacy entry point to enable and configure the plane for the given CRTC and framebuffer. It is never called to disable the plane, i.e. the passed-in crtc and fb paramters are never NULL.

The source rectangle in frame buffer memory coordinates is given by the src_x, src_y, src_w and src_h parameters (as 16.16 fixed point values). Devices that don’t support subpixel plane coordinates can ignore the fractional part.

The destination rectangle in CRTC coordinates is given by the crtc_x, crtc_y, crtc_w and crtc_h parameters (as integer values). Devices scale the source rectangle to the destination rectangle. If scaling is not supported, and the source rectangle size doesn’t match the destination rectangle size, the driver must return a -<errorname>EINVAL</errorname> error.

Drivers implementing atomic modeset should use drm_atomic_helper_update_plane() to implement this hook.

RETURNS:

0 on success or a negative error code on failure.

int (*)(struct drm_plane *plane) disable_plane

This is the legacy entry point to disable the plane. The DRM core calls this method in response to a DRM_IOCTL_MODE_SETPLANE IOCTL call with the frame buffer ID set to 0. Disabled planes must not be processed by the CRTC.

Drivers implementing atomic modeset should use drm_atomic_helper_disable_plane() to implement this hook.

RETURNS:

0 on success or a negative error code on failure.

void (*)(struct drm_plane *plane) destroy
Clean up plane resources. This is only called at driver unload time through drm_mode_config_cleanup() since a plane cannot be hotplugged in DRM.
void (*)(struct drm_plane *plane) reset

Reset plane hardware and software state to off. This function isn’t called by the core directly, only through drm_mode_config_reset(). It’s not a helper hook only for historical reasons.

Atomic drivers can use drm_atomic_helper_plane_reset() to reset atomic state using this hook.

int (*)(struct drm_plane *plane,struct drm_property *property, uint64_t val) set_property

This is the legacy entry point to update a property attached to the plane.

Drivers implementing atomic modeset should use drm_atomic_helper_plane_set_property() to implement this hook.

This callback is optional if the driver does not support any legacy driver-private properties.

RETURNS:

0 on success or a negative error code on failure.

struct drm_plane_state *(*)(struct drm_plane *plane) atomic_duplicate_state

Duplicate the current atomic state for this plane and return it. The core and helpers gurantee that any atomic state duplicated with this hook and still owned by the caller (i.e. not transferred to the driver by calling ->:c:func:atomic_commit() from struct drm_mode_config_funcs) will be cleaned up by calling the atomic_destroy_state hook in this structure.

Atomic drivers which don’t subclass struct drm_plane_state should use drm_atomic_helper_plane_duplicate_state(). Drivers that subclass the state structure to extend it with driver-private state should use __drm_atomic_helper_plane_duplicate_state() to make sure shared state is duplicated in a consistent fashion across drivers.

It is an error to call this hook before plane->state has been initialized correctly.

NOTE:

If the duplicate state references refcounted resources this hook must acquire a reference for each of them. The driver must release these references again in atomic_destroy_state.

RETURNS:

Duplicated atomic state or NULL when the allocation failed.

void (*)(struct drm_plane *plane,struct drm_plane_state *state) atomic_destroy_state
Destroy a state duplicated with atomic_duplicate_state and release or unreference all resources it references
int (*)(struct drm_plane *plane,struct drm_plane_state *state,struct drm_property *property,uint64_t val) atomic_set_property

Decode a driver-private property value and store the decoded value into the passed-in state structure. Since the atomic core decodes all standardized properties (even for extensions beyond the core set of properties which might not be implemented by all drivers) this requires drivers to subclass the state structure.

Such driver-private properties should really only be implemented for truly hardware/vendor specific state. Instead it is preferred to standardize atomic extension and decode the properties used to expose such an extension in the core.

Do not call this function directly, use drm_atomic_plane_set_property() instead.

This callback is optional if the driver does not support any driver-private atomic properties.

NOTE:

This function is called in the state assembly phase of atomic modesets, which can be aborted for any reason (including on userspace’s request to just check whether a configuration would be possible). Drivers MUST NOT touch any persistent state (hardware or software) or data structures except the passed in state parameter.

Also since userspace controls in which order properties are set this function must not do any input validation (since the state update is incomplete and hence likely inconsistent). Instead any such input validation must be done in the various atomic_check callbacks.

RETURNS:

0 if the property has been found, -EINVAL if the property isn’t implemented by the driver (which shouldn’t ever happen, the core only asks for properties attached to this plane). No other validation is allowed by the driver. The core already checks that the property value is within the range (integer, valid enum value, ...) the driver set when registering the property.

int (*)(struct drm_plane *plane,const struct drm_plane_state *state,struct drm_property *property,uint64_t *val) atomic_get_property

Reads out the decoded driver-private property. This is used to implement the GETPLANE IOCTL.

Do not call this function directly, use drm_atomic_plane_get_property() instead.

This callback is optional if the driver does not support any driver-private atomic properties.

RETURNS:

0 on success, -EINVAL if the property isn’t implemented by the driver (which should never happen, the core only asks for properties attached to this plane).

struct drm_plane

central DRM plane control structure

Definition

struct drm_plane {
  struct drm_device * dev;
  struct list_head head;
  struct drm_mode_object base;
  uint32_t possible_crtcs;
  uint32_t * format_types;
  unsigned int format_count;
  bool format_default;
  struct drm_crtc * crtc;
  struct drm_framebuffer * fb;
  struct drm_framebuffer * old_fb;
  const struct drm_plane_funcs * funcs;
  struct drm_object_properties properties;
  enum drm_plane_type type;
  struct drm_plane_state * state;
};

Members

struct drm_device * dev
DRM device this plane belongs to
struct list_head head
for list management
struct drm_mode_object base
base mode object
uint32_t possible_crtcs
pipes this plane can be bound to
uint32_t * format_types
array of formats supported by this plane
unsigned int format_count
number of formats supported
bool format_default
driver hasn’t supplied supported formats for the plane
struct drm_crtc * crtc
currently bound CRTC
struct drm_framebuffer * fb
currently bound fb
struct drm_framebuffer * old_fb
Temporary tracking of the old fb while a modeset is ongoing. Used by drm_mode_set_config_internal() to implement correct refcounting.
const struct drm_plane_funcs * funcs
helper functions
struct drm_object_properties properties
property tracking for this plane
enum drm_plane_type type
type of plane (overlay, primary, cursor)
struct drm_plane_state * state
current atomic state for this plane
struct drm_bridge_funcs

drm_bridge control functions

Definition

struct drm_bridge_funcs {
  int (* attach) (struct drm_bridge *bridge);
  bool (* mode_fixup) (struct drm_bridge *bridge,const struct drm_display_mode *mode,struct drm_display_mode *adjusted_mode);
  void (* disable) (struct drm_bridge *bridge);
  void (* post_disable) (struct drm_bridge *bridge);
  void (* mode_set) (struct drm_bridge *bridge,struct drm_display_mode *mode,struct drm_display_mode *adjusted_mode);
  void (* pre_enable) (struct drm_bridge *bridge);
  void (* enable) (struct drm_bridge *bridge);
};

Members

int (*)(struct drm_bridge *bridge) attach
Called during drm_bridge_attach
bool (*)(struct drm_bridge *bridge,const struct drm_display_mode *mode,struct drm_display_mode *adjusted_mode) mode_fixup

This callback is used to validate and adjust a mode. The paramater mode is the display mode that should be fed to the next element in the display chain, either the final drm_connector or the next drm_bridge. The parameter adjusted_mode is the input mode the bridge requires. It can be modified by this callback and does not need to match mode.

This is the only hook that allows a bridge to reject a modeset. If this function passes all other callbacks must succeed for this configuration.

NOTE:

This function is called in the check phase of atomic modesets, which can be aborted for any reason (including on userspace’s request to just check whether a configuration would be possible). Drivers MUST NOT touch any persistent state (hardware or software) or data structures except the passed in state parameter.

RETURNS:

True if an acceptable configuration is possible, false if the modeset operation should be rejected.

void (*)(struct drm_bridge *bridge) disable

This callback should disable the bridge. It is called right before the preceding element in the display pipe is disabled. If the preceding element is a bridge this means it’s called before that bridge’s ->:c:func:disable() function. If the preceding element is a drm_encoder it’s called right before the encoder’s ->:c:func:disable(), ->:c:func:prepare() or ->:c:func:dpms() hook from struct drm_encoder_helper_funcs.

The bridge can assume that the display pipe (i.e. clocks and timing signals) feeding it is still running when this callback is called.

The disable callback is optional.

void (*)(struct drm_bridge *bridge) post_disable

This callback should disable the bridge. It is called right after the preceding element in the display pipe is disabled. If the preceding element is a bridge this means it’s called after that bridge’s ->:c:func:post_disable() function. If the preceding element is a drm_encoder it’s called right after the encoder’s ->:c:func:disable(), ->:c:func:prepare() or ->:c:func:dpms() hook from struct drm_encoder_helper_funcs.

The bridge must assume that the display pipe (i.e. clocks and timing singals) feeding it is no longer running when this callback is called.

The post_disable callback is optional.

void (*)(struct drm_bridge *bridge,struct drm_display_mode *mode,struct drm_display_mode *adjusted_mode) mode_set
This callback should set the given mode on the bridge. It is called after the ->:c:func:mode_set() callback for the preceding element in the display pipeline has been called already. The display pipe (i.e. clocks and timing signals) is off when this function is called.
void (*)(struct drm_bridge *bridge) pre_enable

This callback should enable the bridge. It is called right before the preceding element in the display pipe is enabled. If the preceding element is a bridge this means it’s called before that bridge’s ->:c:func:pre_enable() function. If the preceding element is a drm_encoder it’s called right before the encoder’s ->:c:func:enable(), ->:c:func:commit() or ->:c:func:dpms() hook from struct drm_encoder_helper_funcs.

The display pipe (i.e. clocks and timing signals) feeding this bridge will not yet be running when this callback is called. The bridge must not enable the display link feeding the next bridge in the chain (if there is one) when this callback is called.

The pre_enable callback is optional.

void (*)(struct drm_bridge *bridge) enable

This callback should enable the bridge. It is called right after the preceding element in the display pipe is enabled. If the preceding element is a bridge this means it’s called after that bridge’s ->:c:func:enable() function. If the preceding element is a drm_encoder it’s called right after the encoder’s ->:c:func:enable(), ->:c:func:commit() or ->:c:func:dpms() hook from struct drm_encoder_helper_funcs.

The bridge can assume that the display pipe (i.e. clocks and timing signals) feeding it is running when this callback is called. This callback must enable the display link feeding the next bridge in the chain if there is one.

The enable callback is optional.

struct drm_bridge

central DRM bridge control structure

Definition

struct drm_bridge {
  struct drm_device * dev;
  struct drm_encoder * encoder;
  struct drm_bridge * next;
#ifdef CONFIG_OF
  struct device_node * of_node;
#endif
  struct list_head list;
  const struct drm_bridge_funcs * funcs;
  void * driver_private;
};

Members

struct drm_device * dev
DRM device this bridge belongs to
struct drm_encoder * encoder
encoder to which this bridge is connected
struct drm_bridge * next
the next bridge in the encoder chain
struct device_node * of_node
device node pointer to the bridge
struct list_head list
to keep track of all added bridges
const struct drm_bridge_funcs * funcs
control functions
void * driver_private
pointer to the bridge driver’s internal context
struct drm_atomic_state

the global state object for atomic updates

Definition

struct drm_atomic_state {
  struct drm_device * dev;
  bool allow_modeset:1;
  bool legacy_cursor_update:1;
  bool legacy_set_config:1;
  struct drm_plane ** planes;
  struct drm_plane_state ** plane_states;
  struct drm_crtc ** crtcs;
  struct drm_crtc_state ** crtc_states;
  int num_connector;
  struct drm_connector ** connectors;
  struct drm_connector_state ** connector_states;
  struct drm_modeset_acquire_ctx * acquire_ctx;
};

Members

struct drm_device * dev
parent DRM device
bool:1 allow_modeset
allow full modeset
bool:1 legacy_cursor_update
hint to enforce legacy cursor IOCTL semantics
bool:1 legacy_set_config
Disable conflicting encoders instead of failing with -EINVAL.
struct drm_plane ** planes
pointer to array of plane pointers
struct drm_plane_state ** plane_states
pointer to array of plane states pointers
struct drm_crtc ** crtcs
pointer to array of CRTC pointers
struct drm_crtc_state ** crtc_states
pointer to array of CRTC states pointers
int num_connector
size of the connectors and connector_states arrays
struct drm_connector ** connectors
pointer to array of connector pointers
struct drm_connector_state ** connector_states
pointer to array of connector states pointers
struct drm_modeset_acquire_ctx * acquire_ctx
acquire context for this atomic modeset state update
struct drm_mode_set

new values for a CRTC config change

Definition

struct drm_mode_set {
  struct drm_framebuffer * fb;
  struct drm_crtc * crtc;
  struct drm_display_mode * mode;
  uint32_t x;
  uint32_t y;
  struct drm_connector ** connectors;
  size_t num_connectors;
};

Members

struct drm_framebuffer * fb
framebuffer to use for new config
struct drm_crtc * crtc
CRTC whose configuration we’re about to change
struct drm_display_mode * mode
mode timings to use
uint32_t x
position of this CRTC relative to fb
uint32_t y
position of this CRTC relative to fb
struct drm_connector ** connectors
array of connectors to drive with this CRTC if possible
size_t num_connectors
size of connectors array

Description

Represents a single crtc the connectors that it drives with what mode and from which framebuffer it scans out from.

This is used to set modes.

struct drm_mode_config_funcs

basic driver provided mode setting functions

Definition

struct drm_mode_config_funcs {
  struct drm_framebuffer *(* fb_create) (struct drm_device *dev,struct drm_file *file_priv,const struct drm_mode_fb_cmd2 *mode_cmd);
  void (* output_poll_changed) (struct drm_device *dev);
  int (* atomic_check) (struct drm_device *dev,struct drm_atomic_state *state);
  int (* atomic_commit) (struct drm_device *dev,struct drm_atomic_state *state,bool nonblock);
  struct drm_atomic_state *(* atomic_state_alloc) (struct drm_device *dev);
  void (* atomic_state_clear) (struct drm_atomic_state *state);
  void (* atomic_state_free) (struct drm_atomic_state *state);
};

Members

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

Create a new framebuffer object. The core does basic checks on the requested metadata, but most of that is left to the driver. See struct drm_mode_fb_cmd2 for details.

If the parameters are deemed valid and the backing storage objects in the underlying memory manager all exist, then the driver allocates a new drm_framebuffer structure, subclassed to contain driver-specific information (like the internal native buffer object references). It also needs to fill out all relevant metadata, which should be done by calling drm_helper_mode_fill_fb_struct().

The initialization is finalized by calling drm_framebuffer_init(), which registers the framebuffer and makes it accessible to other threads.

RETURNS:

A new framebuffer with an initial reference count of 1 or a negative error code encoded with ERR_PTR().

void (*)(struct drm_device *dev) output_poll_changed

Callback used by helpers to inform the driver of output configuration changes.

Drivers implementing fbdev emulation with the helpers can call drm_fb_helper_hotplug_changed from this hook to inform the fbdev helper of output changes.

FIXME:

Except that there’s no vtable for device-level helper callbacks there’s no reason this is a core function.

int (*)(struct drm_device *dev,struct drm_atomic_state *state) atomic_check

This is the only hook to validate an atomic modeset update. This function must reject any modeset and state changes which the hardware or driver doesn’t support. This includes but is of course not limited to:

  • Checking that the modes, framebuffers, scaling and placement requirements and so on are within the limits of the hardware.
  • Checking that any hidden shared resources are not oversubscribed. This can be shared PLLs, shared lanes, overall memory bandwidth, display fifo space (where shared between planes or maybe even CRTCs).
  • Checking that virtualized resources exported to userspace are not oversubscribed. For various reasons it can make sense to expose more planes, crtcs or encoders than which are physically there. One example is dual-pipe operations (which generally should be hidden from userspace if when lockstepped in hardware, exposed otherwise), where a plane might need 1 hardware plane (if it’s just on one pipe), 2 hardware planes (when it spans both pipes) or maybe even shared a hardware plane with a 2nd plane (if there’s a compatible plane requested on the area handled by the other pipe).
  • Check that any transitional state is possible and that if requested, the update can indeed be done in the vblank period without temporarily disabling some functions.
  • Check any other constraints the driver or hardware might have.
  • This callback also needs to correctly fill out the drm_crtc_state in this update to make sure that drm_atomic_crtc_needs_modeset() reflects the nature of the possible update and returns true if and only if the update cannot be applied without tearing within one vblank on that CRTC. The core uses that information to reject updates which require a full modeset (i.e. blanking the screen, or at least pausing updates for a substantial amount of time) if userspace has disallowed that in its request.
  • The driver also does not need to repeat basic input validation like done for the corresponding legacy entry points. The core does that before calling this hook.

See the documentation of atomic_commit for an exhaustive list of error conditions which don’t have to be checked at the ->:c:func:atomic_check() stage?

See the documentation for struct drm_atomic_state for how exactly an atomic modeset update is described.

Drivers using the atomic helpers can implement this hook using drm_atomic_helper_check(), or one of the exported sub-functions of it.

RETURNS:

0 on success or one of the below negative error codes:

  • -EINVAL, if any of the above constraints are violated.
  • -EDEADLK, when returned from an attempt to acquire an additional drm_modeset_lock through drm_modeset_lock().
  • -ENOMEM, if allocating additional state sub-structures failed due to lack of memory.
  • -EINTR, -EAGAIN or -ERESTARTSYS, if the IOCTL should be restarted. This can either be due to a pending signal, or because the driver needs to completely bail out to recover from an exceptional situation like a GPU hang. From a userspace point all errors are treated equally.
int (*)(struct drm_device *dev,struct drm_atomic_state *state,bool nonblock) atomic_commit

This is the only hook to commit an atomic modeset update. The core guarantees that atomic_check has been called successfully before calling this function, and that nothing has been changed in the interim.

See the documentation for struct drm_atomic_state for how exactly an atomic modeset update is described.

Drivers using the atomic helpers can implement this hook using drm_atomic_helper_commit(), or one of the exported sub-functions of it.

Nonblocking commits (as indicated with the nonblock parameter) must do any preparatory work which might result in an unsuccessful commit in the context of this callback. The only exceptions are hardware errors resulting in -EIO. But even in that case the driver must ensure that the display pipe is at least running, to avoid compositors crashing when pageflips don’t work. Anything else, specifically committing the update to the hardware, should be done without blocking the caller. For updates which do not require a modeset this must be guaranteed.

The driver must wait for any pending rendering to the new framebuffers to complete before executing the flip. It should also wait for any pending rendering from other drivers if the underlying buffer is a shared dma-buf. Nonblocking commits must not wait for rendering in the context of this callback.

An application can request to be notified when the atomic commit has completed. These events are per-CRTC and can be distinguished by the CRTC index supplied in drm_event to userspace.

The drm core will supply a struct drm_event in the event member of each CRTC’s drm_crtc_state structure. This can be handled by the drm_crtc_send_vblank_event() function, which the driver should call on the provided event upon completion of the atomic commit. Note that if the driver supports vblank signalling and timestamping the vblank counters and timestamps must agree with the ones returned from page flip events. With the current vblank helper infrastructure this can be achieved by holding a vblank reference while the page flip is pending, acquired through drm_crtc_vblank_get() and released with drm_crtc_vblank_put(). Drivers are free to implement their own vblank counter and timestamp tracking though, e.g. if they have accurate timestamp registers in hardware.

NOTE:

Drivers are not allowed to shut down any display pipe successfully enabled through an atomic commit on their own. Doing so can result in compositors crashing if a page flip is suddenly rejected because the pipe is off.

RETURNS:

0 on success or one of the below negative error codes:

  • -EBUSY, if a nonblocking updated is requested and there is an earlier updated pending. Drivers are allowed to support a queue of outstanding updates, but currently no driver supports that. Note that drivers must wait for preceding updates to complete if a synchronous update is requested, they are not allowed to fail the commit in that case.
  • -ENOMEM, if the driver failed to allocate memory. Specifically this can happen when trying to pin framebuffers, which must only be done when committing the state.
  • -ENOSPC, as a refinement of the more generic -ENOMEM to indicate that the driver has run out of vram, iommu space or similar GPU address space needed for framebuffer.
  • -EIO, if the hardware completely died.
  • -EINTR, -EAGAIN or -ERESTARTSYS, if the IOCTL should be restarted. This can either be due to a pending signal, or because the driver needs to completely bail out to recover from an exceptional situation like a GPU hang. From a userspace point of view all errors are treated equally.

This list is exhaustive. Specifically this hook is not allowed to return -EINVAL (any invalid requests should be caught in atomic_check) or -EDEADLK (this function must not acquire additional modeset locks).

struct drm_atomic_state *(*)(struct drm_device *dev) atomic_state_alloc

This optional hook can be used by drivers that want to subclass struct drm_atomic_state to be able to track their own driver-private global state easily. If this hook is implemented, drivers must also implement atomic_state_clear and atomic_state_free.

RETURNS:

A new drm_atomic_state on success or NULL on failure.

void (*)(struct drm_atomic_state *state) atomic_state_clear

This hook must clear any driver private state duplicated into the passed-in drm_atomic_state. This hook is called when the caller encountered a drm_modeset_lock deadlock and needs to drop all already acquired locks as part of the deadlock avoidance dance implemented in drm_modeset_lock_backoff().

Any duplicated state must be invalidated since a concurrent atomic update might change it, and the drm atomic interfaces always apply updates as relative changes to the current state.

Drivers that implement this must call drm_atomic_state_default_clear() to clear common state.

void (*)(struct drm_atomic_state *state) atomic_state_free

This hook needs driver private resources and the drm_atomic_state itself. Note that the core first calls drm_atomic_state_clear() to avoid code duplicate between the clear and free hooks.

Drivers that implement this must call drm_atomic_state_default_free() to release common resources.

Description

Some global (i.e. not per-CRTC, connector, etc) mode setting functions that involve drivers.

struct drm_mode_config

Mode configuration control structure

Definition

struct drm_mode_config {
  struct mutex mutex;
  struct drm_modeset_lock connection_mutex;
  struct drm_modeset_acquire_ctx * acquire_ctx;
  struct mutex idr_mutex;
  struct idr crtc_idr;
  struct mutex fb_lock;
  int num_fb;
  struct list_head fb_list;
  int num_connector;
  struct list_head connector_list;
  int num_encoder;
  struct list_head encoder_list;
  int num_overlay_plane;
  int num_total_plane;
  struct list_head plane_list;
  int num_crtc;
  struct list_head crtc_list;
  struct list_head property_list;
  int min_width;
  int min_height;
  int max_width;
  int max_height;
  const struct drm_mode_config_funcs * funcs;
  resource_size_t fb_base;
  bool poll_enabled;
  bool poll_running;
  struct delayed_work output_poll_work;
  struct mutex blob_lock;
  struct list_head property_blob_list;
  struct drm_property * degamma_lut_property;
  struct drm_property * degamma_lut_size_property;
  struct drm_property * ctm_property;
  struct drm_property * gamma_lut_property;
  struct drm_property * gamma_lut_size_property;
  uint32_t preferred_depth;
  uint32_t prefer_shadow;
  bool async_page_flip;
  uint32_t cursor_width;
  uint32_t cursor_height;
};

Members

struct mutex mutex
mutex protecting KMS related lists and structures
struct drm_modeset_lock connection_mutex
ww mutex protecting connector state and routing
struct drm_modeset_acquire_ctx * acquire_ctx
global implicit acquire context used by atomic drivers for legacy IOCTLs
struct mutex idr_mutex
mutex for KMS ID allocation and management
struct idr crtc_idr
main KMS ID tracking object
struct mutex fb_lock
mutex to protect fb state and lists
int num_fb
number of fbs available
struct list_head fb_list
list of framebuffers available
int num_connector
number of connectors on this device
struct list_head connector_list
list of connector objects
int num_encoder
number of encoders on this device
struct list_head encoder_list
list of encoder objects
int num_overlay_plane
number of overlay planes on this device
int num_total_plane
number of universal (i.e. with primary/curso) planes on this device
struct list_head plane_list
list of plane objects
int num_crtc
number of CRTCs on this device
struct list_head crtc_list
list of CRTC objects
struct list_head property_list
list of property objects
int min_width
minimum pixel width on this device
int min_height
minimum pixel height on this device
int max_width
maximum pixel width on this device
int max_height
maximum pixel height on this device
const struct drm_mode_config_funcs * funcs
core driver provided mode setting functions
resource_size_t fb_base
base address of the framebuffer
bool poll_enabled
track polling support for this device
bool poll_running
track polling status for this device
struct delayed_work output_poll_work
delayed work for polling in process context
struct mutex blob_lock
mutex for blob property allocation and management @*_property: core property tracking
struct list_head property_blob_list
list of all the blob property objects
struct drm_property * degamma_lut_property
LUT used to convert the framebuffer’s colors to linear gamma
struct drm_property * degamma_lut_size_property
size of the degamma LUT as supported by the driver (read-only)
struct drm_property * ctm_property
Matrix used to convert colors after the lookup in the degamma LUT
struct drm_property * gamma_lut_property
LUT used to convert the colors, after the CSC matrix, to the gamma space of the connected screen (read-only)
struct drm_property * gamma_lut_size_property
size of the gamma LUT as supported by the driver
uint32_t preferred_depth
preferred RBG pixel depth, used by fb helpers
uint32_t prefer_shadow
hint to userspace to prefer shadow-fb rendering
bool async_page_flip
does this device support async flips on the primary plane?
uint32_t cursor_width
hint to userspace for max cursor width
uint32_t cursor_height
hint to userspace for max cursor height

Description

Core mode resource tracking structure. All CRTC, encoders, and connectors enumerated by the driver are added here, as are global properties. Some global restrictions are also here, e.g. dimension restrictions.

drm_for_each_plane_mask(plane, dev, plane_mask)

iterate over planes specified by bitmask

Parameters

plane
the loop cursor
dev
the DRM device
plane_mask
bitmask of plane indices

Description

Iterate over all planes specified by bitmask.

drm_for_each_encoder_mask(encoder, dev, encoder_mask)

iterate over encoders specified by bitmask

Parameters

encoder
the loop cursor
dev
the DRM device
encoder_mask
bitmask of encoder indices

Description

Iterate over all encoders specified by bitmask.

uint32_t drm_crtc_mask(struct drm_crtc * crtc)

find the mask of a registered CRTC

Parameters

struct drm_crtc * crtc
CRTC to find mask for

Description

Given a registered CRTC, return the mask bit of that CRTC for an encoder’s possible_crtcs field.

bool drm_encoder_crtc_ok(struct drm_encoder * encoder, struct drm_crtc * crtc)

can a given crtc drive a given encoder?

Parameters

struct drm_encoder * encoder
encoder to test
struct drm_crtc * crtc
crtc to test

Description

Return false if encoder can’t be driven by crtc, true otherwise.

struct drm_connector * drm_connector_lookup(struct drm_device * dev, uint32_t id)

lookup connector object

Parameters

struct drm_device * dev
DRM device
uint32_t id
connector object id

Description

This function looks up the connector object specified by id add takes a reference to it.

void drm_framebuffer_reference(struct drm_framebuffer * fb)

incr the fb refcnt

Parameters

struct drm_framebuffer * fb
framebuffer

Description

This functions increments the fb’s refcount.

void drm_framebuffer_unreference(struct drm_framebuffer * fb)

unref a framebuffer

Parameters

struct drm_framebuffer * fb
framebuffer to unref

Description

This functions decrements the fb’s refcount and frees it if it drops to zero.

uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer * fb)

read the framebuffer reference count.

Parameters

struct drm_framebuffer * fb
framebuffer

Description

This functions returns the framebuffer’s reference count.

void drm_connector_reference(struct drm_connector * connector)

incr the connector refcnt

Parameters

struct drm_connector * connector
connector

Description

This function increments the connector’s refcount.

void drm_connector_unreference(struct drm_connector * connector)

unref a connector

Parameters

struct drm_connector * connector
connector to unref

Description

This function decrements the connector’s refcount and frees it if it drops to zero.

KMS Locking

As KMS moves toward more fine grained locking, and atomic ioctl where userspace can indirectly control locking order, it becomes necessary to use ww_mutex and acquire-contexts to avoid deadlocks. But because the locking is more distributed around the driver code, we want a bit of extra utility/tracking out of our acquire-ctx. This is provided by drm_modeset_lock / drm_modeset_acquire_ctx.

For basic principles of ww_mutex, see: Documentation/locking/ww-mutex-design.txt

The basic usage pattern is to:

drm_modeset_acquire_init(ctx) retry: foreach (lock in random_ordered_set_of_locks) {

ret = drm_modeset_lock(lock, ctx) if (ret == -EDEADLK) {

drm_modeset_backoff(ctx); goto retry;

}

} ... do stuff ... drm_modeset_drop_locks(ctx); drm_modeset_acquire_fini(ctx);

struct drm_modeset_acquire_ctx

locking context (see ww_acquire_ctx)

Definition

struct drm_modeset_acquire_ctx {
  struct ww_acquire_ctx ww_ctx;
  struct drm_modeset_lock * contended;
  struct list_head locked;
  bool trylock_only;
};

Members

struct ww_acquire_ctx ww_ctx
base acquire ctx
struct drm_modeset_lock * contended
used internally for -EDEADLK handling
struct list_head locked
list of held locks
bool trylock_only
trylock mode used in atomic contexts/panic notifiers

Description

Each thread competing for a set of locks must use one acquire ctx. And if any lock fxn returns -EDEADLK, it must backoff and retry.

struct drm_modeset_lock

used for locking modeset resources.

Definition

struct drm_modeset_lock {
  struct ww_mutex mutex;
  struct list_head head;
};

Members

struct ww_mutex mutex
resource locking
struct list_head head
used to hold it’s place on state->locked list when part of an atomic update

Description

Used for locking CRTCs and other modeset resources.

void drm_modeset_lock_init(struct drm_modeset_lock * lock)

initialize lock

Parameters

struct drm_modeset_lock * lock
lock to init
void drm_modeset_lock_fini(struct drm_modeset_lock * lock)

cleanup lock

Parameters

struct drm_modeset_lock * lock
lock to cleanup
bool drm_modeset_is_locked(struct drm_modeset_lock * lock)

equivalent to mutex_is_locked()

Parameters

struct drm_modeset_lock * lock
lock to check
void drm_modeset_lock_all(struct drm_device * dev)

take all modeset locks

Parameters

struct drm_device * dev
DRM device

Description

This function takes all modeset locks, suitable where a more fine-grained scheme isn’t (yet) implemented. Locks must be dropped by calling the drm_modeset_unlock_all() function.

This function is deprecated. It allocates a lock acquisition context and stores it in the DRM device’s ->mode_config. This facilitate conversion of existing code because it removes the need to manually deal with the acquisition context, but it is also brittle because the context is global and care must be taken not to nest calls. New code should use the drm_modeset_lock_all_ctx() function and pass in the context explicitly.

void drm_modeset_unlock_all(struct drm_device * dev)

drop all modeset locks

Parameters

struct drm_device * dev
DRM device

Description

This function drops all modeset locks taken by a previous call to the drm_modeset_lock_all() function.

This function is deprecated. It uses the lock acquisition context stored in the DRM device’s ->mode_config. This facilitates conversion of existing code because it removes the need to manually deal with the acquisition context, but it is also brittle because the context is global and care must be taken not to nest calls. New code should pass the acquisition context directly to the drm_modeset_drop_locks() function.

void drm_modeset_lock_crtc(struct drm_crtc * crtc, struct drm_plane * plane)

lock crtc with hidden acquire ctx for a plane update

Parameters

struct drm_crtc * crtc
DRM CRTC
struct drm_plane * plane
DRM plane to be updated on crtc

Description

This function locks the given crtc and plane (which should be either the primary or cursor plane) using a hidden acquire context. This is necessary so that drivers internally using the atomic interfaces can grab further locks with the lock acquire context.

Note that plane can be NULL, e.g. when the cursor support hasn’t yet been converted to universal planes yet.

struct drm_modeset_acquire_ctx * drm_modeset_legacy_acquire_ctx(struct drm_crtc * crtc)

find acquire ctx for legacy ioctls

Parameters

struct drm_crtc * crtc
drm crtc

Description

Legacy ioctl operations like cursor updates or page flips only have per-crtc locking, and store the acquire ctx in the corresponding crtc. All other legacy operations take all locks and use a global acquire context. This function grabs the right one.

void drm_modeset_unlock_crtc(struct drm_crtc * crtc)

drop crtc lock

Parameters

struct drm_crtc * crtc
drm crtc

Description

This drops the crtc lock acquire with drm_modeset_lock_crtc() and all other locks acquired through the hidden context.

void drm_warn_on_modeset_not_all_locked(struct drm_device * dev)

check that all modeset locks are locked

Parameters

struct drm_device * dev
device

Description

Useful as a debug assert.

void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx * ctx, uint32_t flags)

initialize acquire context

Parameters

struct drm_modeset_acquire_ctx * ctx
the acquire context
uint32_t flags
for future
void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx * ctx)

cleanup acquire context

Parameters

struct drm_modeset_acquire_ctx * ctx
the acquire context
void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx * ctx)

drop all locks

Parameters

struct drm_modeset_acquire_ctx * ctx
the acquire context

Description

Drop all locks currently held against this acquire context.

void drm_modeset_backoff(struct drm_modeset_acquire_ctx * ctx)

deadlock avoidance backoff

Parameters

struct drm_modeset_acquire_ctx * ctx
the acquire context

Description

If deadlock is detected (ie. drm_modeset_lock() returns -EDEADLK), you must call this function to drop all currently held locks and block until the contended lock becomes available.

int drm_modeset_backoff_interruptible(struct drm_modeset_acquire_ctx * ctx)

deadlock avoidance backoff

Parameters

struct drm_modeset_acquire_ctx * ctx
the acquire context

Description

Interruptible version of drm_modeset_backoff()

int drm_modeset_lock(struct drm_modeset_lock * lock, struct drm_modeset_acquire_ctx * ctx)

take modeset lock

Parameters

struct drm_modeset_lock * lock
lock to take
struct drm_modeset_acquire_ctx * ctx
acquire ctx

Description

If ctx is not NULL, then its ww acquire context is used and the lock will be tracked by the context and can be released by calling drm_modeset_drop_locks(). If -EDEADLK is returned, this means a deadlock scenario has been detected and it is an error to attempt to take any more locks without first calling drm_modeset_backoff().

int drm_modeset_lock_interruptible(struct drm_modeset_lock * lock, struct drm_modeset_acquire_ctx * ctx)

take modeset lock

Parameters

struct drm_modeset_lock * lock
lock to take
struct drm_modeset_acquire_ctx * ctx
acquire ctx

Description

Interruptible version of drm_modeset_lock()

void drm_modeset_unlock(struct drm_modeset_lock * lock)

drop modeset lock

Parameters

struct drm_modeset_lock * lock
lock to release
int drm_modeset_lock_all_ctx(struct drm_device * dev, struct drm_modeset_acquire_ctx * ctx)

take all modeset locks

Parameters

struct drm_device * dev
DRM device
struct drm_modeset_acquire_ctx * ctx
lock acquisition context

Description

This function takes all modeset locks, suitable where a more fine-grained scheme isn’t (yet) implemented.

Unlike drm_modeset_lock_all(), it doesn’t take the dev->mode_config.mutex since that lock isn’t required for modeset state changes. Callers which need to grab that lock too need to do so outside of the acquire context ctx.

Locks acquired with this function should be released by calling the drm_modeset_drop_locks() function on ctx.

Return

0 on success or a negative error-code on failure.

Mode Setting Helper Functions

The plane, CRTC, encoder and connector functions provided by the drivers implement the DRM API. They’re called by the DRM core and ioctl handlers to handle device state changes and configuration request. As implementing those functions often requires logic not specific to drivers, mid-layer helper functions are available to avoid duplicating boilerplate code.

The DRM core contains one mid-layer implementation. The mid-layer provides implementations of several plane, CRTC, encoder and connector functions (called from the top of the mid-layer) that pre-process requests and call lower-level functions provided by the driver (at the bottom of the mid-layer). For instance, the drm_crtc_helper_set_config() function can be used to fill the struct drm_crtc_funcs set_config field. When called, it will split the set_config operation in smaller, simpler operations and call the driver to handle them.

To use the mid-layer, drivers call drm_crtc_helper_add(), drm_encoder_helper_add() and drm_connector_helper_add() functions to install their mid-layer bottom operations handlers, and fill the struct drm_crtc_funcs, struct drm_encoder_funcs and struct drm_connector_funcs structures with pointers to the mid-layer top API functions. Installing the mid-layer bottom operation handlers is best done right after registering the corresponding KMS object.

The mid-layer is not split between CRTC, encoder and connector operations. To use it, a driver must provide bottom functions for all of the three KMS entities.

Atomic Modeset Helper Functions Reference

Overview

This helper library provides implementations of check and commit functions on top of the CRTC modeset helper callbacks and the plane helper callbacks. It also provides convenience implementations for the atomic state handling callbacks for drivers which don’t need to subclass the drm core structures to add their own additional internal state.

This library also provides default implementations for the check callback in drm_atomic_helper_check() and for the commit callback with drm_atomic_helper_commit(). But the individual stages and callbacks are exposed to allow drivers to mix and match and e.g. use the plane helpers only together with a driver private modeset implementation.

This library also provides implementations for all the legacy driver interfaces on top of the atomic interface. See drm_atomic_helper_set_config(), drm_atomic_helper_disable_plane(), drm_atomic_helper_disable_plane() and the various functions to implement set_property callbacks. New drivers must not implement these functions themselves but must use the provided helpers.

The atomic helper uses the same function table structures as all other modesetting helpers. See the documentation for struct drm_crtc_helper_funcs, struct drm_encoder_helper_funcs and struct drm_connector_helper_funcs. It also shares the struct drm_plane_helper_funcs function table with the plane helpers.

Implementing Asynchronous Atomic Commit
Atomic State Reset and Initialization

Both the drm core and the atomic helpers assume that there is always the full and correct atomic software state for all connectors, CRTCs and planes available. Which is a bit a problem on driver load and also after system suspend. One way to solve this is to have a hardware state read-out infrastructure which reconstructs the full software state (e.g. the i915 driver).

The simpler solution is to just reset the software state to everything off, which is easiest to do by calling drm_mode_config_reset(). To facilitate this the atomic helpers provide default reset implementations for all hooks.

On the upside the precise state tracking of atomic simplifies system suspend and resume a lot. For drivers using drm_mode_config_reset() a complete recipe is implemented in drm_atomic_helper_suspend() and drm_atomic_helper_resume(). For other drivers the building blocks are split out, see the documentation for these functions.

drm_atomic_crtc_for_each_plane(plane, crtc)

iterate over planes currently attached to CRTC

Parameters

plane
the loop cursor
crtc
the crtc whose planes are iterated

Description

This iterates over the current state, useful (for example) when applying atomic state after it has been checked and swapped. To iterate over the planes which will be attached (for ->:c:func:atomic_check()) see drm_crtc_for_each_pending_plane()

drm_atomic_crtc_state_for_each_plane(plane, crtc_state)

iterate over attached planes in new state

Parameters

plane
the loop cursor
crtc_state
the incoming crtc-state

Description

Similar to drm_crtc_for_each_plane(), but iterates the planes that will be attached if the specified state is applied. Useful during (for example) ->:c:func:atomic_check() operations, to validate the incoming state

int drm_atomic_helper_check_modeset(struct drm_device * dev, struct drm_atomic_state * state)

validate state object for modeset changes

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * state
the driver state object

Description

Check the state object to see if the requested state is physically possible. This does all the crtc and connector related computations for an atomic update and adds any additional connectors needed for full modesets and calls down into ->mode_fixup functions of the driver backend.

crtc_state->mode_changed is set when the input mode is changed. crtc_state->connectors_changed is set when a connector is added or removed from the crtc. crtc_state->active_changed is set when crtc_state->active changes, which is used for dpms.

IMPORTANT:

Drivers which update ->mode_changed (e.g. in their ->atomic_check hooks if a plane update can’t be done without a full modeset) _must_ call this function afterwards after that change. It is permitted to call this function multiple times for the same update, e.g. when the ->atomic_check functions depend upon the adjusted dotclock for fifo space allocation and watermark computation.

RETURNS Zero for success or -errno

int drm_atomic_helper_check_planes(struct drm_device * dev, struct drm_atomic_state * state)

validate state object for planes changes

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * state
the driver state object

Description

Check the state object to see if the requested state is physically possible. This does all the plane update related checks using by calling into the ->atomic_check hooks provided by the driver.

It also sets crtc_state->planes_changed to indicate that a crtc has updated planes.

RETURNS Zero for success or -errno

int drm_atomic_helper_check(struct drm_device * dev, struct drm_atomic_state * state)

validate state object

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * state
the driver state object

Description

Check the state object to see if the requested state is physically possible. Only crtcs and planes have check callbacks, so for any additional (global) checking that a driver needs it can simply wrap that around this function. Drivers without such needs can directly use this as their ->:c:func:atomic_check() callback.

This just wraps the two parts of the state checking for planes and modeset state in the default order: First it calls drm_atomic_helper_check_modeset() and then drm_atomic_helper_check_planes(). The assumption is that the ->atomic_check functions depend upon an updated adjusted_mode.clock to e.g. properly compute watermarks.

RETURNS Zero for success or -errno

void drm_atomic_helper_update_legacy_modeset_state(struct drm_device * dev, struct drm_atomic_state * old_state)

update legacy modeset state

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * old_state
atomic state object with old state structures

Description

This function updates all the various legacy modeset state pointers in connectors, encoders and crtcs. It also updates the timestamping constants used for precise vblank timestamps by calling drm_calc_timestamping_constants().

Drivers can use this for building their own atomic commit if they don’t have a pure helper-based modeset implementation.

void drm_atomic_helper_commit_modeset_disables(struct drm_device * dev, struct drm_atomic_state * old_state)

modeset commit to disable outputs

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * old_state
atomic state object with old state structures

Description

This function shuts down all the outputs that need to be shut down and prepares them (if required) with the new mode.

For compatibility with legacy crtc helpers this should be called before drm_atomic_helper_commit_planes(), which is what the default commit function does. But drivers with different needs can group the modeset commits together and do the plane commits at the end. This is useful for drivers doing runtime PM since planes updates then only happen when the CRTC is actually enabled.

void drm_atomic_helper_commit_modeset_enables(struct drm_device * dev, struct drm_atomic_state * old_state)

modeset commit to enable outputs

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * old_state
atomic state object with old state structures

Description

This function enables all the outputs with the new configuration which had to be turned off for the update.

For compatibility with legacy crtc helpers this should be called after drm_atomic_helper_commit_planes(), which is what the default commit function does. But drivers with different needs can group the modeset commits together and do the plane commits at the end. This is useful for drivers doing runtime PM since planes updates then only happen when the CRTC is actually enabled.

void drm_atomic_helper_wait_for_fences(struct drm_device * dev, struct drm_atomic_state * state)

wait for fences stashed in plane state

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * state
atomic state object with old state structures

Description

For implicit sync, driver should fish the exclusive fence out from the incoming fb’s and stash it in the drm_plane_state. This is called after drm_atomic_helper_swap_state() so it uses the current plane state (and just uses the atomic state to find the changed planes)

bool drm_atomic_helper_framebuffer_changed(struct drm_device * dev, struct drm_atomic_state * old_state, struct drm_crtc * crtc)

check if framebuffer has changed

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * old_state
atomic state object with old state structures
struct drm_crtc * crtc
DRM crtc

Description

Checks whether the framebuffer used for this CRTC changes as a result of the atomic update. This is useful for drivers which cannot use drm_atomic_helper_wait_for_vblanks() and need to reimplement its functionality.

Return

true if the framebuffer changed.

void drm_atomic_helper_wait_for_vblanks(struct drm_device * dev, struct drm_atomic_state * old_state)

wait for vblank on crtcs

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * old_state
atomic state object with old state structures

Description

Helper to, after atomic commit, wait for vblanks on all effected crtcs (ie. before cleaning up old framebuffers using drm_atomic_helper_cleanup_planes()). It will only wait on crtcs where the framebuffers have actually changed to optimize for the legacy cursor and plane update use-case.

int drm_atomic_helper_commit(struct drm_device * dev, struct drm_atomic_state * state, bool nonblock)

commit validated state object

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * state
the driver state object
bool nonblock
undescribed

Description

This function commits a with drm_atomic_helper_check() pre-validated state object. This can still fail when e.g. the framebuffer reservation fails. For now this doesn’t implement nonblocking commits.

Note that right now this function does not support nonblocking commits, hence driver writers must implement their own version for now. Also note that the default ordering of how the various stages are called is to match the legacy modeset helper library closest. One peculiarity of that is that it doesn’t mesh well with runtime PM at all.

For drivers supporting runtime PM the recommended sequence is

drm_atomic_helper_commit_modeset_disables(dev, state);

drm_atomic_helper_commit_modeset_enables(dev, state);

drm_atomic_helper_commit_planes(dev, state, true);

See the kerneldoc entries for these three functions for more details.

RETURNS Zero for success or -errno.

int drm_atomic_helper_prepare_planes(struct drm_device * dev, struct drm_atomic_state * state)

prepare plane resources before commit

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * state
atomic state object with new state structures

Description

This function prepares plane state, specifically framebuffers, for the new configuration. If any failure is encountered this function will call ->cleanup_fb on any already successfully prepared framebuffer.

Return

0 on success, negative error code on failure.

void drm_atomic_helper_commit_planes(struct drm_device * dev, struct drm_atomic_state * old_state, bool active_only)

commit plane state

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * old_state
atomic state object with old state structures
bool active_only
Only commit on active CRTC if set

Description

This function commits the new plane state using the plane and atomic helper functions for planes and crtcs. It assumes that the atomic state has already been pushed into the relevant object state pointers, since this step can no longer fail.

It still requires the global state object old_state to know which planes and crtcs need to be updated though.

Note that this function does all plane updates across all CRTCs in one step. If the hardware can’t support this approach look at drm_atomic_helper_commit_planes_on_crtc() instead.

Plane parameters can be updated by applications while the associated CRTC is disabled. The DRM/KMS core will store the parameters in the plane state, which will be available to the driver when the CRTC is turned on. As a result most drivers don’t need to be immediately notified of plane updates for a disabled CRTC.

Unless otherwise needed, drivers are advised to set the active_only parameters to true in order not to receive plane update notifications related to a disabled CRTC. This avoids the need to manually ignore plane updates in driver code when the driver and/or hardware can’t or just don’t need to deal with updates on disabled CRTCs, for example when supporting runtime PM.

The drm_atomic_helper_commit() default implementation only sets active_only to false to most closely match the behaviour of the legacy helpers. This should not be copied blindly by drivers.

void drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state * old_crtc_state)

commit plane state for a crtc

Parameters

struct drm_crtc_state * old_crtc_state
atomic state object with the old crtc state

Description

This function commits the new plane state using the plane and atomic helper functions for planes on the specific crtc. It assumes that the atomic state has already been pushed into the relevant object state pointers, since this step can no longer fail.

This function is useful when plane updates should be done crtc-by-crtc instead of one global step like drm_atomic_helper_commit_planes() does.

This function can only be savely used when planes are not allowed to move between different CRTCs because this function doesn’t handle inter-CRTC depencies. Callers need to ensure that either no such depencies exist, resolve them through ordering of commit calls or through some other means.

void drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc * crtc, bool atomic)

helper to disable CRTC’s planes

Parameters

struct drm_crtc * crtc
CRTC
bool atomic
if set, synchronize with CRTC’s atomic_begin/flush hooks

Description

Disables all planes associated with the given CRTC. This can be used for instance in the CRTC helper disable callback to disable all planes before shutting down the display pipeline.

If the atomic-parameter is set the function calls the CRTC’s atomic_begin hook before and atomic_flush hook after disabling the planes.

It is a bug to call this function without having implemented the ->:c:func:atomic_disable() plane hook.

void drm_atomic_helper_cleanup_planes(struct drm_device * dev, struct drm_atomic_state * old_state)

cleanup plane resources after commit

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * old_state
atomic state object with old state structures

Description

This function cleans up plane state, specifically framebuffers, from the old configuration. Hence the old configuration must be perserved in old_state to be able to call this function.

This function must also be called on the new state when the atomic update fails at any point after calling drm_atomic_helper_prepare_planes().

void drm_atomic_helper_swap_state(struct drm_device * dev, struct drm_atomic_state * state)

store atomic state into current sw state

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * state
atomic state

Description

This function stores the atomic state into the current state pointers in all driver objects. It should be called after all failing steps have been done and succeeded, but before the actual hardware state is committed.

For cleanup and error recovery the current state for all changed objects will be swaped into state.

With that sequence it fits perfectly into the plane prepare/cleanup sequence:

  1. Call drm_atomic_helper_prepare_planes() with the staged atomic state.
  2. Do any other steps that might fail.
  3. Put the staged state into the current state pointers with this function.
  4. Actually commit the hardware state.

5. Call drm_atomic_helper_cleanup_planes() with state, which since step 3 contains the old state. Also do any other cleanup required with that state.

int drm_atomic_helper_update_plane(struct drm_plane * plane, struct drm_crtc * crtc, struct drm_framebuffer * fb, int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h)

Helper for primary plane update using atomic

Parameters

struct drm_plane * plane
plane object to update
struct drm_crtc * crtc
owning CRTC of owning plane
struct drm_framebuffer * fb
framebuffer to flip onto plane
int crtc_x
x offset of primary plane on crtc
int crtc_y
y offset of primary plane on crtc
unsigned int crtc_w
width of primary plane rectangle on crtc
unsigned int crtc_h
height of primary plane rectangle on crtc
uint32_t src_x
x offset of fb for panning
uint32_t src_y
y offset of fb for panning
uint32_t src_w
width of source rectangle in fb
uint32_t src_h
height of source rectangle in fb

Description

Provides a default plane update handler using the atomic driver interface.

Return

Zero on success, error code on failure

int drm_atomic_helper_disable_plane(struct drm_plane * plane)

Helper for primary plane disable using * atomic

Parameters

struct drm_plane * plane
plane to disable

Description

Provides a default plane disable handler using the atomic driver interface.

Return

Zero on success, error code on failure

int drm_atomic_helper_set_config(struct drm_mode_set * set)

set a new config from userspace

Parameters

struct drm_mode_set * set
mode set configuration

Description

Provides a default crtc set_config handler using the atomic driver interface.

Return

Returns 0 on success, negative errno numbers on failure.

int drm_atomic_helper_disable_all(struct drm_device * dev, struct drm_modeset_acquire_ctx * ctx)

disable all currently active outputs

Parameters

struct drm_device * dev
DRM device
struct drm_modeset_acquire_ctx * ctx
lock acquisition context

Description

Loops through all connectors, finding those that aren’t turned off and then turns them off by setting their DPMS mode to OFF and deactivating the CRTC that they are connected to.

This is used for example in suspend/resume to disable all currently active functions when suspending.

Note that if callers haven’t already acquired all modeset locks this might return -EDEADLK, which must be handled by calling drm_modeset_backoff().

Return

0 on success or a negative error code on failure.

See also: drm_atomic_helper_suspend(), drm_atomic_helper_resume()

struct drm_atomic_state * drm_atomic_helper_suspend(struct drm_device * dev)

subsystem-level suspend helper

Parameters

struct drm_device * dev
DRM device

Description

Duplicates the current atomic state, disables all active outputs and then returns a pointer to the original atomic state to the caller. Drivers can pass this pointer to the drm_atomic_helper_resume() helper upon resume to restore the output configuration that was active at the time the system entered suspend.

Note that it is potentially unsafe to use this. The atomic state object returned by this function is assumed to be persistent. Drivers must ensure that this holds true. Before calling this function, drivers must make sure to suspend fbdev emulation so that nothing can be using the device.

Return

A pointer to a copy of the state before suspend on success or an ERR_PTR()- encoded error code on failure. Drivers should store the returned atomic state object and pass it to the drm_atomic_helper_resume() helper upon resume.

See also: drm_atomic_helper_duplicate_state(), drm_atomic_helper_disable_all(), drm_atomic_helper_resume()

int drm_atomic_helper_resume(struct drm_device * dev, struct drm_atomic_state * state)

subsystem-level resume helper

Parameters

struct drm_device * dev
DRM device
struct drm_atomic_state * state
atomic state to resume to

Description

Calls drm_mode_config_reset() to synchronize hardware and software states, grabs all modeset locks and commits the atomic state object. This can be used in conjunction with the drm_atomic_helper_suspend() helper to implement suspend/resume for drivers that support atomic mode-setting.

Return

0 on success or a negative error code on failure.

See also: drm_atomic_helper_suspend()

int drm_atomic_helper_crtc_set_property(struct drm_crtc * crtc, struct drm_property * property, uint64_t val)

helper for crtc properties

Parameters

struct drm_crtc * crtc
DRM crtc
struct drm_property * property
DRM property
uint64_t val
value of property

Description

Provides a default crtc set_property handler using the atomic driver interface.

Return

Zero on success, error code on failure

int drm_atomic_helper_plane_set_property(struct drm_plane * plane, struct drm_property * property, uint64_t val)

helper for plane properties

Parameters

struct drm_plane * plane
DRM plane
struct drm_property * property
DRM property
uint64_t val
value of property

Description

Provides a default plane set_property handler using the atomic driver interface.

Return

Zero on success, error code on failure

int drm_atomic_helper_connector_set_property(struct drm_connector * connector, struct drm_property * property, uint64_t val)

helper for connector properties

Parameters

struct drm_connector * connector
DRM connector
struct drm_property * property
DRM property
uint64_t val
value of property

Description

Provides a default connector set_property handler using the atomic driver interface.

Return

Zero on success, error code on failure

int drm_atomic_helper_page_flip(struct drm_crtc * crtc, struct drm_framebuffer * fb, struct drm_pending_vblank_event * event, uint32_t flags)

execute a legacy page flip

Parameters

struct drm_crtc * crtc
DRM crtc
struct drm_framebuffer * fb
DRM framebuffer
struct drm_pending_vblank_event * event
optional DRM event to signal upon completion
uint32_t flags
flip flags for non-vblank sync’ed updates

Description

Provides a default page flip implementation using the atomic driver interface.

Note that for now so called async page flips (i.e. updates which are not synchronized to vblank) are not supported, since the atomic interfaces have no provisions for this yet.

Return

Returns 0 on success, negative errno numbers on failure.

int drm_atomic_helper_connector_dpms(struct drm_connector * connector, int mode)

connector dpms helper implementation

Parameters

struct drm_connector * connector
affected connector
int mode
DPMS mode

Description

This is the main helper function provided by the atomic helper framework for implementing the legacy DPMS connector interface. It computes the new desired ->active state for the corresponding CRTC (if the connector is enabled) and

updates it.

Return

Returns 0 on success, negative errno numbers on failure.

struct drm_encoder * drm_atomic_helper_best_encoder(struct drm_connector * connector)

Helper for drm_connector_helper_funcs ->best_encoder callback

Parameters

struct drm_connector * connector
Connector control structure

Description

This is a drm_connector_helper_funcs ->best_encoder callback helper for connectors that support exactly 1 encoder, statically determined at driver init time.

void drm_atomic_helper_crtc_reset(struct drm_crtc * crtc)

default ->reset hook for CRTCs

Parameters

struct drm_crtc * crtc
drm CRTC

Description

Resets the atomic state for crtc by freeing the state pointer (which might be NULL, e.g. at driver load time) and allocating a new empty state object.

void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc * crtc, struct drm_crtc_state * state)

copy atomic CRTC state

Parameters

struct drm_crtc * crtc
CRTC object
struct drm_crtc_state * state
atomic CRTC state

Description

Copies atomic state from a CRTC’s current state and resets inferred values. This is useful for drivers that subclass the CRTC state.

struct drm_crtc_state * drm_atomic_helper_crtc_duplicate_state(struct drm_crtc * crtc)

default state duplicate hook

Parameters

struct drm_crtc * crtc
drm CRTC

Description

Default CRTC state duplicate hook for drivers which don’t have their own subclassed CRTC state structure.

void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state * state)

release CRTC state

Parameters

struct drm_crtc_state * state
CRTC state object to release

Description

Releases all resources stored in the CRTC state without actually freeing the memory of the CRTC state. This is useful for drivers that subclass the CRTC state.

void drm_atomic_helper_crtc_destroy_state(struct drm_crtc * crtc, struct drm_crtc_state * state)

default state destroy hook

Parameters

struct drm_crtc * crtc
drm CRTC
struct drm_crtc_state * state
CRTC state object to release

Description

Default CRTC state destroy hook for drivers which don’t have their own subclassed CRTC state structure.

void drm_atomic_helper_plane_reset(struct drm_plane * plane)

default ->reset hook for planes

Parameters

struct drm_plane * plane
drm plane

Description

Resets the atomic state for plane by freeing the state pointer (which might be NULL, e.g. at driver load time) and allocating a new empty state object.

void __drm_atomic_helper_plane_duplicate_state(struct drm_plane * plane, struct drm_plane_state * state)

copy atomic plane state

Parameters

struct drm_plane * plane
plane object
struct drm_plane_state * state
atomic plane state

Description

Copies atomic state from a plane’s current state. This is useful for drivers that subclass the plane state.

struct drm_plane_state * drm_atomic_helper_plane_duplicate_state(struct drm_plane * plane)

default state duplicate hook

Parameters

struct drm_plane * plane
drm plane

Description

Default plane state duplicate hook for drivers which don’t have their own subclassed plane state structure.

void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state * state)

release plane state

Parameters

struct drm_plane_state * state
plane state object to release

Description

Releases all resources stored in the plane state without actually freeing the memory of the plane state. This is useful for drivers that subclass the plane state.

void drm_atomic_helper_plane_destroy_state(struct drm_plane * plane, struct drm_plane_state * state)

default state destroy hook

Parameters

struct drm_plane * plane
drm plane
struct drm_plane_state * state
plane state object to release

Description

Default plane state destroy hook for drivers which don’t have their own subclassed plane state structure.

void __drm_atomic_helper_connector_reset(struct drm_connector * connector, struct drm_connector_state * conn_state)

reset state on connector

Parameters

struct drm_connector * connector
drm connector
struct drm_connector_state * conn_state
connector state to assign

Description

Initializes the newly allocated conn_state and assigns it to #connector ->state, usually required when initializing the drivers or when called from the ->reset hook.

This is useful for drivers that subclass the connector state.

void drm_atomic_helper_connector_reset(struct drm_connector * connector)

default ->reset hook for connectors

Parameters

struct drm_connector * connector
drm connector

Description

Resets the atomic state for connector by freeing the state pointer (which might be NULL, e.g. at driver load time) and allocating a new empty state object.

void __drm_atomic_helper_connector_duplicate_state(struct drm_connector * connector, struct drm_connector_state * state)

copy atomic connector state

Parameters

struct drm_connector * connector
connector object
struct drm_connector_state * state
atomic connector state

Description

Copies atomic state from a connector’s current state. This is useful for drivers that subclass the connector state.

struct drm_connector_state * drm_atomic_helper_connector_duplicate_state(struct drm_connector * connector)

default state duplicate hook

Parameters

struct drm_connector * connector
drm connector

Description

Default connector state duplicate hook for drivers which don’t have their own subclassed connector state structure.

struct drm_atomic_state * drm_atomic_helper_duplicate_state(struct drm_device * dev, struct drm_modeset_acquire_ctx * ctx)

duplicate an atomic state object

Parameters

struct drm_device * dev
DRM device
struct drm_modeset_acquire_ctx * ctx
lock acquisition context

Description

Makes a copy of the current atomic state by looping over all objects and duplicating their respective states. This is used for example by suspend/ resume support code to save the state prior to suspend such that it can be restored upon resume.

Note that this treats atomic state as persistent between save and restore. Drivers must make sure that this is possible and won’t result in confusion or erroneous behaviour.

Note that if callers haven’t already acquired all modeset locks this might return -EDEADLK, which must be handled by calling drm_modeset_backoff().

Return

A pointer to the copy of the atomic state object on success or an ERR_PTR()-encoded error code on failure.

See also: drm_atomic_helper_suspend(), drm_atomic_helper_resume()

void __drm_atomic_helper_connector_destroy_state(struct drm_connector_state * state)

release connector state

Parameters

struct drm_connector_state * state
connector state object to release

Description

Releases all resources stored in the connector state without actually freeing the memory of the connector state. This is useful for drivers that subclass the connector state.

void drm_atomic_helper_connector_destroy_state(struct drm_connector * connector, struct drm_connector_state * state)

default state destroy hook

Parameters

struct drm_connector * connector
drm connector
struct drm_connector_state * state
connector state object to release

Description

Default connector state destroy hook for drivers which don’t have their own subclassed connector state structure.

void drm_atomic_helper_legacy_gamma_set(struct drm_crtc * crtc, u16 * red, u16 * green, u16 * blue, uint32_t start, uint32_t size)

set the legacy gamma correction table

Parameters

struct drm_crtc * crtc
CRTC object
u16 * red
red correction table
u16 * green
green correction table
u16 * blue
green correction table
uint32_t start
undescribed
uint32_t size
size of the tables

Description

Implements support for legacy gamma correction table for drivers that support color management through the DEGAMMA_LUT/GAMMA_LUT properties.

Modeset Helper Reference for Common Vtables

struct drm_crtc_helper_funcs

helper operations for CRTCs

Definition

struct drm_crtc_helper_funcs {
  void (* dpms) (struct drm_crtc *crtc, int mode);
  void (* prepare) (struct drm_crtc *crtc);
  void (* commit) (struct drm_crtc *crtc);
  bool (* mode_fixup) (struct drm_crtc *crtc,const struct drm_display_mode *mode,struct drm_display_mode *adjusted_mode);
  int (* mode_set) (struct drm_crtc *crtc, struct drm_display_mode *mode,struct drm_display_mode *adjusted_mode, int x, int y,struct drm_framebuffer *old_fb);
  void (* mode_set_nofb) (struct drm_crtc *crtc);
  int (* mode_set_base) (struct drm_crtc *crtc, int x, int y,struct drm_framebuffer *old_fb);
  int (* mode_set_base_atomic) (struct drm_crtc *crtc,struct drm_framebuffer *fb, int x, int y,enum mode_set_atomic);
  void (* load_lut) (struct drm_crtc *crtc);
  void (* disable) (struct drm_crtc *crtc);
  void (* enable) (struct drm_crtc *crtc);
  int (* atomic_check) (struct drm_crtc *crtc,struct drm_crtc_state *state);
  void (* atomic_begin) (struct drm_crtc *crtc,struct drm_crtc_state *old_crtc_state);
  void (* atomic_flush) (struct drm_crtc *crtc,struct drm_crtc_state *old_crtc_state);
};

Members

void (*)(struct drm_crtc *crtc, int mode) dpms

Callback to control power levels on the CRTC. If the mode passed in is unsupported, the provider must use the next lowest power level. This is used by the legacy CRTC helpers to implement DPMS functionality in drm_helper_connector_dpms().

This callback is also used to disable a CRTC by calling it with DRM_MODE_DPMS_OFF if the disable hook isn’t used.

This callback is used by the legacy CRTC helpers. Atomic helpers also support using this hook for enabling and disabling a CRTC to facilitate transitions to atomic, but it is deprecated. Instead enable and disable should be used.

void (*)(struct drm_crtc *crtc) prepare

This callback should prepare the CRTC for a subsequent modeset, which in practice means the driver should disable the CRTC if it is running. Most drivers ended up implementing this by calling their dpms hook with DRM_MODE_DPMS_OFF.

This callback is used by the legacy CRTC helpers. Atomic helpers also support using this hook for disabling a CRTC to facilitate transitions to atomic, but it is deprecated. Instead disable should be used.

void (*)(struct drm_crtc *crtc) commit

This callback should commit the new mode on the CRTC after a modeset, which in practice means the driver should enable the CRTC. Most drivers ended up implementing this by calling their dpms hook with DRM_MODE_DPMS_ON.

This callback is used by the legacy CRTC helpers. Atomic helpers also support using this hook for enabling a CRTC to facilitate transitions to atomic, but it is deprecated. Instead enable should be used.

bool (*)(struct drm_crtc *crtc,const struct drm_display_mode *mode,struct drm_display_mode *adjusted_mode) mode_fixup

This callback is used to validate a mode. The parameter mode is the display mode that userspace requested, adjusted_mode is the mode the encoders need to be fed with. Note that this is the inverse semantics of the meaning for the drm_encoder and drm_bridge ->:c:func:mode_fixup() functions. If the CRTC cannot support the requested conversion from mode to adjusted_mode it should reject the modeset.

This function is used by both legacy CRTC helpers and atomic helpers. With atomic helpers it is optional.

NOTE:

This function is called in the check phase of atomic modesets, which can be aborted for any reason (including on userspace’s request to just check whether a configuration would be possible). Atomic drivers MUST NOT touch any persistent state (hardware or software) or data structures except the passed in adjusted_mode parameter.

This is in contrast to the legacy CRTC helpers where this was allowed.

Atomic drivers which need to inspect and adjust more state should instead use the atomic_check callback.

Also beware that neither core nor helpers filter modes before passing them to the driver: While the list of modes that is advertised to userspace is filtered using the connector’s ->:c:func:mode_valid() callback, neither the core nor the helpers do any filtering on modes passed in from userspace when setting a mode. It is therefore possible for userspace to pass in a mode that was previously filtered out using ->:c:func:mode_valid() or add a custom mode that wasn’t probed from EDID or similar to begin with. Even though this is an advanced feature and rarely used nowadays, some users rely on being able to specify modes manually so drivers must be prepared to deal with it. Specifically this means that all drivers need not only validate modes in ->:c:func:mode_valid() but also in ->:c:func:mode_fixup() to make sure invalid modes passed in from userspace are rejected.

RETURNS:

True if an acceptable configuration is possible, false if the modeset operation should be rejected.

int (*)(struct drm_crtc *crtc, struct drm_display_mode *mode,struct drm_display_mode *adjusted_mode, int x, int y,struct drm_framebuffer *old_fb) mode_set

This callback is used by the legacy CRTC helpers to set a new mode, position and framebuffer. Since it ties the primary plane to every mode change it is incompatible with universal plane support. And since it can’t update other planes it’s incompatible with atomic modeset support.

This callback is only used by CRTC helpers and deprecated.

RETURNS:

0 on success or a negative error code on failure.

void (*)(struct drm_crtc *crtc) mode_set_nofb

This callback is used to update the display mode of a CRTC without changing anything of the primary plane configuration. This fits the requirement of atomic and hence is used by the atomic helpers. It is also used by the transitional plane helpers to implement a mode_set hook in drm_helper_crtc_mode_set().

Note that the display pipe is completely off when this function is called. Atomic drivers which need hardware to be running before they program the new display mode (e.g. because they implement runtime PM) should not use this hook. This is because the helper library calls this hook only once per mode change and not every time the display pipeline is suspended using either DPMS or the new “ACTIVE” property. Which means register values set in this callback might get reset when the CRTC is suspended, but not restored. Such drivers should instead move all their CRTC setup into the enable callback.

This callback is optional.

int (*)(struct drm_crtc *crtc, int x, int y,struct drm_framebuffer *old_fb) mode_set_base

This callback is used by the legacy CRTC helpers to set a new framebuffer and scanout position. It is optional and used as an optimized fast-path instead of a full mode set operation with all the resulting flickering. If it is not present drm_crtc_helper_set_config() will fall back to a full modeset, using the ->:c:func:mode_set() callback. Since it can’t update other planes it’s incompatible with atomic modeset support.

This callback is only used by the CRTC helpers and deprecated.

RETURNS:

0 on success or a negative error code on failure.

int (*)(struct drm_crtc *crtc,struct drm_framebuffer *fb, int x, int y,enum mode_set_atomic) mode_set_base_atomic

This callback is used by the fbdev helpers to set a new framebuffer and scanout without sleeping, i.e. from an atomic calling context. It is only used to implement kgdb support.

This callback is optional and only needed for kgdb support in the fbdev helpers.

RETURNS:

0 on success or a negative error code on failure.

void (*)(struct drm_crtc *crtc) load_lut

Load a LUT prepared with the gamma_set functions from drm_fb_helper_funcs.

This callback is optional and is only used by the fbdev emulation helpers.

FIXME:

This callback is functionally redundant with the core gamma table support and simply exists because the fbdev hasn’t yet been refactored to use the core gamma table interfaces.

void (*)(struct drm_crtc *crtc) disable

This callback should be used to disable the CRTC. With the atomic drivers it is called after all encoders connected to this CRTC have been shut off already using their own ->disable hook. If that sequence is too simple drivers can just add their own hooks and call it from this CRTC callback here by looping over all encoders connected to it using for_each_encoder_on_crtc().

This hook is used both by legacy CRTC helpers and atomic helpers. Atomic drivers don’t need to implement it if there’s no need to disable anything at the CRTC level. To ensure that runtime PM handling (using either DPMS or the new “ACTIVE” property) works disable must be the inverse of enable for atomic drivers.

NOTE:

With legacy CRTC helpers there’s a big semantic difference between disable and other hooks (like prepare or dpms) used to shut down a CRTC: disable is only called when also logically disabling the display pipeline and needs to release any resources acquired in mode_set (like shared PLLs, or again release pinned framebuffers).

Therefore disable must be the inverse of mode_set plus commit for drivers still using legacy CRTC helpers, which is different from the rules under atomic.

void (*)(struct drm_crtc *crtc) enable

This callback should be used to enable the CRTC. With the atomic drivers it is called before all encoders connected to this CRTC are enabled through the encoder’s own ->enable hook. If that sequence is too simple drivers can just add their own hooks and call it from this CRTC callback here by looping over all encoders connected to it using for_each_encoder_on_crtc().

This hook is used only by atomic helpers, for symmetry with disable. Atomic drivers don’t need to implement it if there’s no need to enable anything at the CRTC level. To ensure that runtime PM handling (using either DPMS or the new “ACTIVE” property) works enable must be the inverse of disable for atomic drivers.

int (*)(struct drm_crtc *crtc,struct drm_crtc_state *state) atomic_check

Drivers should check plane-update related CRTC constraints in this hook. They can also check mode related limitations but need to be aware of the calling order, since this hook is used by drm_atomic_helper_check_planes() whereas the preparations needed to check output routing and the display mode is done in drm_atomic_helper_check_modeset(). Therefore drivers that want to check output routing and display mode constraints in this callback must ensure that drm_atomic_helper_check_modeset() has been called beforehand. This is calling order used by the default helper implementation in drm_atomic_helper_check().

When using drm_atomic_helper_check_planes() CRTCs’ ->:c:func:atomic_check() hooks are called after the ones for planes, which allows drivers to assign shared resources requested by planes in the CRTC callback 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:c:type: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 and by the transitional plane 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 free-standing state objects passed-in or assembled in the overall drm_atomic_state 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.

void (*)(struct drm_crtc *crtc,struct drm_crtc_state *old_crtc_state) atomic_begin

Drivers should prepare for an atomic update of multiple planes on a CRTC in this hook. Depending upon hardware this might be vblank evasion, blocking updates by setting bits or doing preparatory work for e.g. manual update display.

This hook is called before any plane commit functions are called.

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_commit_planes() for a discussion of the tradeoffs and variants of plane commit helpers.

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

void (*)(struct drm_crtc *crtc,struct drm_crtc_state *old_crtc_state) atomic_flush

Drivers should finalize an atomic update of multiple planes on a CRTC in this hook. Depending upon hardware this might include checking that vblank evasion was successful, unblocking updates by setting bits or setting the GO bit to flush out all updates.

Simple hardware or hardware with special requirements can commit and flush out all updates for all planes from this hook and forgo all the other commit hooks for plane updates.

This hook is called after any plane commit functions are called.

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_commit_planes() for a discussion of the tradeoffs and variants of plane commit helpers.

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

Description

These hooks are used by the legacy CRTC helpers, the transitional plane helpers and the new atomic modesetting helpers.

void drm_crtc_helper_add(struct drm_crtc * crtc, const struct drm_crtc_helper_funcs * funcs)

sets the helper vtable for a crtc

Parameters

struct drm_crtc * crtc
DRM CRTC
const struct drm_crtc_helper_funcs * funcs
helper vtable to set for crtc
struct drm_encoder_helper_funcs

helper operations for encoders

Definition

struct drm_encoder_helper_funcs {
  void (* dpms) (struct drm_encoder *encoder, int mode);
  bool (* mode_fixup) (struct drm_encoder *encoder,const struct drm_display_mode *mode,struct drm_display_mode *adjusted_mode);
  void (* prepare) (struct drm_encoder *encoder);
  void (* commit) (struct drm_encoder *encoder);
  void (* mode_set) (struct drm_encoder *encoder,struct drm_display_mode *mode,struct drm_display_mode *adjusted_mode);
  struct drm_crtc *(* get_crtc) (struct drm_encoder *encoder);
  enum drm_connector_status (* detect) (struct drm_encoder *encoder,struct drm_connector *connector);
  void (* disable) (struct drm_encoder *encoder);
  void (* enable) (struct drm_encoder *encoder);
  int (* atomic_check) (struct drm_encoder *encoder,struct drm_crtc_state *crtc_state,struct drm_connector_state *conn_state);
};

Members

void (*)(struct drm_encoder *encoder, int mode) dpms

Callback to control power levels on the encoder. If the mode passed in is unsupported, the provider must use the next lowest power level. This is used by the legacy encoder helpers to implement DPMS functionality in drm_helper_connector_dpms().

This callback is also used to disable an encoder by calling it with DRM_MODE_DPMS_OFF if the disable hook isn’t used.

This callback is used by the legacy CRTC helpers. Atomic helpers also support using this hook for enabling and disabling an encoder to facilitate transitions to atomic, but it is deprecated. Instead enable and disable should be used.

bool (*)(struct drm_encoder *encoder,const struct drm_display_mode *mode,struct drm_display_mode *adjusted_mode) mode_fixup

This callback is used to validate and adjust a mode. The parameter mode is the display mode that should be fed to the next element in the display chain, either the final drm_connector or a drm_bridge. The parameter adjusted_mode is the input mode the encoder requires. It can be modified by this callback and does not need to match mode.

This function is used by both legacy CRTC helpers and atomic helpers. This hook is optional.

NOTE:

This function is called in the check phase of atomic modesets, which can be aborted for any reason (including on userspace’s request to just check whether a configuration would be possible). Atomic drivers MUST NOT touch any persistent state (hardware or software) or data structures except the passed in adjusted_mode parameter.

This is in contrast to the legacy CRTC helpers where this was allowed.

Atomic drivers which need to inspect and adjust more state should instead use the atomic_check callback.

Also beware that neither core nor helpers filter modes before passing them to the driver: While the list of modes that is advertised to userspace is filtered using the connector’s ->:c:func:mode_valid() callback, neither the core nor the helpers do any filtering on modes passed in from userspace when setting a mode. It is therefore possible for userspace to pass in a mode that was previously filtered out using ->:c:func:mode_valid() or add a custom mode that wasn’t probed from EDID or similar to begin with. Even though this is an advanced feature and rarely used nowadays, some users rely on being able to specify modes manually so drivers must be prepared to deal with it. Specifically this means that all drivers need not only validate modes in ->:c:func:mode_valid() but also in ->:c:func:mode_fixup() to make sure invalid modes passed in from userspace are rejected.

RETURNS:

True if an acceptable configuration is possible, false if the modeset operation should be rejected.

void (*)(struct drm_encoder *encoder) prepare

This callback should prepare the encoder for a subsequent modeset, which in practice means the driver should disable the encoder if it is running. Most drivers ended up implementing this by calling their dpms hook with DRM_MODE_DPMS_OFF.

This callback is used by the legacy CRTC helpers. Atomic helpers also support using this hook for disabling an encoder to facilitate transitions to atomic, but it is deprecated. Instead disable should be used.

void (*)(struct drm_encoder *encoder) commit

This callback should commit the new mode on the encoder after a modeset, which in practice means the driver should enable the encoder. Most drivers ended up implementing this by calling their dpms hook with DRM_MODE_DPMS_ON.

This callback is used by the legacy CRTC helpers. Atomic helpers also support using this hook for enabling an encoder to facilitate transitions to atomic, but it is deprecated. Instead enable should be used.

void (*)(struct drm_encoder *encoder,struct drm_display_mode *mode,struct drm_display_mode *adjusted_mode) mode_set

This callback is used to update the display mode of an encoder.

Note that the display pipe is completely off when this function is called. Drivers which need hardware to be running before they program the new display mode (because they implement runtime PM) should not use this hook, because the helper library calls it only once and not every time the display pipeline is suspend using either DPMS or the new “ACTIVE” property. Such drivers should instead move all their encoder setup into the ->:c:func:enable() callback.

This callback is used both by the legacy CRTC helpers and the atomic modeset helpers. It is optional in the atomic helpers.

struct drm_crtc *(*)(struct drm_encoder *encoder) get_crtc

This callback is used by the legacy CRTC helpers to work around deficiencies in its own book-keeping.

Do not use, use atomic helpers instead, which get the book keeping right.

FIXME:

Currently only nouveau is using this, and as soon as nouveau is atomic we can ditch this hook.

enum drm_connector_status (*)(struct drm_encoder *encoder,struct drm_connector *connector) detect

This callback can be used by drivers who want to do detection on the encoder object instead of in connector functions.

It is not used by any helper and therefore has purely driver-specific semantics. New drivers shouldn’t use this and instead just implement their own private callbacks.

FIXME:

This should just be converted into a pile of driver vfuncs. Currently radeon, amdgpu and nouveau are using it.

void (*)(struct drm_encoder *encoder) disable

This callback should be used to disable the encoder. With the atomic drivers it is called before this encoder’s CRTC has been shut off using the CRTC’s own ->disable hook. If that sequence is too simple drivers can just add their own driver private encoder hooks and call them from CRTC’s callback by looping over all encoders connected to it using for_each_encoder_on_crtc().

This hook is used both by legacy CRTC helpers and atomic helpers. Atomic drivers don’t need to implement it if there’s no need to disable anything at the encoder level. To ensure that runtime PM handling (using either DPMS or the new “ACTIVE” property) works disable must be the inverse of enable for atomic drivers.

NOTE:

With legacy CRTC helpers there’s a big semantic difference between disable and other hooks (like prepare or dpms) used to shut down a encoder: disable is only called when also logically disabling the display pipeline and needs to release any resources acquired in mode_set (like shared PLLs, or again release pinned framebuffers).

Therefore disable must be the inverse of mode_set plus commit for drivers still using legacy CRTC helpers, which is different from the rules under atomic.

void (*)(struct drm_encoder *encoder) enable

This callback should be used to enable the encoder. With the atomic drivers it is called after this encoder’s CRTC has been enabled using the CRTC’s own ->enable hook. If that sequence is too simple drivers can just add their own driver private encoder hooks and call them from CRTC’s callback by looping over all encoders connected to it using for_each_encoder_on_crtc().

This hook is used only by atomic helpers, for symmetry with disable. Atomic drivers don’t need to implement it if there’s no need to enable anything at the encoder level. To ensure that runtime PM handling (using either DPMS or the new “ACTIVE” property) works enable must be the inverse of disable for atomic drivers.

int (*)(struct drm_encoder *encoder,struct drm_crtc_state *crtc_state,struct drm_connector_state *conn_state) atomic_check

This callback is used to validate encoder state for atomic drivers. Since the encoder is the object connecting the CRTC and connector it gets passed both states, to be able to validate interactions and update the CRTC to match what the encoder needs for the requested connector.

This function is used by the atomic 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 free-standing state objects passed-in or assembled in the overall drm_atomic_state 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.

Description

These hooks are used by the legacy CRTC helpers, the transitional plane helpers and the new atomic modesetting helpers.

void drm_encoder_helper_add(struct drm_encoder * encoder, const struct drm_encoder_helper_funcs * funcs)

sets the helper vtable for an encoder

Parameters

struct drm_encoder * encoder
DRM encoder
const struct drm_encoder_helper_funcs * funcs
helper vtable to set for encoder
struct drm_connector_helper_funcs

helper operations for connectors

Definition

struct drm_connector_helper_funcs {
  int (* get_modes) (struct drm_connector *connector);
  enum drm_mode_status (* mode_valid) (struct drm_connector *connector,struct drm_display_mode *mode);
  struct drm_encoder *(* best_encoder) (struct drm_connector *connector);
  struct drm_encoder *(* atomic_best_encoder) (struct drm_connector *connector,struct drm_connector_state *connector_state);
};

Members

int (*)(struct drm_connector *connector) get_modes

This function should fill in all modes currently valid for the sink into the connector->probed_modes list. It should also update the EDID property by calling drm_mode_connector_update_edid_property().

The usual way to implement this is to cache the EDID retrieved in the probe callback somewhere in the driver-private connector structure. In this function drivers then parse the modes in the EDID and add them by calling drm_add_edid_modes(). But connectors that driver a fixed panel can also manually add specific modes using drm_mode_probed_add(). Drivers which manually add modes should also make sure that the display_info, width_mm and height_mm fields of the struct drm_connector are filled in.

Virtual drivers that just want some standard VESA mode with a given resolution can call drm_add_modes_noedid(), and mark the preferred one using drm_set_preferred_mode().

Finally drivers that support audio probably want to update the ELD data, too, using drm_edid_to_eld().

This function is only called after the ->:c:func:detect() hook has indicated that a sink is connected and when the EDID isn’t overridden through sysfs or the kernel commandline.

This callback is used by the probe helpers in e.g. drm_helper_probe_single_connector_modes().

RETURNS:

The number of modes added by calling drm_mode_probed_add().

enum drm_mode_status (*)(struct drm_connector *connector,struct drm_display_mode *mode) mode_valid

Callback to validate a mode for a connector, irrespective of the specific display configuration.

This callback is used by the probe helpers to filter the mode list (which is usually derived from the EDID data block from the sink). See e.g. drm_helper_probe_single_connector_modes().

NOTE:

This only filters the mode list supplied to userspace in the GETCONNECOTR IOCTL. Userspace is free to create modes of its own and ask the kernel to use them. It this case the atomic helpers or legacy CRTC helpers will not call this function. Drivers therefore must still fully validate any mode passed in in a modeset request.

RETURNS:

Either MODE_OK or one of the failure reasons in enum drm_mode_status.

struct drm_encoder *(*)(struct drm_connector *connector) best_encoder

This function should select the best encoder for the given connector.

This function is used by both the atomic helpers (in the drm_atomic_helper_check_modeset() function) and in the legacy CRTC helpers.

NOTE:

In atomic drivers this function is called in the check phase of an atomic update. The driver is not allowed to change or inspect anything outside of arguments passed-in. Atomic drivers which need to inspect dynamic configuration state should instead use atomic_best_encoder.

RETURNS:

Encoder that should be used for the given connector and connector state, or NULL if no suitable encoder exists. Note that the helpers will ensure that encoders aren’t used twice, drivers should not check for this.

struct drm_encoder *(*)(struct drm_connector *connector,struct drm_connector_state *connector_state) atomic_best_encoder

This is the atomic version of best_encoder for atomic drivers which need to select the best encoder depending upon the desired configuration and can’t select it statically.

This function is used by drm_atomic_helper_check_modeset() and either this or best_encoder is required.

NOTE:

This function is called in the check phase of an atomic update. The driver is not allowed to change anything outside of the free-standing state objects passed-in or assembled in the overall drm_atomic_state update tracking structure.

RETURNS:

Encoder that should be used for the given connector and connector state, or NULL if no suitable encoder exists. Note that the helpers will ensure that encoders aren’t used twice, drivers should not check for this.

Description

These functions are used by the atomic and legacy modeset helpers and by the probe helpers.

void drm_connector_helper_add(struct drm_connector * connector, const struct drm_connector_helper_funcs * funcs)

sets the helper vtable for a connector

Parameters

struct drm_connector * connector
DRM connector
const struct drm_connector_helper_funcs * funcs
helper vtable to set for connector
struct drm_plane_helper_funcs

helper operations for planes

Definition

struct drm_plane_helper_funcs {
  int (* prepare_fb) (struct drm_plane *plane,const struct drm_plane_state *new_state);
  void (* cleanup_fb) (struct drm_plane *plane,const struct drm_plane_state *old_state);
  int (* atomic_check) (struct drm_plane *plane,struct drm_plane_state *state);
  void (* atomic_update) (struct drm_plane *plane,struct drm_plane_state *old_state);
  void (* atomic_disable) (struct drm_plane *plane,struct drm_plane_state *old_state);
};

Members

int (*)(struct drm_plane *plane,const struct drm_plane_state *new_state) prepare_fb

This hook is to prepare a framebuffer for scanout by e.g. pinning it’s backing storage or relocating it into a contiguous block of VRAM. Other possible preparatory work includes flushing caches.

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 fence member 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.

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 and by the transitional plane helpers, but it is optional.

RETURNS:

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

void (*)(struct drm_plane *plane,const struct drm_plane_state *old_state) 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 and by the transitional plane helpers, but it is optional.

int (*)(struct drm_plane *plane,struct drm_plane_state *state) atomic_check

Drivers should check plane specific constraints in this hook.

When using drm_atomic_helper_check_planes() plane’s ->:c:func: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:c:type: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 and by the transitional plane 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 free-standing state objects passed-in or assembled in the overall drm_atomic_state 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.

void (*)(struct drm_plane *plane,struct drm_plane_state *old_state) atomic_update

Drivers should use this function to update the plane state. This hook is called in-between the ->:c:func:atomic_begin() and ->:c:func:atomic_flush() of drm_crtc_helper_funcs.

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_commit_planes() for a discussion of the tradeoffs and variants of plane commit helpers.

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

void (*)(struct drm_plane *plane,struct drm_plane_state *old_state) atomic_disable

Drivers should use this function to unconditionally disable a plane. This hook is called in-between the ->:c:func:atomic_begin() and ->:c:func:atomic_flush() of drm_crtc_helper_funcs. 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 ->:c:func:disable() hook in drm_crtc_helper_funcs.

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_commit_planes() for a discussion of the tradeoffs and variants of plane commit helpers.

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

Description

These functions are used by the atomic helpers and by the transitional plane helpers.

void drm_plane_helper_add(struct drm_plane * plane, const struct drm_plane_helper_funcs * funcs)

sets the helper vtable for a plane

Parameters

struct drm_plane * plane
DRM plane
const struct drm_plane_helper_funcs * funcs
helper vtable to set for plane

The DRM mode setting helper functions are common code for drivers to use if they wish. Drivers are not forced to use this code in their implementations but it would be useful if the code they do use at least provides a consistent interface and operation to userspace. Therefore it is highly recommended to use the provided helpers as much as possible.

Because there is only one pointer per modeset object to hold a vfunc table for helper libraries they are by necessity shared among the different helpers.

To make this clear all the helper vtables are pulled together in this location here.

Legacy CRTC/Modeset Helper Functions Reference

void drm_helper_move_panel_connectors_to_head(struct drm_device * dev)

move panels to the front in the connector list

Parameters

struct drm_device * dev
drm device to operate on

Description

Some userspace presumes that the first connected connector is the main display, where it’s supposed to display e.g. the login screen. For laptops, this should be the main panel. Use this function to sort all (eDP/LVDS) panels to the front of the connector list, instead of painstakingly trying to initialize them in the right order.

bool drm_helper_encoder_in_use(struct drm_encoder * encoder)

check if a given encoder is in use

Parameters

struct drm_encoder * encoder
encoder to check

Description

Checks whether encoder is with the current mode setting output configuration in use by any connector. This doesn’t mean that it is actually enabled since the DPMS state is tracked separately.

Return

True if encoder is used, false otherwise.

bool drm_helper_crtc_in_use(struct drm_crtc * crtc)

check if a given CRTC is in a mode_config

Parameters

struct drm_crtc * crtc
CRTC to check

Description

Checks whether crtc is with the current mode setting output configuration in use by any connector. This doesn’t mean that it is actually enabled since the DPMS state is tracked separately.

Return

True if crtc is used, false otherwise.

void drm_helper_disable_unused_functions(struct drm_device * dev)

disable unused objects

Parameters

struct drm_device * dev
DRM device

Description

This function walks through the entire mode setting configuration of dev. It will remove any CRTC links of unused encoders and encoder links of disconnected connectors. Then it will disable all unused encoders and CRTCs either by calling their disable callback if available or by calling their dpms callback with DRM_MODE_DPMS_OFF.

NOTE

This function is part of the legacy modeset helper library and will cause major confusion with atomic drivers. This is because atomic helpers guarantee to never call ->:c:func:disable() hooks on a disabled function, or ->:c:func:enable() hooks on an enabled functions. drm_helper_disable_unused_functions() on the other hand throws such guarantees into the wind and calls disable hooks unconditionally on unused functions.

bool drm_crtc_helper_set_mode(struct drm_crtc * crtc, struct drm_display_mode * mode, int x, int y, struct drm_framebuffer * old_fb)

internal helper to set a mode

Parameters

struct drm_crtc * crtc
CRTC to program
struct drm_display_mode * mode
mode to use
int x
horizontal offset into the surface
int y
vertical offset into the surface
struct drm_framebuffer * old_fb
old framebuffer, for cleanup

Description

Try to set mode on crtc. Give crtc and its associated connectors a chance to fixup or reject the mode prior to trying to set it. This is an internal helper that drivers could e.g. use to update properties that require the entire output pipe to be disabled and re-enabled in a new configuration. For example for changing whether audio is enabled on a hdmi link or for changing panel fitter or dither attributes. It is also called by the drm_crtc_helper_set_config() helper function to drive the mode setting sequence.

Return

True if the mode was set successfully, false otherwise.

int drm_crtc_helper_set_config(struct drm_mode_set * set)

set a new config from userspace

Parameters

struct drm_mode_set * set
mode set configuration

Description

The drm_crtc_helper_set_config() helper function implements the set_config callback of struct drm_crtc_funcs for drivers using the legacy CRTC helpers.

It first tries to locate the best encoder for each connector by calling the connector ->:c:func:best_encoder() (struct drm_connector_helper_funcs) helper operation.

After locating the appropriate encoders, the helper function will call the mode_fixup encoder and CRTC helper operations to adjust the requested mode, or reject it completely in which case an error will be returned to the application. If the new configuration after mode adjustment is identical to the current configuration the helper function will return without performing any other operation.

If the adjusted mode is identical to the current mode but changes to the frame buffer need to be applied, the drm_crtc_helper_set_config() function will call the CRTC ->:c:func:mode_set_base() (struct drm_crtc_helper_funcs) helper operation.

If the adjusted mode differs from the current mode, or if the ->:c:func:mode_set_base() helper operation is not provided, the helper function performs a full mode set sequence by calling the ->:c:func:prepare(), ->:c:func:mode_set() and ->:c:func:commit() CRTC and encoder helper operations, in that order. Alternatively it can also use the dpms and disable helper operations. For details see struct drm_crtc_helper_funcs and struct drm_encoder_helper_funcs.

This function is deprecated. New drivers must implement atomic modeset support, for which this function is unsuitable. Instead drivers should use drm_atomic_helper_set_config().

Return

Returns 0 on success, negative errno numbers on failure.

int drm_helper_connector_dpms(struct drm_connector * connector, int mode)

connector dpms helper implementation

Parameters

struct drm_connector * connector
affected connector
int mode
DPMS mode

Description

The drm_helper_connector_dpms() helper function implements the ->:c:func:dpms() callback of struct drm_connector_funcs for drivers using the legacy CRTC helpers.

This is the main helper function provided by the CRTC helper framework for implementing the DPMS connector attribute. It computes the new desired DPMS state for all encoders and CRTCs in the output mesh and calls the ->:c:func:dpms() callbacks provided by the driver in struct drm_crtc_helper_funcs and struct drm_encoder_helper_funcs appropriately.

This function is deprecated. New drivers must implement atomic modeset support, for which this function is unsuitable. Instead drivers should use drm_atomic_helper_connector_dpms().

Return

Always returns 0.

void drm_helper_mode_fill_fb_struct(struct drm_framebuffer * fb, const struct drm_mode_fb_cmd2 * mode_cmd)

fill out framebuffer metadata

Parameters

struct drm_framebuffer * fb
drm_framebuffer object to fill out
const struct drm_mode_fb_cmd2 * mode_cmd
metadata from the userspace fb creation request

Description

This helper can be used in a drivers fb_create callback to pre-fill the fb’s metadata fields.

void drm_helper_resume_force_mode(struct drm_device * dev)

force-restore mode setting configuration

Parameters

struct drm_device * dev
drm_device which should be restored

Description

Drivers which use the mode setting helpers can use this function to force-restore the mode setting configuration e.g. on resume or when something else might have trampled over the hw state (like some overzealous old BIOSen tended to do).

This helper doesn’t provide a error return value since restoring the old config should never fail due to resource allocation issues since the driver has successfully set the restored configuration already. Hence this should boil down to the equivalent of a few dpms on calls, which also don’t provide an error code.

Drivers where simply restoring an old configuration again might fail (e.g. due to slight differences in allocating shared resources when the configuration is restored in a different order than when userspace set it up) need to use their own restore logic.

This function is deprecated. New drivers should implement atomic mode- setting and use the atomic suspend/resume helpers.

See also: drm_atomic_helper_suspend(), drm_atomic_helper_resume()

int drm_helper_crtc_mode_set(struct drm_crtc * crtc, struct drm_display_mode * mode, struct drm_display_mode * adjusted_mode, int x, int y, struct drm_framebuffer * old_fb)

mode_set implementation for atomic plane helpers

Parameters

struct drm_crtc * crtc
DRM CRTC
struct drm_display_mode * mode
DRM display mode which userspace requested
struct drm_display_mode * adjusted_mode
DRM display mode adjusted by ->mode_fixup callbacks
int x
x offset of the CRTC scanout area on the underlying framebuffer
int y
y offset of the CRTC scanout area on the underlying framebuffer
struct drm_framebuffer * old_fb
previous framebuffer

Description

This function implements a callback useable as the ->mode_set callback required by the CRTC helpers. Besides the atomic plane helper functions for the primary plane the driver must also provide the ->mode_set_nofb callback to set up the CRTC.

This is a transitional helper useful for converting drivers to the atomic interfaces.

int drm_helper_crtc_mode_set_base(struct drm_crtc * crtc, int x, int y, struct drm_framebuffer * old_fb)

mode_set_base implementation for atomic plane helpers

Parameters

struct drm_crtc * crtc
DRM CRTC
int x
x offset of the CRTC scanout area on the underlying framebuffer
int y
y offset of the CRTC scanout area on the underlying framebuffer
struct drm_framebuffer * old_fb
previous framebuffer

Description

This function implements a callback useable as the ->mode_set_base used required by the CRTC helpers. The driver must provide the atomic plane helper functions for the primary plane.

This is a transitional helper useful for converting drivers to the atomic interfaces.

void drm_helper_crtc_enable_color_mgmt(struct drm_crtc * crtc, int degamma_lut_size, int gamma_lut_size)

enable color management properties

Parameters

struct drm_crtc * crtc
DRM CRTC
int degamma_lut_size
the size of the degamma lut (before CSC)
int gamma_lut_size
the size of the gamma lut (after CSC)

Description

This function lets the driver enable the color correction properties on a CRTC. This includes 3 degamma, csc and gamma properties that userspace can set and 2 size properties to inform the userspace of the lut sizes.

The CRTC modeset helper library provides a default set_config implementation in drm_crtc_helper_set_config(). Plus a few other convenience functions using the same callbacks which drivers can use to e.g. restore the modeset configuration on resume with drm_helper_resume_force_mode().

Note that this helper library doesn’t track the current power state of CRTCs and encoders. It can call callbacks like ->:c:func:dpms() even though the hardware is already in the desired state. This deficiency has been fixed in the atomic helpers.

The driver callbacks are mostly compatible with the atomic modeset helpers, except for the handling of the primary plane: Atomic helpers require that the primary plane is implemented as a real standalone plane and not directly tied to the CRTC state. For easier transition this library provides functions to implement the old semantics required by the CRTC helpers using the new plane and atomic helper callbacks.

Drivers are strongly urged to convert to the atomic helpers (by way of first converting to the plane helpers). New drivers must not use these functions but need to implement the atomic interface instead, potentially using the atomic helpers for that.

These legacy modeset helpers use the same function table structures as all other modesetting helpers. See the documentation for struct drm_crtc_helper_funcs, struct drm_encoder_helper_funcs and struct drm_connector_helper_funcs.

Output Probing Helper Functions Reference

This library provides some helper code for output probing. It provides an implementation of the core connector->fill_modes interface with drm_helper_probe_single_connector_modes.

It also provides support for polling connectors with a work item and for generic hotplug interrupt handling where the driver doesn’t or cannot keep track of a per-connector hpd interrupt.

This helper library can be used independently of the modeset helper library. Drivers can also overwrite different parts e.g. use their own hotplug handling code to avoid probing unrelated outputs.

The probe helpers share the function table structures with other display helper libraries. See struct drm_connector_helper_funcs for the details.

void drm_kms_helper_poll_enable_locked(struct drm_device * dev)

re-enable output polling.

Parameters

struct drm_device * dev
drm_device

Description

This function re-enables the output polling work without locking the mode_config mutex.

This is like drm_kms_helper_poll_enable() however it is to be called from a context where the mode_config mutex is locked already.

int drm_helper_probe_single_connector_modes(struct drm_connector * connector, uint32_t maxX, uint32_t maxY)

get complete set of display modes

Parameters

struct drm_connector * connector
connector to probe
uint32_t maxX
max width for modes
uint32_t maxY
max height for modes

Description

Based on the helper callbacks implemented by connector in struct drm_connector_helper_funcs try to detect all valid modes. Modes will first be added to the connector’s probed_modes list, then culled (based on validity and the maxX, maxY parameters) and put into the normal modes list.

Intended to be used as a generic implementation of the ->:c:func:fill_modes() connector vfunc for drivers that use the CRTC helpers for output mode filtering and detection.

The basic procedure is as follows

  1. All modes currently on the connector’s modes list are marked as stale

  2. New modes are added to the connector’s probed_modes list with drm_mode_probed_add(). New modes start their life with status as OK. Modes are added from a single source using the following priority order.

    • debugfs ‘override_edid’ (used for testing only)
    • firmware EDID (drm_load_edid_firmware())
    • connector helper ->:c:func:get_modes() vfunc
    • if the connector status is connector_status_connected, standard VESA DMT modes up to 1024x768 are automatically added (drm_add_modes_noedid())

    Finally modes specified via the kernel command line (video=...) are added in addition to what the earlier probes produced (drm_helper_probe_add_cmdline_mode()). These modes are generated using the VESA GTF/CVT formulas.

  3. Modes are moved from the probed_modes list to the modes list. Potential duplicates are merged together (see drm_mode_connector_list_update()). After this step the probed_modes list will be empty again.

  4. Any non-stale mode on the modes list then undergoes validation

    • drm_mode_validate_basic() performs basic sanity checks
    • drm_mode_validate_size() filters out modes larger than maxX and maxY (if specified)
    • drm_mode_validate_flag() checks the modes againt basic connector capabilites (interlace_allowed,doublescan_allowed,stereo_allowed)
    • the optional connector ->:c:func:mode_valid() helper can perform driver and/or hardware specific checks
  5. Any mode whose status is not OK is pruned from the connector’s modes list, accompanied by a debug message indicating the reason for the mode’s rejection (see drm_mode_prune_invalid()).

Return

The number of modes found on connector.

void drm_kms_helper_hotplug_event(struct drm_device * dev)

fire off KMS hotplug events

Parameters

struct drm_device * dev
drm_device whose connector state changed

Description

This function fires off the uevent for userspace and also calls the output_poll_changed function, which is most commonly used to inform the fbdev emulation code and allow it to update the fbcon output configuration.

Drivers should call this from their hotplug handling code when a change is detected. Note that this function does not do any output detection of its own, like drm_helper_hpd_irq_event() does - this is assumed to be done by the driver already.

This function must be called from process context with no mode setting locks held.

void drm_kms_helper_poll_disable(struct drm_device * dev)

disable output polling

Parameters

struct drm_device * dev
drm_device

Description

This function disables the output polling work.

Drivers can call this helper from their device suspend implementation. It is not an error to call this even when output polling isn’t enabled or arlready disabled.

void drm_kms_helper_poll_enable(struct drm_device * dev)

re-enable output polling.

Parameters

struct drm_device * dev
drm_device

Description

This function re-enables the output polling work.

Drivers can call this helper from their device resume implementation. It is an error to call this when the output polling support has not yet been set up.

void drm_kms_helper_poll_init(struct drm_device * dev)

initialize and enable output polling

Parameters

struct drm_device * dev
drm_device

Description

This function intializes and then also enables output polling support for dev. Drivers which do not have reliable hotplug support in hardware can use this helper infrastructure to regularly poll such connectors for changes in their connection state.

Drivers can control which connectors are polled by setting the DRM_CONNECTOR_POLL_CONNECT and DRM_CONNECTOR_POLL_DISCONNECT flags. On connectors where probing live outputs can result in visual distortion drivers should not set the DRM_CONNECTOR_POLL_DISCONNECT flag to avoid this. Connectors which have no flag or only DRM_CONNECTOR_POLL_HPD set are completely ignored by the polling logic.

Note that a connector can be both polled and probed from the hotplug handler, in case the hotplug interrupt is known to be unreliable.

void drm_kms_helper_poll_fini(struct drm_device * dev)

disable output polling and clean it up

Parameters

struct drm_device * dev
drm_device
bool drm_helper_hpd_irq_event(struct drm_device * dev)

hotplug processing

Parameters

struct drm_device * dev
drm_device

Description

Drivers can use this helper function to run a detect cycle on all connectors which have the DRM_CONNECTOR_POLL_HPD flag set in their polled member. All other connectors are ignored, which is useful to avoid reprobing fixed panels.

This helper function is useful for drivers which can’t or don’t track hotplug interrupts for each connector.

Drivers which support hotplug interrupts for each connector individually and which have a more fine-grained detect logic should bypass this code and directly call drm_kms_helper_hotplug_event() in case the connector state changed.

This function must be called from process context with no mode setting locks held.

Note that a connector can be both polled and probed from the hotplug handler, in case the hotplug interrupt is known to be unreliable.

fbdev Helper Functions Reference

The fb helper functions are useful to provide an fbdev on top of a drm kernel mode setting driver. They can be used mostly independently from the crtc helper functions used by many drivers to implement the kernel mode setting interfaces.

Initialization is done as a four-step process with drm_fb_helper_prepare(), drm_fb_helper_init(), drm_fb_helper_single_add_all_connectors() and drm_fb_helper_initial_config(). Drivers with fancier requirements than the default behaviour can override the third step with their own code. Teardown is done with drm_fb_helper_fini().

At runtime drivers should restore the fbdev console by calling drm_fb_helper_restore_fbdev_mode_unlocked() from their ->lastclose callback. They should also notify the fb helper code from updates to the output configuration by calling drm_fb_helper_hotplug_event(). For easier integration with the output polling code in drm_crtc_helper.c the modeset code provides a ->output_poll_changed callback.

All other functions exported by the fb helper library can be used to implement the fbdev driver interface by the driver.

It is possible, though perhaps somewhat tricky, to implement race-free hotplug detection using the fbdev helpers. The drm_fb_helper_prepare() helper must be called first to initialize the minimum required to make hotplug detection work. Drivers also need to make sure to properly set up the dev->mode_config.funcs member. After calling drm_kms_helper_poll_init() it is safe to enable interrupts and start processing hotplug events. At the same time, drivers should initialize all modeset objects such as CRTCs, encoders and connectors. To finish up the fbdev helper initialization, the drm_fb_helper_init() function is called. To probe for all attached displays and set up an initial configuration using the detected hardware, drivers should call drm_fb_helper_single_add_all_connectors() followed by drm_fb_helper_initial_config().

If drm_framebuffer_funcs ->dirty is set, the drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions will accumulate changes and schedule drm_fb_helper ->dirty_work to run right away. This worker then calls the dirty() function ensuring that it will always run in process context since the fb_*() function could be running in atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io callback it will also schedule dirty_work with the damage collected from the mmap page writes.

int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper * fb_helper)

add all connectors to fbdev emulation helper

Parameters

struct drm_fb_helper * fb_helper
fbdev initialized with drm_fb_helper_init

Description

This functions adds all the available connectors for use with the given fb_helper. This is a separate step to allow drivers to freely assign connectors to the fbdev, e.g. if some are reserved for special purposes or not adequate to be used for the fbcon.

This function is protected against concurrent connector hotadds/removals using drm_fb_helper_add_one_connector() and drm_fb_helper_remove_one_connector().

int drm_fb_helper_debug_enter(struct fb_info * info)

implementation for ->fb_debug_enter

Parameters

struct fb_info * info
fbdev registered by the helper
int drm_fb_helper_debug_leave(struct fb_info * info)

implementation for ->fb_debug_leave

Parameters

struct fb_info * info
fbdev registered by the helper
int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper * fb_helper)

restore fbdev configuration

Parameters

struct drm_fb_helper * fb_helper
fbcon to restore

Description

This should be called from driver’s drm ->lastclose callback when implementing an fbcon on top of kms using this helper. This ensures that the user isn’t greeted with a black screen when e.g. X dies.

Return

Zero if everything went ok, negative error code otherwise.

int drm_fb_helper_blank(int blank, struct fb_info * info)

implementation for ->fb_blank

Parameters

int blank
desired blanking state
struct fb_info * info
fbdev registered by the helper
void drm_fb_helper_prepare(struct drm_device * dev, struct drm_fb_helper * helper, const struct drm_fb_helper_funcs * funcs)

setup a drm_fb_helper structure

Parameters

struct drm_device * dev
DRM device
struct drm_fb_helper * helper
driver-allocated fbdev helper structure to set up
const struct drm_fb_helper_funcs * funcs
pointer to structure of functions associate with this helper

Description

Sets up the bare minimum to make the framebuffer helper usable. This is useful to implement race-free initialization of the polling helpers.

int drm_fb_helper_init(struct drm_device * dev, struct drm_fb_helper * fb_helper, int crtc_count, int max_conn_count)

initialize a drm_fb_helper structure

Parameters

struct drm_device * dev
drm device
struct drm_fb_helper * fb_helper
driver-allocated fbdev helper structure to initialize
int crtc_count
maximum number of crtcs to support in this fbdev emulation
int max_conn_count
max connector count

Description

This allocates the structures for the fbdev helper with the given limits. Note that this won’t yet touch the hardware (through the driver interfaces) nor register the fbdev. This is only done in drm_fb_helper_initial_config() to allow driver writes more control over the exact init sequence.

Drivers must call drm_fb_helper_prepare() before calling this function.

Return

Zero if everything went ok, nonzero otherwise.

struct fb_info * drm_fb_helper_alloc_fbi(struct drm_fb_helper * fb_helper)

allocate fb_info and some of its members

Parameters

struct drm_fb_helper * fb_helper
driver-allocated fbdev helper

Description

A helper to alloc fb_info and the members cmap and apertures. Called by the driver within the fb_probe fb_helper callback function.

Return

fb_info pointer if things went okay, pointer containing error code otherwise

void drm_fb_helper_unregister_fbi(struct drm_fb_helper * fb_helper)

unregister fb_info framebuffer device

Parameters

struct drm_fb_helper * fb_helper
driver-allocated fbdev helper

Description

A wrapper around unregister_framebuffer, to release the fb_info framebuffer device

void drm_fb_helper_release_fbi(struct drm_fb_helper * fb_helper)

dealloc fb_info and its members

Parameters

struct drm_fb_helper * fb_helper
driver-allocated fbdev helper

Description

A helper to free memory taken by fb_info and the members cmap and apertures

wrapper around unlink_framebuffer

Parameters

struct drm_fb_helper * fb_helper
driver-allocated fbdev helper

Description

A wrapper around unlink_framebuffer implemented by fbdev core

void drm_fb_helper_deferred_io(struct fb_info * info, struct list_head * pagelist)

fbdev deferred_io callback function

Parameters

struct fb_info * info
fb_info struct pointer
struct list_head * pagelist
list of dirty mmap framebuffer pages

Description

This function is used as the fb_deferred_io ->deferred_io callback function for flushing the fbdev mmap writes.

ssize_t drm_fb_helper_sys_read(struct fb_info * info, char __user * buf, size_t count, loff_t * ppos)

wrapper around fb_sys_read

Parameters

struct fb_info * info
fb_info struct pointer
char __user * buf
userspace buffer to read from framebuffer memory
size_t count
number of bytes to read from framebuffer memory
loff_t * ppos
read offset within framebuffer memory

Description

A wrapper around fb_sys_read implemented by fbdev core

ssize_t drm_fb_helper_sys_write(struct fb_info * info, const char __user * buf, size_t count, loff_t * ppos)

wrapper around fb_sys_write

Parameters

struct fb_info * info
fb_info struct pointer
const char __user * buf
userspace buffer to write to framebuffer memory
size_t count
number of bytes to write to framebuffer memory
loff_t * ppos
write offset within framebuffer memory

Description

A wrapper around fb_sys_write implemented by fbdev core

void drm_fb_helper_sys_fillrect(struct fb_info * info, const struct fb_fillrect * rect)

wrapper around sys_fillrect

Parameters

struct fb_info * info
fbdev registered by the helper
const struct fb_fillrect * rect
info about rectangle to fill

Description

A wrapper around sys_fillrect implemented by fbdev core

void drm_fb_helper_sys_copyarea(struct fb_info * info, const struct fb_copyarea * area)

wrapper around sys_copyarea

Parameters

struct fb_info * info
fbdev registered by the helper
const struct fb_copyarea * area
info about area to copy

Description

A wrapper around sys_copyarea implemented by fbdev core

void drm_fb_helper_sys_imageblit(struct fb_info * info, const struct fb_image * image)

wrapper around sys_imageblit

Parameters

struct fb_info * info
fbdev registered by the helper
const struct fb_image * image
info about image to blit

Description

A wrapper around sys_imageblit implemented by fbdev core

void drm_fb_helper_cfb_fillrect(struct fb_info * info, const struct fb_fillrect * rect)

wrapper around cfb_fillrect

Parameters

struct fb_info * info
fbdev registered by the helper
const struct fb_fillrect * rect
info about rectangle to fill

Description

A wrapper around cfb_imageblit implemented by fbdev core

void drm_fb_helper_cfb_copyarea(struct fb_info * info, const struct fb_copyarea * area)

wrapper around cfb_copyarea

Parameters

struct fb_info * info
fbdev registered by the helper
const struct fb_copyarea * area
info about area to copy

Description

A wrapper around cfb_copyarea implemented by fbdev core

void drm_fb_helper_cfb_imageblit(struct fb_info * info, const struct fb_image * image)

wrapper around cfb_imageblit

Parameters

struct fb_info * info
fbdev registered by the helper
const struct fb_image * image
info about image to blit

Description

A wrapper around cfb_imageblit implemented by fbdev core

void drm_fb_helper_set_suspend(struct drm_fb_helper * fb_helper, int state)

wrapper around fb_set_suspend

Parameters

struct drm_fb_helper * fb_helper
driver-allocated fbdev helper
int state
desired state, zero to resume, non-zero to suspend

Description

A wrapper around fb_set_suspend implemented by fbdev core

int drm_fb_helper_setcmap(struct fb_cmap * cmap, struct fb_info * info)

implementation for ->fb_setcmap

Parameters

struct fb_cmap * cmap
cmap to set
struct fb_info * info
fbdev registered by the helper
int drm_fb_helper_check_var(struct fb_var_screeninfo * var, struct fb_info * info)

implementation for ->fb_check_var

Parameters

struct fb_var_screeninfo * var
screeninfo to check
struct fb_info * info
fbdev registered by the helper
int drm_fb_helper_set_par(struct fb_info * info)

implementation for ->fb_set_par

Parameters

struct fb_info * info
fbdev registered by the helper

Description

This will let fbcon do the mode init and is called at initialization time by the fbdev core when registering the driver, and later on through the hotplug callback.

int drm_fb_helper_pan_display(struct fb_var_screeninfo * var, struct fb_info * info)

implementation for ->fb_pan_display

Parameters

struct fb_var_screeninfo * var
updated screen information
struct fb_info * info
fbdev registered by the helper
void drm_fb_helper_fill_fix(struct fb_info * info, uint32_t pitch, uint32_t depth)

initializes fixed fbdev information

Parameters

struct fb_info * info
fbdev registered by the helper
uint32_t pitch
desired pitch
uint32_t depth
desired depth

Description

Helper to fill in the fixed fbdev information useful for a non-accelerated fbdev emulations. Drivers which support acceleration methods which impose additional constraints need to set up their own limits.

Drivers should call this (or their equivalent setup code) from their ->fb_probe callback.

void drm_fb_helper_fill_var(struct fb_info * info, struct drm_fb_helper * fb_helper, uint32_t fb_width, uint32_t fb_height)

initalizes variable fbdev information

Parameters

struct fb_info * info
fbdev instance to set up
struct drm_fb_helper * fb_helper
fb helper instance to use as template
uint32_t fb_width
desired fb width
uint32_t fb_height
desired fb height

Description

Sets up the variable fbdev metainformation from the given fb helper instance and the drm framebuffer allocated in fb_helper->fb.

Drivers should call this (or their equivalent setup code) from their ->fb_probe callback after having allocated the fbdev backing storage framebuffer.

int drm_fb_helper_initial_config(struct drm_fb_helper * fb_helper, int bpp_sel)

setup a sane initial connector configuration

Parameters

struct drm_fb_helper * fb_helper
fb_helper device struct
int bpp_sel
bpp value to use for the framebuffer configuration

Description

Scans the CRTCs and connectors and tries to put together an initial setup. At the moment, this is a cloned configuration across all heads with a new framebuffer object as the backing store.

Note that this also registers the fbdev and so allows userspace to call into the driver through the fbdev interfaces.

This function will call down into the ->fb_probe callback to let the driver allocate and initialize the fbdev info structure and the drm framebuffer used to back the fbdev. drm_fb_helper_fill_var() and drm_fb_helper_fill_fix() are provided as helpers to setup simple default values for the fbdev info structure.

HANG DEBUGGING:

When you have fbcon support built-in or already loaded, this function will do a full modeset to setup the fbdev console. Due to locking misdesign in the VT/fbdev subsystem that entire modeset sequence has to be done while holding console_lock. Until console_unlock is called no dmesg lines will be sent out to consoles, not even serial console. This means when your driver crashes, you will see absolutely nothing else but a system stuck in this function, with no further output. Any kind of printk() you place within your own driver or in the drm core modeset code will also never show up.

Standard debug practice is to run the fbcon setup without taking the console_lock as a hack, to be able to see backtraces and crashes on the serial line. This can be done by setting the fb.lockless_register_fb=1 kernel cmdline option.

The other option is to just disable fbdev emulation since very likely the first modeset from userspace will crash in the same way, and is even easier to debug. This can be done by setting the drm_kms_helper.fbdev_emulation=0 kernel cmdline option.

Return

Zero if everything went ok, nonzero otherwise.

int drm_fb_helper_hotplug_event(struct drm_fb_helper * fb_helper)

respond to a hotplug notification by probing all the outputs attached to the fb

Parameters

struct drm_fb_helper * fb_helper
the drm_fb_helper

Description

Scan the connectors attached to the fb_helper and try to put together a setup after *notification of a change in output configuration.

Called at runtime, takes the mode config locks to be able to check/change the modeset configuration. Must be run from process context (which usually means either the output polling work or a work item launched from the driver’s hotplug interrupt).

Note that drivers may call this even before calling drm_fb_helper_initial_config but only after drm_fb_helper_init. This allows for a race-free fbcon setup and will make sure that the fbdev emulation will not miss any hotplug events.

Return

0 on success and a non-zero error code otherwise.

struct drm_fb_helper_surface_size

describes fbdev size and scanout surface size

Definition

struct drm_fb_helper_surface_size {
  u32 fb_width;
  u32 fb_height;
  u32 surface_width;
  u32 surface_height;
  u32 surface_bpp;
  u32 surface_depth;
};

Members

u32 fb_width
fbdev width
u32 fb_height
fbdev height
u32 surface_width
scanout buffer width
u32 surface_height
scanout buffer height
u32 surface_bpp
scanout buffer bpp
u32 surface_depth
scanout buffer depth

Description

Note that the scanout surface width/height may be larger than the fbdev width/height. In case of multiple displays, the scanout surface is sized according to the largest width/height (so it is large enough for all CRTCs to scanout). But the fbdev width/height is sized to the minimum width/ height of all the displays. This ensures that fbcon fits on the smallest of the attached displays.

So what is passed to drm_fb_helper_fill_var() should be fb_width/fb_height, rather than the surface size.

struct drm_fb_helper_funcs

driver callbacks for the fbdev emulation library

Definition

struct drm_fb_helper_funcs {
  void (* gamma_set) (struct drm_crtc *crtc, u16 red, u16 green,u16 blue, int regno);
  void (* gamma_get) (struct drm_crtc *crtc, u16 *red, u16 *green,u16 *blue, int regno);
  int (* fb_probe) (struct drm_fb_helper *helper,struct drm_fb_helper_surface_size *sizes);
  bool (* initial_config) (struct drm_fb_helper *fb_helper,struct drm_fb_helper_crtc **crtcs,struct drm_display_mode **modes,struct drm_fb_offset *offsets,bool *enabled, int width, int height);
};

Members

void (*)(struct drm_crtc *crtc, u16 red, u16 green,u16 blue, int regno) gamma_set

Set the given gamma LUT register on the given CRTC.

This callback is optional.

FIXME:

This callback is functionally redundant with the core gamma table support and simply exists because the fbdev hasn’t yet been refactored to use the core gamma table interfaces.

void (*)(struct drm_crtc *crtc, u16 *red, u16 *green,u16 *blue, int regno) gamma_get

Read the given gamma LUT register on the given CRTC, used to save the current LUT when force-restoring the fbdev for e.g. kdbg.

This callback is optional.

FIXME:

This callback is functionally redundant with the core gamma table support and simply exists because the fbdev hasn’t yet been refactored to use the core gamma table interfaces.

int (*)(struct drm_fb_helper *helper,struct drm_fb_helper_surface_size *sizes) fb_probe

Driver callback to allocate and initialize the fbdev info structure. Furthermore it also needs to allocate the DRM framebuffer used to back the fbdev.

This callback is mandatory.

RETURNS:

The driver should return 0 on success and a negative error code on failure.

bool (*)(struct drm_fb_helper *fb_helper,struct drm_fb_helper_crtc **crtcs,struct drm_display_mode **modes,struct drm_fb_offset *offsets,bool *enabled, int width, int height) initial_config

Driver callback to setup an initial fbdev display configuration. Drivers can use this callback to tell the fbdev emulation what the preferred initial configuration is. This is useful to implement smooth booting where the fbdev (and subsequently all userspace) never changes the mode, but always inherits the existing configuration.

This callback is optional.

RETURNS:

The driver should return true if a suitable initial configuration has been filled out and false when the fbdev helper should fall back to the default probing logic.

Description

Driver callbacks used by the fbdev emulation helper library.

struct drm_fb_helper

main structure to emulate fbdev on top of KMS

Definition

struct drm_fb_helper {
  struct drm_framebuffer * fb;
  struct drm_device * dev;
  int crtc_count;
  struct drm_fb_helper_crtc * crtc_info;
  int connector_count;
  int connector_info_alloc_count;
  struct drm_fb_helper_connector ** connector_info;
  const struct drm_fb_helper_funcs * funcs;
  struct fb_info * fbdev;
  u32 pseudo_palette[17];
  struct drm_clip_rect dirty_clip;
  spinlock_t dirty_lock;
  struct work_struct dirty_work;
  struct list_head kernel_fb_list;
  bool delayed_hotplug;
  bool atomic;
};

Members

struct drm_framebuffer * fb
Scanout framebuffer object
struct drm_device * dev
DRM device
int crtc_count
number of possible CRTCs
struct drm_fb_helper_crtc * crtc_info
per-CRTC helper state (mode, x/y offset, etc)
int connector_count
number of connected connectors
int connector_info_alloc_count
size of connector_info
struct drm_fb_helper_connector ** connector_info
array of per-connector information
const struct drm_fb_helper_funcs * funcs
driver callbacks for fb helper
struct fb_info * fbdev
emulated fbdev device info struct
u32 pseudo_palette[17]
fake palette of 16 colors
struct drm_clip_rect dirty_clip
clip rectangle used with deferred_io to accumulate damage to the screen buffer
spinlock_t dirty_lock
spinlock protecting dirty_clip
struct work_struct dirty_work
worker used to flush the framebuffer
struct list_head kernel_fb_list
Entry on the global kernel_fb_helper_list, used for kgdb entry/exit.
bool delayed_hotplug
A hotplug was received while fbdev wasn’t in control of the DRM device, i.e. another KMS master was active. The output configuration needs to be reprobe when fbdev is in control again.
bool atomic
Use atomic updates for restore_fbdev_mode(), etc. This defaults to true if driver has DRIVER_ATOMIC feature flag, but drivers can override it to true after drm_fb_helper_init() if they support atomic modeset but do not yet advertise DRIVER_ATOMIC (note that fb-helper does not require ASYNC commits).

Description

This is the main structure used by the fbdev helpers. Drivers supporting fbdev emulation should embedded this into their overall driver structure. Drivers must also fill out a struct drm_fb_helper_funcs with a few operations.

Framebuffer CMA Helper Functions Reference

Provides helper functions for creating a cma (contiguous memory allocator) backed framebuffer.

drm_fb_cma_create() is used in the drm_mode_config_funcs ->fb_create callback function to create a cma backed framebuffer.

An fbdev framebuffer backed by cma is also available by calling drm_fbdev_cma_init(). drm_fbdev_cma_fini() tears it down. If the drm_framebuffer_funcs ->dirty callback is set, fb_deferred_io will be set up automatically. dirty() is called by drm_fb_helper_deferred_io() in process context (struct delayed_work).

Example fbdev deferred io code:

static int driver_fbdev_fb_dirty(struct drm_framebuffer *fb,
struct drm_file *file_priv, unsigned flags, unsigned color, struct drm_clip_rect *clips, unsigned num_clips)
{
struct drm_gem_cma_object *cma = drm_fb_cma_get_gem_obj(fb, 0); ... push changes ... return 0;

}

static struct drm_framebuffer_funcs driver_fbdev_fb_funcs = {
.destroy = drm_fb_cma_destroy, .create_handle = drm_fb_cma_create_handle, .dirty = driver_fbdev_fb_dirty,

};

static int driver_fbdev_create(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
return drm_fbdev_cma_create_with_funcs(helper, sizes,
driver_fbdev_fb_funcs);

}

static const struct drm_fb_helper_funcs driver_fb_helper_funcs = {
.fb_probe = driver_fbdev_create,

};

Initialize: fbdev = drm_fbdev_cma_init_with_funcs(dev, 16,

dev->mode_config.num_crtc, dev->mode_config.num_connector, driver_fb_helper_funcs);
struct drm_framebuffer * drm_fb_cma_create_with_funcs(struct drm_device * dev, struct drm_file * file_priv, const struct drm_mode_fb_cmd2 * mode_cmd, const struct drm_framebuffer_funcs * funcs)

helper function for the drm_mode_config_funcs ->fb_create callback function

Parameters

struct drm_device * dev
undescribed
struct drm_file * file_priv
undescribed
const struct drm_mode_fb_cmd2 * mode_cmd
undescribed
const struct drm_framebuffer_funcs * funcs
undescribed

Description

This can be used to set drm_framebuffer_funcs for drivers that need the dirty() callback. Use drm_fb_cma_create() if you don’t need to change drm_framebuffer_funcs.

struct drm_framebuffer * drm_fb_cma_create(struct drm_device * dev, struct drm_file * file_priv, const struct drm_mode_fb_cmd2 * mode_cmd)

drm_mode_config_funcs ->fb_create callback function

Parameters

struct drm_device * dev
undescribed
struct drm_file * file_priv
undescribed
const struct drm_mode_fb_cmd2 * mode_cmd
undescribed

Description

If your hardware has special alignment or pitch requirements these should be checked before calling this function. Use drm_fb_cma_create_with_funcs() if you need to set drm_framebuffer_funcs ->dirty.

struct drm_gem_cma_object * drm_fb_cma_get_gem_obj(struct drm_framebuffer * fb, unsigned int plane)

Get CMA GEM object for framebuffer

Parameters

struct drm_framebuffer * fb
The framebuffer
unsigned int plane
Which plane

Description

Return the CMA GEM object for given framebuffer.

This function will usually be called from the CRTC callback functions.

int drm_fb_cma_debugfs_show(struct seq_file * m, void * arg)

Helper to list CMA framebuffer objects in debugfs.

Parameters

struct seq_file * m
undescribed
void * arg
undescribed
struct drm_fbdev_cma * drm_fbdev_cma_init_with_funcs(struct drm_device * dev, unsigned int preferred_bpp, unsigned int num_crtc, unsigned int max_conn_count, const struct drm_fb_helper_funcs * funcs)

Allocate and initializes a drm_fbdev_cma struct

Parameters

struct drm_device * dev
DRM device
unsigned int preferred_bpp
Preferred bits per pixel for the device
unsigned int num_crtc
Number of CRTCs
unsigned int max_conn_count
Maximum number of connectors
const struct drm_fb_helper_funcs * funcs
fb helper functions, in particular fb_probe()

Description

Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR.

struct drm_fbdev_cma * drm_fbdev_cma_init(struct drm_device * dev, unsigned int preferred_bpp, unsigned int num_crtc, unsigned int max_conn_count)

Allocate and initializes a drm_fbdev_cma struct

Parameters

struct drm_device * dev
DRM device
unsigned int preferred_bpp
Preferred bits per pixel for the device
unsigned int num_crtc
Number of CRTCs
unsigned int max_conn_count
Maximum number of connectors

Description

Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR.

void drm_fbdev_cma_fini(struct drm_fbdev_cma * fbdev_cma)

Free drm_fbdev_cma struct

Parameters

struct drm_fbdev_cma * fbdev_cma
The drm_fbdev_cma struct
void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma * fbdev_cma)

Restores initial framebuffer mode

Parameters

struct drm_fbdev_cma * fbdev_cma
The drm_fbdev_cma struct, may be NULL

Description

This function is usually called from the DRM drivers lastclose callback.

void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma * fbdev_cma)

Poll for hotpulug events

Parameters

struct drm_fbdev_cma * fbdev_cma
The drm_fbdev_cma struct, may be NULL

Description

This function is usually called from the DRM drivers output_poll_changed callback.

Display Port Helper Functions Reference

These functions contain some common logic and helpers at various abstraction levels to deal with Display Port sink devices and related things like DP aux channel transfers, EDID reading over DP aux channels, decoding certain DPCD blocks, ...

The DisplayPort AUX channel is an abstraction to allow generic, driver- independent access to AUX functionality. Drivers can take advantage of this by filling in the fields of the drm_dp_aux structure.

Transactions are described using a hardware-independent drm_dp_aux_msg structure, which is passed into a driver’s .:c:func:transfer() implementation. Both native and I2C-over-AUX transactions are supported.

struct drm_dp_aux_msg

DisplayPort AUX channel transaction

Definition

struct drm_dp_aux_msg {
  unsigned int address;
  u8 request;
  u8 reply;
  void * buffer;
  size_t size;
};

Members

unsigned int address
address of the (first) register to access
u8 request
contains the type of transaction (see DP_AUX_* macros)
u8 reply
upon completion, contains the reply type of the transaction
void * buffer
pointer to a transmission or reception buffer
size_t size
size of buffer
struct drm_dp_aux

DisplayPort AUX channel

Definition

struct drm_dp_aux {
  const char * name;
  struct i2c_adapter ddc;
  struct device * dev;
  struct mutex hw_mutex;
  ssize_t (* transfer) (struct drm_dp_aux *aux,struct drm_dp_aux_msg *msg);
};

Members

const char * name
user-visible name of this AUX channel and the I2C-over-AUX adapter
struct i2c_adapter ddc
I2C adapter that can be used for I2C-over-AUX communication
struct device * dev
pointer to struct device that is the parent for this AUX channel
struct mutex hw_mutex
internal mutex used for locking transfers
ssize_t (*)(struct drm_dp_aux *aux,struct drm_dp_aux_msg *msg) transfer
transfers a message representing a single AUX transaction

Description

The .dev field should be set to a pointer to the device that implements the AUX channel.

The .name field may be used to specify the name of the I2C adapter. If set to NULL, dev_name() of .dev will be used.

Drivers provide a hardware-specific implementation of how transactions are executed via the .:c:func:transfer() function. A pointer to a drm_dp_aux_msg structure describing the transaction is passed into this function. Upon success, the implementation should return the number of payload bytes that were transferred, or a negative error-code on failure. Helpers propagate errors from the .:c:func:transfer() function, with the exception of the -EBUSY error, which causes a transaction to be retried. On a short, helpers will return -EPROTO to make it simpler to check for failure.

An AUX channel can also be used to transport I2C messages to a sink. A typical application of that is to access an EDID that’s present in the sink device. The .:c:func:transfer() function can also be used to execute such transactions. The drm_dp_aux_register() function registers an I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers should call drm_dp_aux_unregister() to remove the I2C adapter. The I2C adapter uses long transfers by default; if a partial response is received, the adapter will drop down to the size given by the partial response for this transaction only.

Note that the aux helper code assumes that the .:c:func:transfer() function only modifies the reply field of the drm_dp_aux_msg structure. The retry logic and i2c helpers assume this is the case.

ssize_t drm_dp_dpcd_readb(struct drm_dp_aux * aux, unsigned int offset, u8 * valuep)

read a single byte from the DPCD

Parameters

struct drm_dp_aux * aux
DisplayPort AUX channel
unsigned int offset
address of the register to read
u8 * valuep
location where the value of the register will be stored

Description

Returns the number of bytes transferred (1) on success, or a negative error code on failure.

ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux * aux, unsigned int offset, u8 value)

write a single byte to the DPCD

Parameters

struct drm_dp_aux * aux
DisplayPort AUX channel
unsigned int offset
address of the register to write
u8 value
value to write to the register

Description

Returns the number of bytes transferred (1) on success, or a negative error code on failure.

ssize_t drm_dp_dpcd_read(struct drm_dp_aux * aux, unsigned int offset, void * buffer, size_t size)

read a series of bytes from the DPCD

Parameters

struct drm_dp_aux * aux
DisplayPort AUX channel
unsigned int offset
address of the (first) register to read
void * buffer
buffer to store the register values
size_t size
number of bytes in buffer

Description

Returns the number of bytes transferred on success, or a negative error code on failure. -EIO is returned if the request was NAKed by the sink or if the retry count was exceeded. If not all bytes were transferred, this function returns -EPROTO. Errors from the underlying AUX channel transfer function, with the exception of -EBUSY (which causes the transaction to be retried), are propagated to the caller.

ssize_t drm_dp_dpcd_write(struct drm_dp_aux * aux, unsigned int offset, void * buffer, size_t size)

write a series of bytes to the DPCD

Parameters

struct drm_dp_aux * aux
DisplayPort AUX channel
unsigned int offset
address of the (first) register to write
void * buffer
buffer containing the values to write
size_t size
number of bytes in buffer

Description

Returns the number of bytes transferred on success, or a negative error code on failure. -EIO is returned if the request was NAKed by the sink or if the retry count was exceeded. If not all bytes were transferred, this function returns -EPROTO. Errors from the underlying AUX channel transfer function, with the exception of -EBUSY (which causes the transaction to be retried), are propagated to the caller.

read DPCD link status (bytes 0x202-0x207)

Parameters

struct drm_dp_aux * aux
DisplayPort AUX channel
u8 status[DP_LINK_STATUS_SIZE]
undescribed

Description

Returns the number of bytes transferred on success or a negative error code on failure.

probe a DisplayPort link for capabilities

Parameters

struct drm_dp_aux * aux
DisplayPort AUX channel
struct drm_dp_link * link
pointer to structure in which to return link capabilities

Description

The structure filled in by this function can usually be passed directly into drm_dp_link_power_up() and drm_dp_link_configure() to power up and configure the link based on the link’s capabilities.

Returns 0 on success or a negative error code on failure.

power up a DisplayPort link

Parameters

struct drm_dp_aux * aux
DisplayPort AUX channel
struct drm_dp_link * link
pointer to a structure containing the link configuration

Description

Returns 0 on success or a negative error code on failure.

power down a DisplayPort link

Parameters

struct drm_dp_aux * aux
DisplayPort AUX channel
struct drm_dp_link * link
pointer to a structure containing the link configuration

Description

Returns 0 on success or a negative error code on failure.

configure a DisplayPort link

Parameters

struct drm_dp_aux * aux
DisplayPort AUX channel
struct drm_dp_link * link
pointer to a structure containing the link configuration

Description

Returns 0 on success or a negative error code on failure.

int drm_dp_aux_register(struct drm_dp_aux * aux)

initialise and register aux channel

Parameters

struct drm_dp_aux * aux
DisplayPort AUX channel

Description

Returns 0 on success or a negative error code on failure.

void drm_dp_aux_unregister(struct drm_dp_aux * aux)

unregister an AUX adapter

Parameters

struct drm_dp_aux * aux
DisplayPort AUX channel

Display Port Dual Mode Adaptor Helper Functions Reference

Helper functions to deal with DP dual mode (aka. DP++) adaptors.

Type 1: Adaptor registers (if any) and the sink DDC bus may be accessed via I2C.

Type 2: Adaptor registers and sink DDC bus can be accessed either via I2C or I2C-over-AUX. Source devices may choose to implement either of these access methods.

enum drm_dp_dual_mode_type

Type of the DP dual mode adaptor

Constants

DRM_DP_DUAL_MODE_NONE
No DP dual mode adaptor
DRM_DP_DUAL_MODE_UNKNOWN
Could be either none or type 1 DVI adaptor
DRM_DP_DUAL_MODE_TYPE1_DVI
Type 1 DVI adaptor
DRM_DP_DUAL_MODE_TYPE1_HDMI
Type 1 HDMI adaptor
DRM_DP_DUAL_MODE_TYPE2_DVI
Type 2 DVI adaptor
DRM_DP_DUAL_MODE_TYPE2_HDMI
Type 2 HDMI adaptor
ssize_t drm_dp_dual_mode_read(struct i2c_adapter * adapter, u8 offset, void * buffer, size_t size)

Read from the DP dual mode adaptor register(s)

Parameters

struct i2c_adapter * adapter
I2C adapter for the DDC bus
u8 offset
register offset
void * buffer
buffer for return data
size_t size
sizo of the buffer

Description

Reads size bytes from the DP dual mode adaptor registers starting at offset.

Return

0 on success, negative error code on failure

ssize_t drm_dp_dual_mode_write(struct i2c_adapter * adapter, u8 offset, const void * buffer, size_t size)

Write to the DP dual mode adaptor register(s)

Parameters

struct i2c_adapter * adapter
I2C adapter for the DDC bus
u8 offset
register offset
const void * buffer
buffer for write data
size_t size
sizo of the buffer

Description

Writes size bytes to the DP dual mode adaptor registers starting at offset.

Return

0 on success, negative error code on failure

enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter * adapter)

Identify the DP dual mode adaptor

Parameters

struct i2c_adapter * adapter
I2C adapter for the DDC bus

Description

Attempt to identify the type of the DP dual mode adaptor used.

Note that when the answer is DRM_DP_DUAL_MODE_UNKNOWN it’s not certain whether we’re dealing with a native HDMI port or a type 1 DVI dual mode adaptor. The driver will have to use some other hardware/driver specific mechanism to make that distinction.

Return

The type of the DP dual mode adaptor used

int drm_dp_dual_mode_max_tmds_clock(enum drm_dp_dual_mode_type type, struct i2c_adapter * adapter)

Max TMDS clock for DP dual mode adaptor

Parameters

enum drm_dp_dual_mode_type type
DP dual mode adaptor type
struct i2c_adapter * adapter
I2C adapter for the DDC bus

Description

Determine the max TMDS clock the adaptor supports based on the type of the dual mode adaptor and the DP_DUAL_MODE_MAX_TMDS_CLOCK register (on type2 adaptors). As some type 1 adaptors have problems with registers (see comments in drm_dp_dual_mode_detect()) we don’t read the register on those, instead we simply assume a 165 MHz limit based on the specification.

Return

Maximum supported TMDS clock rate for the DP dual mode adaptor in kHz.

int drm_dp_dual_mode_get_tmds_output(enum drm_dp_dual_mode_type type, struct i2c_adapter * adapter, bool * enabled)

Get the state of the TMDS output buffers in the DP dual mode adaptor

Parameters

enum drm_dp_dual_mode_type type
DP dual mode adaptor type
struct i2c_adapter * adapter
I2C adapter for the DDC bus
bool * enabled
current state of the TMDS output buffers

Description

Get the state of the TMDS output buffers in the adaptor. For type2 adaptors this is queried from the DP_DUAL_MODE_TMDS_OEN register. As some type 1 adaptors have problems with registers (see comments in drm_dp_dual_mode_detect()) we don’t read the register on those, instead we simply assume that the buffers are always enabled.

Return

0 on success, negative error code on failure

int drm_dp_dual_mode_set_tmds_output(enum drm_dp_dual_mode_type type, struct i2c_adapter * adapter, bool enable)

Enable/disable TMDS output buffers in the DP dual mode adaptor

Parameters

enum drm_dp_dual_mode_type type
DP dual mode adaptor type
struct i2c_adapter * adapter
I2C adapter for the DDC bus
bool enable
enable (as opposed to disable) the TMDS output buffers

Description

Set the state of the TMDS output buffers in the adaptor. For type2 this is set via the DP_DUAL_MODE_TMDS_OEN register. As some type 1 adaptors have problems with registers (see comments in drm_dp_dual_mode_detect()) we avoid touching the register, making this function a no-op on type 1 adaptors.

Return

0 on success, negative error code on failure

const char * drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type)

Get the name of the DP dual mode adaptor type as a string

Parameters

enum drm_dp_dual_mode_type type
DP dual mode adaptor type

Return

String representation of the DP dual mode adaptor type

Display Port MST Helper Functions Reference

These functions contain parts of the DisplayPort 1.2a MultiStream Transport protocol. The helpers contain a topology manager and bandwidth manager. The helpers encapsulate the sending and received of sideband msgs.

struct drm_dp_vcpi

Virtual Channel Payload Identifier

Definition

struct drm_dp_vcpi {
  int vcpi;
  int pbn;
  int aligned_pbn;
  int num_slots;
};

Members

int vcpi
Virtual channel ID.
int pbn
Payload Bandwidth Number for this channel
int aligned_pbn
PBN aligned with slot size
int num_slots
number of slots for this PBN
struct drm_dp_mst_port

MST port

Definition

struct drm_dp_mst_port {
  struct kref kref;
  u8 port_num;
  bool input;
  bool mcs;
  bool ddps;
  u8 pdt;
  bool ldps;
  u8 dpcd_rev;
  u8 num_sdp_streams;
  u8 num_sdp_stream_sinks;
  uint16_t available_pbn;
  struct list_head next;
  struct drm_dp_mst_branch * mstb;
  struct drm_dp_aux aux;
  struct drm_dp_mst_branch * parent;
  struct drm_dp_vcpi vcpi;
  struct drm_connector * connector;
  struct drm_dp_mst_topology_mgr * mgr;
};

Members

struct kref kref
reference count for this port.
u8 port_num
port number
bool input
if this port is an input port.
bool mcs
message capability status - DP 1.2 spec.
bool ddps
DisplayPort Device Plug Status - DP 1.2
u8 pdt
Peer Device Type
bool ldps
Legacy Device Plug Status
u8 dpcd_rev
DPCD revision of device on this port
u8 num_sdp_streams
Number of simultaneous streams
u8 num_sdp_stream_sinks
Number of stream sinks
uint16_t available_pbn
Available bandwidth for this port.
struct list_head next
link to next port on this branch device
struct drm_dp_mst_branch * mstb
branch device attach below this port
struct drm_dp_aux aux
i2c aux transport to talk to device connected to this port.
struct drm_dp_mst_branch * parent
branch device parent of this port
struct drm_dp_vcpi vcpi
Virtual Channel Payload info for this port.
struct drm_connector * connector
DRM connector this port is connected to.
struct drm_dp_mst_topology_mgr * mgr
topology manager this port lives under.

Description

This structure represents an MST port endpoint on a device somewhere in the MST topology.

struct drm_dp_mst_branch

MST branch device.

Definition

struct drm_dp_mst_branch {
  struct kref kref;
  u8 rad[8];
  u8 lct;
  int num_ports;
  int msg_slots;
  struct list_head ports;
  struct drm_dp_mst_port * port_parent;
  struct drm_dp_mst_topology_mgr * mgr;
  struct drm_dp_sideband_msg_tx * tx_slots[2];
  int last_seqno;
  bool link_address_sent;
  u8 guid[16];
};

Members

struct kref kref
reference count for this port.
u8 rad[8]
Relative Address to talk to this branch device.
u8 lct
Link count total to talk to this branch device.
int num_ports
number of ports on the branch.
int msg_slots
one bit per transmitted msg slot.
struct list_head ports
linked list of ports on this branch.
struct drm_dp_mst_port * port_parent
pointer to the port parent, NULL if toplevel.
struct drm_dp_mst_topology_mgr * mgr
topology manager for this branch device.
struct drm_dp_sideband_msg_tx * tx_slots[2]
transmission slots for this device.
int last_seqno
last sequence number used to talk to this.
bool link_address_sent
if a link address message has been sent to this device yet.
u8 guid[16]
guid for DP 1.2 branch device. port under this branch can be identified by port #.

Description

This structure represents an MST branch device, there is one primary branch device at the root, along with any other branches connected to downstream port of parent branches.

struct drm_dp_mst_topology_mgr

DisplayPort MST manager

Definition

struct drm_dp_mst_topology_mgr {
  struct device * dev;
  const struct drm_dp_mst_topology_cbs * cbs;
  struct drm_dp_aux * aux;
  int max_payloads;
  int conn_base_id;
  struct drm_dp_sideband_msg_rx down_rep_recv;
  struct drm_dp_sideband_msg_rx up_req_recv;
  struct mutex lock;
  bool mst_state;
  struct drm_dp_mst_branch * mst_primary;
  u8 dpcd[DP_RECEIVER_CAP_SIZE];
  int pbn_div;
};

Members

struct device * dev
device pointer for adding i2c devices etc.
const struct drm_dp_mst_topology_cbs * cbs
callbacks for connector addition and destruction. max_dpcd_transaction_bytes - maximum number of bytes to read/write in one go.
struct drm_dp_aux * aux
aux channel for the DP connector.
int max_payloads
maximum number of payloads the GPU can generate.
int conn_base_id
DRM connector ID this mgr is connected to.
struct drm_dp_sideband_msg_rx down_rep_recv
msg receiver state for down replies.
struct drm_dp_sideband_msg_rx up_req_recv
msg receiver state for up requests.
struct mutex lock
protects mst state, primary, dpcd.
bool mst_state
if this manager is enabled for an MST capable port.
struct drm_dp_mst_branch * mst_primary
pointer to the primary branch device.
u8 dpcd[DP_RECEIVER_CAP_SIZE]
cache of DPCD for primary port.
int pbn_div
PBN to slots divisor.

Description

This struct represents the toplevel displayport MST topology manager. There should be one instance of this for every MST capable DP connector on the GPU.

int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr * mgr)

Execute payload update part 1

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager to use.

Description

This iterates over all proposed virtual channels, and tries to allocate space in the link for them. For 0->slots transitions, this step just writes the VCPI to the MST device. For slots->0 transitions, this writes the updated VCPIs and removes the remote VC payloads.

after calling this the driver should generate ACT and payload packets.

int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr * mgr)

Execute payload update part 2

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager to use.

Description

This iterates over all proposed virtual channels, and tries to allocate space in the link for them. For 0->slots transitions, this step writes the remote VC payload commands. For slots->0 this just resets some internal state.

int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr * mgr, bool mst_state)

Set the MST state for a topology manager

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager to set state for
bool mst_state
true to enable MST on this connector - false to disable.

Description

This is called by the driver when it detects an MST capable device plugged into a DP MST capable port, or when a DP MST capable device is unplugged.

void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr * mgr)

suspend the MST manager

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager to suspend

Description

This function tells the MST device that we can’t handle UP messages anymore. This should stop it from sending any since we are suspended.

int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr * mgr)

resume the MST manager

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager to resume

Description

This will fetch DPCD and see if the device is still there, if it is, it will rewrite the MSTM control bits, and return.

if the device fails this returns -1, and the driver should do a full MST reprobe, in case we were undocked.

int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr * mgr, u8 * esi, bool * handled)

MST hotplug IRQ notify

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager to notify irq for.
u8 * esi
4 bytes from SINK_COUNT_ESI
bool * handled
whether the hpd interrupt was consumed or not

Description

This should be called from the driver when it detects a short IRQ, along with the value of the DEVICE_SERVICE_IRQ_VECTOR_ESI0. The topology manager will process the sideband messages received as a result of this.

enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector * connector, struct drm_dp_mst_topology_mgr * mgr, struct drm_dp_mst_port * port)

get connection status for an MST port

Parameters

struct drm_connector * connector
undescribed
struct drm_dp_mst_topology_mgr * mgr
manager for this port
struct drm_dp_mst_port * port
unverified pointer to a port

Description

This returns the current connection state for a port. It validates the port pointer still exists so the caller doesn’t require a reference

bool drm_dp_mst_port_has_audio(struct drm_dp_mst_topology_mgr * mgr, struct drm_dp_mst_port * port)

Check whether port has audio capability or not

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager for this port
struct drm_dp_mst_port * port
unverified pointer to a port.

Description

This returns whether the port supports audio or not.

struct edid * drm_dp_mst_get_edid(struct drm_connector * connector, struct drm_dp_mst_topology_mgr * mgr, struct drm_dp_mst_port * port)

get EDID for an MST port

Parameters

struct drm_connector * connector
toplevel connector to get EDID for
struct drm_dp_mst_topology_mgr * mgr
manager for this port
struct drm_dp_mst_port * port
unverified pointer to a port.

Description

This returns an EDID for the port connected to a connector, It validates the pointer still exists so the caller doesn’t require a reference.

int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr * mgr, int pbn)

find slots for this PBN value

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager to use
int pbn
payload bandwidth to convert into slots.
bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr * mgr, struct drm_dp_mst_port * port, int pbn, int * slots)

Allocate a virtual channel

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager for this port
struct drm_dp_mst_port * port
port to allocate a virtual channel for.
int pbn
payload bandwidth number to request
int * slots
returned number of slots for this PBN.
void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr * mgr, struct drm_dp_mst_port * port)

Reset number of slots to 0 for VCPI

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager for this port
struct drm_dp_mst_port * port
unverified pointer to a port.

Description

This just resets the number of slots for the ports VCPI for later programming.

void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr * mgr, struct drm_dp_mst_port * port)

deallocate a VCPI

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager for this port
struct drm_dp_mst_port * port
unverified port to deallocate vcpi for
int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr * mgr)

Check ACT handled status.

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager to use

Description

Check the payload status bits in the DPCD for ACT handled completion.

int drm_dp_calc_pbn_mode(int clock, int bpp)

Calculate the PBN for a mode.

Parameters

int clock
dot clock for the mode
int bpp
bpp for the mode.

Description

This uses the formula in the spec to calculate the PBN value for a mode.

void drm_dp_mst_dump_topology(struct seq_file * m, struct drm_dp_mst_topology_mgr * mgr)

Parameters

struct seq_file * m
seq_file to dump output to
struct drm_dp_mst_topology_mgr * mgr
manager to dump current topology for.

Description

helper to dump MST topology to a seq file for debugfs.

int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr * mgr, struct device * dev, struct drm_dp_aux * aux, int max_dpcd_transaction_bytes, int max_payloads, int conn_base_id)

initialise a topology manager

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager struct to initialise
struct device * dev
device providing this structure - for i2c addition.
struct drm_dp_aux * aux
DP helper aux channel to talk to this device
int max_dpcd_transaction_bytes
hw specific DPCD transaction limit
int max_payloads
maximum number of payloads this GPU can source
int conn_base_id
the connector object ID the MST device is connected to.

Description

Return 0 for success, or negative error code on failure

void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr * mgr)

destroy topology manager.

Parameters

struct drm_dp_mst_topology_mgr * mgr
manager to destroy

MIPI DSI Helper Functions Reference

These functions contain some common logic and helpers to deal with MIPI DSI peripherals.

Helpers are provided for a number of standard MIPI DSI command as well as a subset of the MIPI DCS command set.

struct mipi_dsi_msg

read/write DSI buffer

Definition

struct mipi_dsi_msg {
  u8 channel;
  u8 type;
  u16 flags;
  size_t tx_len;
  const void * tx_buf;
  size_t rx_len;
  void * rx_buf;
};

Members

u8 channel
virtual channel id
u8 type
payload data type
u16 flags
flags controlling this message transmission
size_t tx_len
length of tx_buf
const void * tx_buf
data to be written
size_t rx_len
length of rx_buf
void * rx_buf
data to be read, or NULL
struct mipi_dsi_packet

represents a MIPI DSI packet in protocol format

Definition

struct mipi_dsi_packet {
  size_t size;
  u8 header[4];
  size_t payload_length;
  const u8 * payload;
};

Members

size_t size
size (in bytes) of the packet
u8 header[4]
the four bytes that make up the header (Data ID, Word Count or Packet Data, and ECC)
size_t payload_length
number of bytes in the payload
const u8 * payload
a pointer to a buffer containing the payload, if any
struct mipi_dsi_host_ops

DSI bus operations

Definition

struct mipi_dsi_host_ops {
  int (* attach) (struct mipi_dsi_host *host,struct mipi_dsi_device *dsi);
  int (* detach) (struct mipi_dsi_host *host,struct mipi_dsi_device *dsi);
  ssize_t (* transfer) (struct mipi_dsi_host *host,const struct mipi_dsi_msg *msg);
};

Members

int (*)(struct mipi_dsi_host *host,struct mipi_dsi_device *dsi) attach
attach DSI device to DSI host
int (*)(struct mipi_dsi_host *host,struct mipi_dsi_device *dsi) detach
detach DSI device from DSI host
ssize_t (*)(struct mipi_dsi_host *host,const struct mipi_dsi_msg *msg) transfer
transmit a DSI packet

Description

DSI packets transmitted by .:c:func:transfer() are passed in as mipi_dsi_msg structures. This structure contains information about the type of packet being transmitted as well as the transmit and receive buffers. When an error is encountered during transmission, this function will return a negative error code. On success it shall return the number of bytes transmitted for write packets or the number of bytes received for read packets.

Note that typically DSI packet transmission is atomic, so the .:c:func:transfer() function will seldomly return anything other than the number of bytes contained in the transmit buffer on success.

struct mipi_dsi_host

DSI host device

Definition

struct mipi_dsi_host {
  struct device * dev;
  const struct mipi_dsi_host_ops * ops;
  struct list_head list;
};

Members

struct device * dev
driver model device node for this DSI host
const struct mipi_dsi_host_ops * ops
DSI host operations
struct list_head list
list management
struct mipi_dsi_device_info

template for creating a mipi_dsi_device

Definition

struct mipi_dsi_device_info {
  char type[DSI_DEV_NAME_SIZE];
  u32 channel;
  struct device_node * node;
};

Members

char type[DSI_DEV_NAME_SIZE]
DSI peripheral chip type
u32 channel
DSI virtual channel assigned to peripheral
struct device_node * node
pointer to OF device node or NULL

Description

This is populated and passed to mipi_dsi_device_new to create a new DSI device

struct mipi_dsi_device

DSI peripheral device

Definition

struct mipi_dsi_device {
  struct mipi_dsi_host * host;
  struct device dev;
  char name[DSI_DEV_NAME_SIZE];
  unsigned int channel;
  unsigned int lanes;
  enum mipi_dsi_pixel_format format;
  unsigned long mode_flags;
};

Members

struct mipi_dsi_host * host
DSI host for this peripheral
struct device dev
driver model device node for this peripheral
char name[DSI_DEV_NAME_SIZE]
DSI peripheral chip type
unsigned int channel
virtual channel assigned to the peripheral
unsigned int lanes
number of active data lanes
enum mipi_dsi_pixel_format format
pixel format for video mode
unsigned long mode_flags
DSI operation mode related flags
int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)

obtain the number of bits per pixel for any given pixel format defined by the MIPI DSI specification

Parameters

enum mipi_dsi_pixel_format fmt
MIPI DSI pixel format

Return

The number of bits per pixel of the given pixel format.

enum mipi_dsi_dcs_tear_mode

Tearing Effect Output Line mode

Constants

MIPI_DSI_DCS_TEAR_MODE_VBLANK
the TE output line consists of V-Blanking information only
MIPI_DSI_DCS_TEAR_MODE_VHBLANK
the TE output line consists of both V-Blanking and H-Blanking information
struct mipi_dsi_driver

DSI driver

Definition

struct mipi_dsi_driver {
  struct device_driver driver;
  int(* probe) (struct mipi_dsi_device *dsi);
  int(* remove) (struct mipi_dsi_device *dsi);
  void (* shutdown) (struct mipi_dsi_device *dsi);
};

Members

struct device_driver driver
device driver model driver
int(*)(struct mipi_dsi_device *dsi) probe
callback for device binding
int(*)(struct mipi_dsi_device *dsi) remove
callback for device unbinding
void (*)(struct mipi_dsi_device *dsi) shutdown
called at shutdown time to quiesce the device
struct mipi_dsi_device * of_find_mipi_dsi_device_by_node(struct device_node * np)

find the MIPI DSI device matching a device tree node

Parameters

struct device_node * np
device tree node

Return

A pointer to the MIPI DSI device corresponding to np or NULL if no
such device exists (or has not been registered yet).
struct mipi_dsi_device * mipi_dsi_device_register_full(struct mipi_dsi_host * host, const struct mipi_dsi_device_info * info)

create a MIPI DSI device

Parameters

struct mipi_dsi_host * host
DSI host to which this device is connected
const struct mipi_dsi_device_info * info
pointer to template containing DSI device information

Description

Create a MIPI DSI device by using the device information provided by mipi_dsi_device_info template

Return

A pointer to the newly created MIPI DSI device, or, a pointer encoded with an error

void mipi_dsi_device_unregister(struct mipi_dsi_device * dsi)

unregister MIPI DSI device

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device
struct mipi_dsi_host * of_find_mipi_dsi_host_by_node(struct device_node * node)

find the MIPI DSI host matching a device tree node

Parameters

struct device_node * node
device tree node

Return

A pointer to the MIPI DSI host corresponding to node or NULL if no such device exists (or has not been registered yet).

int mipi_dsi_attach(struct mipi_dsi_device * dsi)

attach a DSI device to its DSI host

Parameters

struct mipi_dsi_device * dsi
DSI peripheral
int mipi_dsi_detach(struct mipi_dsi_device * dsi)

detach a DSI device from its DSI host

Parameters

struct mipi_dsi_device * dsi
DSI peripheral
bool mipi_dsi_packet_format_is_short(u8 type)

check if a packet is of the short format

Parameters

u8 type
MIPI DSI data type of the packet

Return

true if the packet for the given data type is a short packet, false otherwise.

bool mipi_dsi_packet_format_is_long(u8 type)

check if a packet is of the long format

Parameters

u8 type
MIPI DSI data type of the packet

Return

true if the packet for the given data type is a long packet, false otherwise.

int mipi_dsi_create_packet(struct mipi_dsi_packet * packet, const struct mipi_dsi_msg * msg)

create a packet from a message according to the DSI protocol

Parameters

struct mipi_dsi_packet * packet
pointer to a DSI packet structure
const struct mipi_dsi_msg * msg
message to translate into a packet

Return

0 on success or a negative error code on failure.

int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device * dsi)

sends a Shutdown Peripheral command

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device

Return

0 on success or a negative error code on failure.

int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device * dsi)

sends a Turn On Peripheral command

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device

Return

0 on success or a negative error code on failure.

ssize_t mipi_dsi_generic_write(struct mipi_dsi_device * dsi, const void * payload, size_t size)

transmit data using a generic write packet

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device
const void * payload
buffer containing the payload
size_t size
size of payload buffer

Description

This function will automatically choose the right data type depending on the payload length.

Return

The number of bytes transmitted on success or a negative error code on failure.

ssize_t mipi_dsi_generic_read(struct mipi_dsi_device * dsi, const void * params, size_t num_params, void * data, size_t size)

receive data using a generic read packet

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device
const void * params
buffer containing the request parameters
size_t num_params
number of request parameters
void * data
buffer in which to return the received data
size_t size
size of receive buffer

Description

This function will automatically choose the right data type depending on the number of parameters passed in.

Return

The number of bytes successfully read or a negative error code on failure.

ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device * dsi, const void * data, size_t len)

transmit a DCS command with payload

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device
const void * data
buffer containing data to be transmitted
size_t len
size of transmission buffer

Description

This function will automatically choose the right data type depending on the command payload length.

Return

The number of bytes successfully transmitted or a negative error code on failure.

ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device * dsi, u8 cmd, const void * data, size_t len)

send DCS write command

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device
u8 cmd
DCS command
const void * data
buffer containing the command payload
size_t len
command payload length

Description

This function will automatically choose the right data type depending on the command payload length.

Return

The number of bytes successfully transmitted or a negative error code on failure.

ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device * dsi, u8 cmd, void * data, size_t len)

send DCS read request command

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device
u8 cmd
DCS command
void * data
buffer in which to receive data
size_t len
size of receive buffer

Return

The number of bytes read or a negative error code on failure.

int mipi_dsi_dcs_nop(struct mipi_dsi_device * dsi)

send DCS nop packet

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device

Return

0 on success or a negative error code on failure.

int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device * dsi)

perform a software reset of the display module

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device

Return

0 on success or a negative error code on failure.

int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device * dsi, u8 * mode)

query the display module’s current power mode

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device
u8 * mode
return location for the current power mode

Return

0 on success or a negative error code on failure.

int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device * dsi, u8 * format)

gets the pixel format for the RGB image data used by the interface

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device
u8 * format
return location for the pixel format

Return

0 on success or a negative error code on failure.

int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device * dsi)

disable all unnecessary blocks inside the display module except interface communication

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device

Return

0 on success or a negative error code on failure.

int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device * dsi)

enable all blocks inside the display module

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device

Return

0 on success or a negative error code on failure.

int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device * dsi)

stop displaying the image data on the display device

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device

Return

0 on success or a negative error code on failure.

int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device * dsi)

start displaying the image data on the display device

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device

Return

0 on success or a negative error code on failure

int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device * dsi, u16 start, u16 end)

define the column extent of the frame memory accessed by the host processor

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device
u16 start
first column of frame memory
u16 end
last column of frame memory

Return

0 on success or a negative error code on failure.

int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device * dsi, u16 start, u16 end)

define the page extent of the frame memory accessed by the host processor

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device
u16 start
first page of frame memory
u16 end
last page of frame memory

Return

0 on success or a negative error code on failure.

int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device * dsi)

turn off the display module’s Tearing Effect output signal on the TE signal line

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device

Return

0 on success or a negative error code on failure

int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device * dsi, enum mipi_dsi_dcs_tear_mode mode)

turn on the display module’s Tearing Effect output signal on the TE signal line.

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device
enum mipi_dsi_dcs_tear_mode mode
the Tearing Effect Output Line mode

Return

0 on success or a negative error code on failure

int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device * dsi, u8 format)

sets the pixel format for the RGB image data used by the interface

Parameters

struct mipi_dsi_device * dsi
DSI peripheral device
u8 format
pixel format

Return

0 on success or a negative error code on failure.

int mipi_dsi_driver_register_full(struct mipi_dsi_driver * drv, struct module * owner)

register a driver for DSI devices

Parameters

struct mipi_dsi_driver * drv
DSI driver structure
struct module * owner
owner module

Return

0 on success or a negative error code on failure.

void mipi_dsi_driver_unregister(struct mipi_dsi_driver * drv)

unregister a driver for DSI devices

Parameters

struct mipi_dsi_driver * drv
DSI driver structure

Return

0 on success or a negative error code on failure.

EDID Helper Functions Reference

int drm_edid_header_is_valid(const u8 * raw_edid)

sanity check the header of the base EDID block

Parameters

const u8 * raw_edid
pointer to raw base EDID block

Description

Sanity check the header of the base EDID block.

Return

8 if the header is perfect, down to 0 if it’s totally wrong.

bool drm_edid_block_valid(u8 * raw_edid, int block, bool print_bad_edid, bool * edid_corrupt)

Sanity check the EDID block (base or extension)

Parameters

u8 * raw_edid
pointer to raw EDID block
int block
type of block to validate (0 for base, extension otherwise)
bool print_bad_edid
if true, dump bad EDID blocks to the console
bool * edid_corrupt
if true, the header or checksum is invalid

Description

Validate a base or extension EDID block and optionally dump bad blocks to the console.

Return

True if the block is valid, false otherwise.

bool drm_edid_is_valid(struct edid * edid)

sanity check EDID data

Parameters

struct edid * edid
EDID data

Description

Sanity-check an entire EDID record (including extensions)

Return

True if the EDID data is valid, false otherwise.

struct edid * drm_do_get_edid(struct drm_connector * connector, int (*get_edid_block) (void *data, u8 *buf, unsigned int block, size_t len, void * data)

get EDID data using a custom EDID block read function

Parameters

struct drm_connector * connector
connector we’re probing
int (*)(void *data, u8 *buf, unsigned int block,                          &n