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.
-
int
drm_dev_init
(struct drm_device * dev, struct drm_driver * driver, struct device * parent)¶ Initialise new DRM device
Parameters
struct drm_device * dev
- DRM device
struct drm_driver * driver
- DRM driver
struct device * parent
- Parent device object
Description
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.
Drivers that do not want to allocate their own device struct
embedding struct drm_device
can call drm_dev_alloc()
instead.
Return
0 on success, or error code on failure.
-
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.
Drivers that wish to subclass or embed struct drm_device
into their
own struct should look at using drm_dev_init()
instead.
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.
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 drm_device->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 anddrm_gem_object_unreference()
ordrm_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 usingdrm_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()
.
DRM Format Handling¶
-
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.
-
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.
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.
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.
-
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.
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.
-
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. drm_connector_register_all()
is called
automatically from 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.
-
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.
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.
-
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.
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.
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.
-
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.
-
void
drm_crtc_enable_color_mgmt
(struct drm_crtc * crtc, uint degamma_lut_size, bool has_ctm, uint gamma_lut_size)¶ enable color management properties
Parameters
struct drm_crtc * crtc
- DRM CRTC
uint degamma_lut_size
- the size of the degamma lut (before CSC)
bool has_ctm
- whether to attach ctm_property for CSC matrix
uint 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. Each of the properties are optional. The gamma and degamma properties are only attached if their size is not 0 and ctm_property is only attached if has_ctm is true.
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 calldrm_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 * mode_blob;
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 * mode_blob
drm_property_blob
for modestruct 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);
int (* gamma_set) (struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,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.
int (*)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,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 thedrm_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 throughdrm_crtc_vblank_get()
and released withdrm_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 usedrm_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;
char * name;
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 list_head commit_list;
spinlock_t commit_lock;
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
char * name
- human readable name, can be overwritten by the driver
struct drm_modeset_lock mutex
- This provides a read lock for the overall crtc state (mode, dpms state, ...) and a write lock for everything which can be update without a full modeset (fb, cursor data, crtc properties ...). Full modeset also need to grab dev->mode_config.connection_mutex.
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 list_head commit_list
- List of
drm_crtc_commit
structures tracking pending commits. Protected by commit_lock. This list doesn’t hold its own full reference, but burrows it from the ongoing commit. Commit entries must be removed from this list once the commit is fully completed, but before it’s correspodingdrm_atomic_state
gets destroyed. spinlock_t commit_lock
- Spinlock to protect commit_list.
struct drm_modeset_acquire_ctx * acquire_ctx
- Per-CRTC implicit acquire context used by atomic drivers for legacy IOCTLs, so that atomic drivers can get at the locking acquire context.
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);
int (* late_register) (struct drm_connector *connector);
void (* early_unregister) (struct drm_connector *connector);
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()
ordrm_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.
int (*)(struct drm_connector *connector) late_register
This optional hook can be used to register additional userspace interfaces attached to the connector, light backlight control, i2c, DP aux or similar interfaces. It is called late in the driver load sequence from
drm_connector_register()
when registering all the core drm connector interfaces. Everything added from this callback should be unregistered in the early_unregister callback.Returns:
0 on success, or a negative error code on failure.
void (*)(struct drm_connector *connector) early_unregister
- This optional hook should be used to unregister the additional
userspace interfaces attached to the connector from
late_unregister()
. It is called fromdrm_connector_unregister()
, early in the driver unload sequence to disable userspace access before data structures are torndown. 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 usedrm_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
- human readable name, can be overwritten by the driver
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_id;
int connector_type;
int connector_type_id;
bool interlace_allowed;
bool doublescan_allowed;
bool stereo_allowed;
bool registered;
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;
struct drm_property_blob * tile_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
- human readable name, can be overwritten by the driver
int connector_id
- compacted connector id useful indexing arrays
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?
bool registered
- is this connector exposed (registered) with userspace?
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.
struct drm_property_blob * tile_blob_ptr
- DRM blob property data for the tile property (used mostly by DP MST).
This is meant for screens which are driven through separate display
pipelines represented by
drm_crtc
, which might not be running with genlocked clocks. For tiled panels which are genlocked, like dual-link LVDS or dual-link DSI, the driver should try to not expose the tiling and virtualize bothdrm_crtc
anddrm_plane
if needed. 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;
unsigned int rotation;
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)
unsigned int rotation
- rotation of the plane
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 usedrm_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;
char * name;
struct drm_modeset_lock mutex;
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;
const struct drm_plane_helper_funcs * helper_private;
struct drm_plane_state * state;
};
Members
struct drm_device * dev
- DRM device this plane belongs to
struct list_head head
- for list management
char * name
- human readable name, can be overwritten by the driver
struct drm_modeset_lock mutex
- Protects modeset plane state, together with the mutex of
drm_crtc
this plane is linked to (when active, getting actived or getting disabled). 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)
const struct drm_plane_helper_funcs * helper_private
- mid-layer private data
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 nextdrm_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 structdrm_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 structdrm_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 structdrm_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 structdrm_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_crtc_commit
¶ track modeset commits on a CRTC
Definition
struct drm_crtc_commit {
struct drm_crtc * crtc;
struct kref ref;
struct completion flip_done;
struct completion hw_done;
struct completion cleanup_done;
struct list_head commit_entry;
struct drm_pending_vblank_event * event;
};
Members
struct drm_crtc * crtc
- DRM CRTC for this commit.
struct kref ref
- Reference count for this structure. Needed to allow blocking on completions without the risk of the completion disappearing meanwhile.
struct completion flip_done
- Will be signaled when the hardware has flipped to the new set of buffers. Signals at the same time as when the drm event for this commit is sent to userspace, or when an out-fence is singalled. Note that for most hardware, in most cases this happens after hw_done is signalled.
struct completion hw_done
Will be signalled when all hw register changes for this commit have been written out. Especially when disabling a pipe this can be much later than than flip_done, since that can signal already when the screen goes black, whereas to fully shut down a pipe more register I/O is required.
Note that this does not need to include separately reference-counted resources like backing storage buffer pinning, or runtime pm management.
struct completion cleanup_done
- Will be signalled after old buffers have been cleaned up by calling
drm_atomic_helper_cleanup_planes()
. Since this can only happen after a vblank wait completed it might be a bit later. This completion is useful to throttle updates and avoid hardware updates getting ahead of the buffer cleanup too much. struct list_head commit_entry
- Entry on the per-CRTC commit_list. Protected by crtc->commit_lock.
struct drm_pending_vblank_event * event
drm_pending_vblank_event
pointer to clean up private events.
Description
This structure is used to track pending modeset changes and atomic commit on a per-CRTC basis. Since updating the list should never block this structure is reference counted to allow waiters to safely wait on an event to complete, without holding any locks.
It has 3 different events in total to allow a fine-grained synchronization between outstanding updates:
atomic commit thread hardware
write new state into hardware ----> ...
signal hw_done
switch to new state on next
... v/hblank
wait for buffers to show up ...
... send completion irq
irq handler signals flip_done
cleanup old buffers
signal cleanup_done
wait for flip_done <----
clean up atomic state
The important bit to know is that cleanup_done is the terminal event, but the ordering between flip_done and hw_done is entirely up to the specific driver and modeset state change.
For an implementation of how to use this look at
drm_atomic_helper_setup_commit()
from the atomic helper library.
-
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_planes_state * planes;
struct __drm_crtcs_state * crtcs;
int num_connector;
struct __drm_connnectors_state * connectors;
struct drm_modeset_acquire_ctx * acquire_ctx;
struct work_struct commit_work;
};
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_planes_state * planes
- pointer to array of structures with per-plane data
struct __drm_crtcs_state * crtcs
- pointer to array of CRTC pointers
int num_connector
- size of the connectors and connector_states arrays
struct __drm_connnectors_state * connectors
- pointer to array of structures with per-connector data
struct drm_modeset_acquire_ctx * acquire_ctx
- acquire context for this atomic modeset state update
struct work_struct commit_work
- Work item which can be used by the driver or helpers to execute the commit without blocking.
-
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 callingdrm_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 thatdrm_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
throughdrm_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’sdrm_crtc_state
structure. This can be handled by thedrm_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 throughdrm_crtc_vblank_get()
and released withdrm_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 adrm_modeset_lock
deadlock and needs to drop all already acquired locks as part of the deadlock avoidance dance implemented indrm_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 callsdrm_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 idr tile_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;
bool delayed_event;
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;
bool allow_fb_modifiers;
uint32_t cursor_width;
uint32_t cursor_height;
struct drm_mode_config_helper_funcs * helper_private;
};
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. Protects both crtc_idr and tile_idr.
struct idr crtc_idr
- Main KMS ID tracking object. Use this idr for all IDs, fb, crtc, connector, modes - just makes life easier to have only one.
struct idr tile_idr
- Use this idr for allocating new IDs for tiled sinks like use in some high-res DP MST screens.
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
bool delayed_event
- track delayed poll uevent deliver 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?
bool allow_fb_modifiers
- Whether the driver supports fb modifiers in the ADDFB2.1 ioctl call.
uint32_t cursor_width
- hint to userspace for max cursor width
uint32_t cursor_height
- hint to userspace for max cursor height
struct drm_mode_config_helper_funcs * helper_private
- mid-layer private data
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.
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.
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.
-
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.
-
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.
Parameters
struct drm_plane * plane
- plane to find index for
Description
Given a registered plane, return the index of that plane within a DRM device’s list of planes.
-
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(:c:type:`ctx`)
retry:
foreach (lock in random_ordered_set_of_locks) {
ret = drm_modeset_lock(lock, :c:type:`ctx`)
if (ret == -EDEADLK) {
drm_modeset_backoff(:c:type:`ctx`);
goto retry;
}
}
... do stuff ...
drm_modeset_drop_locks(:c:type:`ctx`);
drm_modeset_acquire_fini(:c:type:`ctx`);
On top of of these per-object locks using :c:type:`ww_mutex` there's also an overall
dev->mode_config.lock, for protecting everything else. Mostly this means
probe state of connectors, and preventing hotplug add/removal of connectors.
Finally there's a bunch of dedicated locks to protect drm core internal
lists and lookup data structures.
-
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.
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¶
Nonblocking atomic commits have to be implemented in the following sequence:
1. Run drm_atomic_helper_prepare_planes()
first. This is the only function
which commit needs to call which can fail, so we want to run it first and
synchronously.
2. Synchronize with any outstanding nonblocking commit worker threads which might be affected the new state update. This can be done by either cancelling or flushing the work items, depending upon whether the driver can deal with cancelled updates. Note that it is important to ensure that the framebuffer cleanup is still done when cancelling.
Asynchronous workers need to have sufficient parallelism to be able to run
different atomic commits on different CRTCs in parallel. The simplest way to
achive this is by running them on the system_unbound_wq
work queue. Note
that drivers are not required to split up atomic commits and run an
individual commit in parallel - userspace is supposed to do that if it cares.
But it might be beneficial to do that for modesets, since those necessarily
must be done as one global operation, and enabling or disabling a CRTC can
take a long time. But even that is not required.
3. The software state is updated synchronously with
drm_atomic_helper_swap_state()
. Doing this under the protection of all modeset
locks means concurrent callers never see inconsistent state. And doing this
while it’s guaranteed that no relevant nonblocking worker runs means that
nonblocking workers do not need grab any locks. Actually they must not grab
locks, for otherwise the work flushing will deadlock.
4. Schedule a work item to do all subsequent steps, using the split-out commit helpers: a) pre-plane commit b) plane commit c) post-plane commit and then cleaning up the framebuffers after the old framebuffer is no longer being displayed.
The above scheme is implemented in the atomic helper libraries in
drm_atomic_helper_commit()
using a bunch of helper functions. See
drm_atomic_helper_setup_commit()
for a starting point.
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_atomic_crtc_state_for_each_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.
-
drm_atomic_crtc_state_for_each_plane_state
(plane, plane_state, crtc_state)¶ iterate over attached planes in new state
Parameters
plane
- the loop cursor
plane_state
- loop cursor for the plane’s state, must be const
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.
Compared to just drm_atomic_crtc_state_for_each_plane()
this also fills in a
const plane_state. This is useful when a driver just wants to peek at other
active planes on this crtc, but does not need to change it.
-
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.
Return
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.
Return
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.
Return
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.
-
void
drm_atomic_helper_commit_tail
(struct drm_atomic_state * state)¶ commit atomic update to hardware
Parameters
struct drm_atomic_state * state
- new modeset state to be committed
Description
This is the default implemenation for the ->:c:func:atomic_commit_tail() hook of the
drm_mode_config_helper_funcs
vtable.
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 instead
drm_atomic_helper_commit_modeset_disables(dev, state);
drm_atomic_helper_commit_modeset_enables(dev, state);
drm_atomic_helper_commit_planes(dev, state, true);
for committing the atomic update to hardware. See the kerneldoc entries for these three functions for more details.
-
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
- whether nonblocking behavior is requested.
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. This
function implements nonblocking commits, using
drm_atomic_helper_setup_commit()
and related functions.
Note that right now this function does not support nonblocking commits, hence driver writers must implement their own version for now.
Committing the actual hardware state is done through the
->:c:func:atomic_commit_tail() callback of the drm_mode_config_helper_funcs
vtable,
or it’s default implementation drm_atomic_helper_commit_tail()
.
Return
Zero for success or -errno.
-
int
drm_atomic_helper_setup_commit
(struct drm_atomic_state * state, bool nonblock)¶ setup possibly nonblocking commit
Parameters
struct drm_atomic_state * state
- new modeset state to be committed
bool nonblock
- whether nonblocking behavior is requested.
Description
This function prepares state to be used by the atomic helper’s support for nonblocking commits. Drivers using the nonblocking commit infrastructure should always call this function from their ->atomic_commit hook.
To be able to use this support drivers need to use a few more helper
functions. drm_atomic_helper_wait_for_dependencies()
must be called before
actually committing the hardware state, and for nonblocking commits this call
must be placed in the async worker. See also drm_atomic_helper_swap_state()
and it’s stall parameter, for when a driver’s commit hooks look at the
->state pointers of struct drm_crtc
, drm_plane
or drm_connector
directly.
Completion of the hardware commit step must be signalled using
drm_atomic_helper_commit_hw_done()
. After this step the driver is not allowed
to read or change any permanent software or hardware modeset state. The only
exception is state protected by other means than drm_modeset_lock
locks.
Only the free standing state with pointers to the old state structures can
be inspected, e.g. to clean up old buffers using
drm_atomic_helper_cleanup_planes()
.
At the very end, before cleaning up state drivers must call
drm_atomic_helper_commit_cleanup_done()
.
This is all implemented by in drm_atomic_helper_commit()
, giving drivers a
complete and esay-to-use default implementation of the atomic_commit()
hook.
The tracking of asynchronously executed and still pending commits is done
using the core structure drm_crtc_commit
.
By default there’s no need to clean up resources allocated by this function
explicitly: drm_atomic_state_default_clear()
will take care of that
automatically.
Return
0 on success. -EBUSY when userspace schedules nonblocking commits too fast, -ENOMEM on allocation failures and -EINTR when a signal is pending.
-
void
drm_atomic_helper_wait_for_dependencies
(struct drm_atomic_state * state)¶ wait for required preceeding commits
Parameters
struct drm_atomic_state * state
- new modeset state to be committed
Description
This function waits for all preceeding commits that touch the same CRTC as
state to both be committed to the hardware (as signalled by
drm_atomic_helper_commit_hw_done) and executed by the hardware (as signalled
by calling drm_crtc_vblank_send_event on the event member of
drm_crtc_state
).
This is part of the atomic helper support for nonblocking commits, see
drm_atomic_helper_setup_commit()
for an overview.
-
void
drm_atomic_helper_commit_hw_done
(struct drm_atomic_state * state)¶ setup possible nonblocking commit
Parameters
struct drm_atomic_state * state
- new modeset state to be committed
Description
This function is used to signal completion of the hardware commit step. After
this step the driver is not allowed to read or change any permanent software
or hardware modeset state. The only exception is state protected by other
means than drm_modeset_lock
locks.
Drivers should try to postpone any expensive or delayed cleanup work after this function is called.
This is part of the atomic helper support for nonblocking commits, see
drm_atomic_helper_setup_commit()
for an overview.
-
void
drm_atomic_helper_commit_cleanup_done
(struct drm_atomic_state * state)¶ signal completion of commit
Parameters
struct drm_atomic_state * state
- new modeset state to be committed
Description
This signals completion of the atomic update state, including any cleanup
work. If used, it must be called right before calling
drm_atomic_state_free()
.
This is part of the atomic helper support for nonblocking commits, see
drm_atomic_helper_setup_commit()
for an overview.
-
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_atomic_state * state, bool stall)¶ store atomic state into current sw state
Parameters
struct drm_atomic_state * state
- atomic state
bool stall
- stall for proceeding commits
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:
- Call
drm_atomic_helper_prepare_planes()
with the staged atomic state. - Do any other steps that might fail.
- Put the staged state into the current state pointers with this function.
- 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.
stall must be set when nonblocking commits for this driver directly access
the ->state pointer of drm_plane
, drm_crtc
or drm_connector
. With the
current atomic helpers this is almost always the case, since the helpers
don’t pass the right state structures to the callbacks.
-
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.
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.
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.
-
int
drm_atomic_helper_legacy_gamma_set
(struct drm_crtc * crtc, u16 * red, u16 * green, u16 * blue, 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 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
anddrm_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 indrm_atomic_helper_check_modeset()
. Therefore drivers that want to check output routing and display mode constraints in this callback must ensure thatdrm_atomic_helper_check_modeset()
has been called beforehand. This is calling order used by the default helper implementation indrm_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 adrm_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 usingdrm_mode_probed_add()
. Drivers which manually add modes should also make sure that the display_info, width_mm and height_mm fields of the structdrm_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 usingdrm_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.
You can leave this function to NULL if the connector is only attached to a single encoder and you are using the atomic helpers. In this case, the core will call
drm_atomic_helper_best_encoder()
for you.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()
. If it is not implemented, the core will fallback to best_encoder (ordrm_atomic_helper_best_encoder()
if best_encoder is NULL).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 indrm_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
-
struct
drm_mode_config_helper_funcs
¶ global modeset helper operations
Definition
struct drm_mode_config_helper_funcs {
void (* atomic_commit_tail) (struct drm_atomic_state *state);
};
Members
void (*)(struct drm_atomic_state *state) atomic_commit_tail
This hook is used by the default
atomic_commit()
hook implemented indrm_atomic_helper_commit()
together with the nonblocking commit helpers (seedrm_atomic_helper_setup_commit()
for a starting point) to implement blocking and nonblocking commits easily. It is not used by the atomic helpersThis hook should first commit the given atomic state to the hardware. But drivers can add more waiting calls at the start of their implementation, e.g. to wait for driver-internal request for implicit syncing, before starting to commit the update to the hardware.
After the atomic update is committed to the hardware this hook needs to call
drm_atomic_helper_commit_hw_done()
. Then wait for the upate to be executed by the hardware, for example usingdrm_atomic_helper_wait_for_vblanks()
, and then clean up the old framebuffers usingdrm_atomic_helper_cleanup_planes()
.When disabling a CRTC this hook _must_ stall for the commit to complete. Vblank waits don’t work on disabled CRTC, hence the core can’t take care of this. And it also can’t rely on the vblank event, since that can be signalled already when the screen shows black, which can happen much earlier than the last hardware access needed to shut off the display pipeline completely.
This hook is optional, the default implementation is
drm_atomic_helper_commit_tail()
.
Description
These helper functions are used by the atomic helpers.
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.
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.
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
All modes currently on the connector’s modes list are marked as stale
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.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.Any non-stale mode on the modes list then undergoes validation
drm_mode_validate_basic()
performs basic sanity checksdrm_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
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
-
void
drm_fb_helper_unlink_fbi
(struct drm_fb_helper * fb_helper)¶ 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;
};
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.
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,
:c:type:`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,
:c:type:`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
- DRM device
struct drm_file * file_priv
- drm file for the ioctl call
const struct drm_mode_fb_cmd2 * mode_cmd
- metadata from the userspace fb creation request
const struct drm_framebuffer_funcs * funcs
- vtable to be used for the new framebuffer object
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
- DRM device
struct drm_file * file_priv
- drm file for the ioctl call
const struct drm_mode_fb_cmd2 * mode_cmd
- metadata from the userspace fb creation request
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
- output file
void * arg
- private data for the callback
-
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.
-
int
drm_dp_dpcd_read_link_status
(struct drm_dp_aux * aux, u8 status[DP_LINK_STATUS_SIZE])¶ 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.
-
int
drm_dp_link_probe
(struct drm_dp_aux * aux, struct drm_dp_link * link)¶ 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.
-
int
drm_dp_link_power_up
(struct drm_dp_aux * aux, struct drm_dp_link * link)¶ 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.
-
int
drm_dp_link_power_down
(struct drm_dp_aux * aux, struct drm_dp_link * link)¶ 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.
-
int
drm_dp_link_configure
(struct drm_dp_aux * aux, struct drm_dp_link * link)¶ 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.
-
void
drm_dp_aux_init
(struct drm_dp_aux * aux)¶ minimally initialise an aux channel
Parameters
struct drm_dp_aux * aux
- DisplayPort AUX channel
Description
If you need to use the drm_dp_aux’s i2c adapter prior to registering it
with the outside world, call drm_dp_aux_init()
first. You must still
call drm_dp_aux_register()
once the connector has been registered to
allow userspace access to the auxiliary DP channel.
-
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
Automatically calls drm_dp_aux_init()
if this hasn’t been done yet.
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_set_tear_scanline
(struct mipi_dsi_device * dsi, u16 param)¶ turn on the display module’s Tearing Effect output signal on the TE signal line when display module reaches line N defined by STS[n:0].
Parameters
struct mipi_dsi_device * dsi
- DSI peripheral device
u16 param
- STS[10:0]
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, size_t len) get_edid_block
- EDID block read function
void * data
- private data passed to the block read function
Description
When the I2C adapter connected to the DDC bus is hidden behind a device that exposes a different interface to read EDID blocks this function can be used to get EDID data using a custom block read function.
As in the general case the DDC bus is accessible by the kernel at the I2C
level, drivers must make all reasonable efforts to expose it as an I2C
adapter and use drm_get_edid()
instead of abusing this function.
Return
Pointer to valid EDID or NULL if we couldn’t find any.
-
bool
drm_probe_ddc
(struct i2c_adapter * adapter)¶ probe DDC presence
Parameters
struct i2c_adapter * adapter
- I2C adapter to probe
Return
True on success, false on failure.
-
struct edid *
drm_get_edid
(struct drm_connector * connector, struct i2c_adapter * adapter)¶ get EDID data, if available
Parameters
struct drm_connector * connector
- connector we’re probing
struct i2c_adapter * adapter
- I2C adapter to use for DDC
Description
Poke the given I2C channel to grab EDID data if possible. If found, attach it to the connector.
Return
Pointer to valid EDID or NULL if we couldn’t find any.
-
struct edid *
drm_get_edid_switcheroo
(struct drm_connector * connector, struct i2c_adapter * adapter)¶ get EDID data for a vga_switcheroo output
Parameters
struct drm_connector * connector
- connector we’re probing
struct i2c_adapter * adapter
- I2C adapter to use for DDC
Description
Wrapper around drm_get_edid()
for laptops with dual GPUs using one set of
outputs. The wrapper adds the requisite vga_switcheroo calls to temporarily
switch DDC to the GPU which is retrieving EDID.
Return
Pointer to valid EDID or NULL
if we couldn’t find any.
-
struct edid *
drm_edid_duplicate
(const struct edid * edid)¶ duplicate an EDID and the extensions
Parameters
const struct edid * edid
- EDID to duplicate
Return
Pointer to duplicated EDID or NULL on allocation failure.
-
u8
drm_match_cea_mode
(const struct drm_display_mode * to_match)¶ look for a CEA mode matching given mode
Parameters
const struct drm_display_mode * to_match
- display mode
Return
The CEA Video ID (VIC) of the mode or 0 if it isn’t a CEA-861 mode.
-
enum hdmi_picture_aspect
drm_get_cea_aspect_ratio
(const u8 video_code)¶ get the picture aspect ratio corresponding to the input VIC from the CEA mode list
Parameters
const u8 video_code
- ID given to each of the CEA modes
Description
Returns picture aspect ratio
-
void
drm_edid_get_monitor_name
(struct edid * edid, char * name, int bufsize)¶ fetch the monitor name from the edid
Parameters
struct edid * edid
- monitor EDID information
char * name
- pointer to a character array to hold the name of the monitor
int bufsize
- The size of the name buffer (should be at least 14 chars.)
-
void
drm_edid_to_eld
(struct drm_connector * connector, struct edid * edid)¶ build ELD from EDID
Parameters
struct drm_connector * connector
- connector corresponding to the HDMI/DP sink
struct edid * edid
- EDID to parse
Description
Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. The Conn_Type, HDCP and Port_ID ELD fields are left for the graphics driver to fill in.
-
int
drm_edid_to_sad
(struct edid * edid, struct cea_sad ** sads)¶ extracts SADs from EDID
Parameters
struct edid * edid
- EDID to parse
struct cea_sad ** sads
- pointer that will be set to the extracted SADs
Description
Looks for CEA EDID block and extracts SADs (Short Audio Descriptors) from it.
Note
The returned pointer needs to be freed using kfree()
.
Return
The number of found SADs or negative number on error.
-
int
drm_edid_to_speaker_allocation
(struct edid * edid, u8 ** sadb)¶ extracts Speaker Allocation Data Blocks from EDID
Parameters
struct edid * edid
- EDID to parse
u8 ** sadb
- pointer to the speaker block
Description
Looks for CEA EDID block and extracts the Speaker Allocation Data Block from it.
Note
The returned pointer needs to be freed using kfree()
.
Return
The number of found Speaker Allocation Blocks or negative number on error.
-
int
drm_av_sync_delay
(struct drm_connector * connector, const struct drm_display_mode * mode)¶ compute the HDMI/DP sink audio-video sync delay
Parameters
struct drm_connector * connector
- connector associated with the HDMI/DP sink
const struct drm_display_mode * mode
- the display mode
Return
The HDMI/DP sink’s audio-video sync delay in milliseconds or 0 if the sink doesn’t support audio or video.
-
struct drm_connector *
drm_select_eld
(struct drm_encoder * encoder)¶ select one ELD from multiple HDMI/DP sinks
Parameters
struct drm_encoder * encoder
- the encoder just changed display mode
Description
It’s possible for one encoder to be associated with multiple HDMI/DP sinks. The policy is now hard coded to simply use the first HDMI/DP sink’s ELD.
Return
The connector associated with the first HDMI/DP sink that has ELD attached to it.
-
bool
drm_detect_hdmi_monitor
(struct edid * edid)¶ detect whether monitor is HDMI
Parameters
struct edid * edid
- monitor EDID information
Description
Parse the CEA extension according to CEA-861-B.
Return
True if the monitor is HDMI, false if not or unknown.
-
bool
drm_detect_monitor_audio
(struct edid * edid)¶ check monitor audio capability
Parameters
struct edid * edid
- EDID block to scan
Description
Monitor should have CEA extension block. If monitor has ‘basic audio’, but no CEA audio blocks, it’s ‘basic audio’ only. If there is any audio extension block and supported audio format, assume at least ‘basic audio’ support, even if ‘basic audio’ is not defined in EDID.
Return
True if the monitor supports audio, false otherwise.
-
bool
drm_rgb_quant_range_selectable
(struct edid * edid)¶ is RGB quantization range selectable?
Parameters
struct edid * edid
- EDID block to scan
Description
Check whether the monitor reports the RGB quantization range selection as supported. The AVI infoframe can then be used to inform the monitor which quantization range (full or limited) is used.
Return
True if the RGB quantization range is selectable, false otherwise.
-
int
drm_add_edid_modes
(struct drm_connector * connector, struct edid * edid)¶ add modes from EDID data, if available
Parameters
struct drm_connector * connector
- connector we’re probing
struct edid * edid
- EDID data
Description
Add the specified modes to the connector’s mode list.
Return
The number of modes added or 0 if we couldn’t find any.
-
int
drm_add_modes_noedid
(struct drm_connector * connector, int hdisplay, int vdisplay)¶ add modes for the connectors without EDID
Parameters
struct drm_connector * connector
- connector we’re probing
int hdisplay
- the horizontal display limit
int vdisplay
- the vertical display limit
Description
Add the specified modes to the connector’s mode list. Only when the hdisplay/vdisplay is not beyond the given limit, it will be added.
Return
The number of modes added or 0 if we couldn’t find any.
-
void
drm_set_preferred_mode
(struct drm_connector * connector, int hpref, int vpref)¶ Sets the preferred mode of a connector
Parameters
struct drm_connector * connector
- connector whose mode list should be processed
int hpref
- horizontal resolution of preferred mode
int vpref
- vertical resolution of preferred mode
Description
Marks a mode as preferred if it matches the resolution specified by hpref and vpref.
-
int
drm_hdmi_avi_infoframe_from_display_mode
(struct hdmi_avi_infoframe * frame, const struct drm_display_mode * mode)¶ fill an HDMI AVI infoframe with data from a DRM display mode
Parameters
struct hdmi_avi_infoframe * frame
- HDMI AVI infoframe
const struct drm_display_mode * mode
- DRM display mode
Return
0 on success or a negative error code on failure.
-
int
drm_hdmi_vendor_infoframe_from_display_mode
(struct hdmi_vendor_infoframe * frame, const struct drm_display_mode * mode)¶ fill an HDMI infoframe with data from a DRM display mode
Parameters
struct hdmi_vendor_infoframe * frame
- HDMI vendor infoframe
const struct drm_display_mode * mode
- DRM display mode
Description
Note that there’s is a need to send HDMI vendor infoframes only when using a 4k or stereoscopic 3D mode. So when giving any other mode as input this function will return -EINVAL, error that can be safely ignored.
Return
0 on success or a negative error code on failure.
Rectangle Utilities Reference¶
Utility functions to help manage rectangular areas for clipping, scaling, etc. calculations.
-
struct
drm_rect
¶ two dimensional rectangle
Definition
struct drm_rect {
int x1;
int y1;
int x2;
int y2;
};
Members
int x1
- horizontal starting coordinate (inclusive)
int y1
- vertical starting coordinate (inclusive)
int x2
- horizontal ending coordinate (exclusive)
int y2
- vertical ending coordinate (exclusive)
Parameters
struct drm_rect * r
- rectangle to be adjusted
int dw
- horizontal adjustment
int dh
- vertical adjustment
Description
Change the size of rectangle r by dw in the horizontal direction, and by dh in the vertical direction, while keeping the center of r stationary.
Positive dw and dh increase the size, negative values decrease it.
Parameters
struct drm_rect * r
- rectangle to be tranlated
int dx
- horizontal translation
int dy
- vertical translation
Description
Move rectangle r by dx in the horizontal direction, and by dy in the vertical direction.
Parameters
struct drm_rect * r
- rectangle to be downscaled
int horz
- horizontal downscale factor
int vert
- vertical downscale factor
Description
Divide the coordinates of rectangle r by horz and vert.
Parameters
const struct drm_rect * r
- rectangle whose width is returned
Return
The width of the rectangle.
Parameters
const struct drm_rect * r
- rectangle whose height is returned
Return
The height of the rectangle.
Parameters
const struct drm_rect * r
- rectangle whose visibility is returned
Return
true
if the rectangle is visible, false
otherwise.
-
bool
drm_rect_equals
(const struct drm_rect * r1, const struct drm_rect * r2)¶ determine if two rectangles are equal
Parameters
const struct drm_rect * r1
- first rectangle
const struct drm_rect * r2
- second rectangle
Return
true
if the rectangles are equal, false
otherwise.
Parameters
struct drm_rect * r1
- first rectangle
const struct drm_rect * r2
- second rectangle
Description
Calculate the intersection of rectangles r1 and r2. r1 will be overwritten with the intersection.
Return
true
if rectangle r1 is still visible after the operation,
false
otherwise.
-
bool
drm_rect_clip_scaled
(struct drm_rect * src, struct drm_rect * dst, const struct drm_rect * clip, int hscale, int vscale)¶ perform a scaled clip operation
Parameters
struct drm_rect * src
- source window rectangle
struct drm_rect * dst
- destination window rectangle
const struct drm_rect * clip
- clip rectangle
int hscale
- horizontal scaling factor
int vscale
- vertical scaling factor
Description
Clip rectangle dst by rectangle clip. Clip rectangle src by the same amounts multiplied by hscale and vscale.
Return
true
if rectangle dst is still visible after being clipped,
false
otherwise
-
int
drm_rect_calc_hscale
(const struct drm_rect * src, const struct drm_rect * dst, int min_hscale, int max_hscale)¶ calculate the horizontal scaling factor
Parameters
const struct drm_rect * src
- source window rectangle
const struct drm_rect * dst
- destination window rectangle
int min_hscale
- minimum allowed horizontal scaling factor
int max_hscale
- maximum allowed horizontal scaling factor
Description
Calculate the horizontal scaling factor as (src width) / (dst width).
Return
The horizontal scaling factor, or errno of out of limits.
-
int
drm_rect_calc_vscale
(const struct drm_rect * src, const struct drm_rect * dst, int min_vscale, int max_vscale)¶ calculate the vertical scaling factor
Parameters
const struct drm_rect * src
- source window rectangle
const struct drm_rect * dst
- destination window rectangle
int min_vscale
- minimum allowed vertical scaling factor
int max_vscale
- maximum allowed vertical scaling factor
Description
Calculate the vertical scaling factor as (src height) / (dst height).
Return
The vertical scaling factor, or errno of out of limits.
-
int
drm_rect_calc_hscale_relaxed
(struct drm_rect * src, struct drm_rect * dst, int min_hscale, int max_hscale)¶ calculate the horizontal scaling factor
Parameters
struct drm_rect * src
- source window rectangle
struct drm_rect * dst
- destination window rectangle
int min_hscale
- minimum allowed horizontal scaling factor
int max_hscale
- maximum allowed horizontal scaling factor
Description
Calculate the horizontal scaling factor as (src width) / (dst width).
If the calculated scaling factor is below min_vscale, decrease the height of rectangle dst to compensate.
If the calculated scaling factor is above max_vscale, decrease the height of rectangle src to compensate.
Return
The horizontal scaling factor.
-
int
drm_rect_calc_vscale_relaxed
(struct drm_rect * src, struct drm_rect * dst, int min_vscale, int max_vscale)¶ calculate the vertical scaling factor
Parameters
struct drm_rect * src
- source window rectangle
struct drm_rect * dst
- destination window rectangle
int min_vscale
- minimum allowed vertical scaling factor
int max_vscale
- maximum allowed vertical scaling factor
Description
Calculate the vertical scaling factor as (src height) / (dst height).
If the calculated scaling factor is below min_vscale, decrease the height of rectangle dst to compensate.
If the calculated scaling factor is above max_vscale, decrease the height of rectangle src to compensate.
Return
The vertical scaling factor.
-
void
drm_rect_debug_print
(const char * prefix, const struct drm_rect * r, bool fixed_point)¶ print the rectangle information
Parameters
const char * prefix
- prefix string
const struct drm_rect * r
- rectangle to print
bool fixed_point
- rectangle is in 16.16 fixed point format
-
void
drm_rect_rotate
(struct drm_rect * r, int width, int height, unsigned int rotation)¶ Rotate the rectangle
Parameters
struct drm_rect * r
- rectangle to be rotated
int width
- Width of the coordinate space
int height
- Height of the coordinate space
unsigned int rotation
- Transformation to be applied
Description
Apply rotation to the coordinates of rectangle r.
width and height combined with rotation define the location of the new origin.
width correcsponds to the horizontal and height to the vertical axis of the untransformed coordinate space.
-
void
drm_rect_rotate_inv
(struct drm_rect * r, int width, int height, unsigned int rotation)¶ Inverse rotate the rectangle
Parameters
struct drm_rect * r
- rectangle to be rotated
int width
- Width of the coordinate space
int height
- Height of the coordinate space
unsigned int rotation
- Transformation whose inverse is to be applied
Description
Apply the inverse of rotation to the coordinates of rectangle r.
width and height combined with rotation define the location of the new origin.
width correcsponds to the horizontal and height to the vertical axis of the original untransformed coordinate space, so that you never have to flip them when doing a rotatation and its inverse. That is, if you do:
drm_rotate(r
, width, height, rotation);
drm_rotate_inv(r
, width, height, rotation);
you will always get back the original rectangle.
Flip-work Helper Reference¶
Util to queue up work to run from work-queue context after flip/vblank. Typically this can be used to defer unref of framebuffer’s, cursor bo’s, etc until after vblank. The APIs are all thread-safe. Moreover, drm_flip_work_queue_task and drm_flip_work_queue can be called in atomic context.
-
struct
drm_flip_task
¶ flip work task
Definition
struct drm_flip_task {
struct list_head node;
void * data;
};
Members
struct list_head node
- list entry element
void * data
- data to pass to work->func
-
struct
drm_flip_work
¶ flip work queue
Definition
struct drm_flip_work {
const char * name;
drm_flip_func_t func;
struct work_struct worker;
struct list_head queued;
struct list_head commited;
spinlock_t lock;
};
Members
const char * name
- debug name
drm_flip_func_t func
- callback fxn called for each committed item
struct work_struct worker
- worker which calls func
struct list_head queued
- queued tasks
struct list_head commited
- commited tasks
spinlock_t lock
- lock to access queued and commited lists
-
struct drm_flip_task *
drm_flip_work_allocate_task
(void * data, gfp_t flags)¶ allocate a flip-work task
Parameters
void * data
- data associated to the task
gfp_t flags
- allocator flags
Description
Allocate a drm_flip_task object and attach private data to it.
-
void
drm_flip_work_queue_task
(struct drm_flip_work * work, struct drm_flip_task * task)¶ queue a specific task
Parameters
struct drm_flip_work * work
- the flip-work
struct drm_flip_task * task
- the task to handle
Description
Queues task, that will later be run (passed back to drm_flip_func_t
func) on a work queue after drm_flip_work_commit()
is called.
-
void
drm_flip_work_queue
(struct drm_flip_work * work, void * val)¶ queue work
Parameters
struct drm_flip_work * work
- the flip-work
void * val
- the value to queue
Description
Queues work, that will later be run (passed back to drm_flip_func_t
func) on a work queue after drm_flip_work_commit()
is called.
-
void
drm_flip_work_commit
(struct drm_flip_work * work, struct workqueue_struct * wq)¶ commit queued work
Parameters
struct drm_flip_work * work
- the flip-work
struct workqueue_struct * wq
- the work-queue to run the queued work on
Description
Trigger work previously queued by drm_flip_work_queue()
to run
on a workqueue. The typical usage would be to queue work (via
drm_flip_work_queue()
) at any point (from vblank irq and/or
prior), and then from vblank irq commit the queued work.
-
void
drm_flip_work_init
(struct drm_flip_work * work, const char * name, drm_flip_func_t func)¶ initialize flip-work
Parameters
struct drm_flip_work * work
- the flip-work to initialize
const char * name
- debug name
drm_flip_func_t func
- the callback work function
Description
Initializes/allocates resources for the flip-work
-
void
drm_flip_work_cleanup
(struct drm_flip_work * work)¶ cleans up flip-work
Parameters
struct drm_flip_work * work
- the flip-work to cleanup
Description
Destroy resources allocated for the flip-work
HDMI Infoframes Helper Reference¶
Strictly speaking this is not a DRM helper library but generally useable by any driver interfacing with HDMI outputs like v4l or alsa drivers. But it nicely fits into the overall topic of mode setting helper libraries and hence is also included here.
-
union
hdmi_infoframe
¶ overall union of all abstract infoframe representations
Definition
union hdmi_infoframe {
struct hdmi_any_infoframe any;
struct hdmi_avi_infoframe avi;
struct hdmi_spd_infoframe spd;
union hdmi_vendor_any_infoframe vendor;
struct hdmi_audio_infoframe audio;
};
Members
struct hdmi_any_infoframe any
- generic infoframe
struct hdmi_avi_infoframe avi
- avi infoframe
struct hdmi_spd_infoframe spd
- spd infoframe
union hdmi_vendor_any_infoframe vendor
- union of all vendor infoframes
struct hdmi_audio_infoframe audio
- audio infoframe
Description
This is used by the generic pack function. This works since all infoframes have the same header which also indicates which type of infoframe should be packed.
-
int
hdmi_avi_infoframe_init
(struct hdmi_avi_infoframe * frame)¶ initialize an HDMI AVI infoframe
Parameters
struct hdmi_avi_infoframe * frame
- HDMI AVI infoframe
Description
Returns 0 on success or a negative error code on failure.
-
ssize_t
hdmi_avi_infoframe_pack
(struct hdmi_avi_infoframe * frame, void * buffer, size_t size)¶ write HDMI AVI infoframe to binary buffer
Parameters
struct hdmi_avi_infoframe * frame
- HDMI AVI infoframe
void * buffer
- destination buffer
size_t size
- size of buffer
Description
Packs the information contained in the frame structure into a binary representation that can be written into the corresponding controller registers. Also computes the checksum as required by section 5.3.5 of the HDMI 1.4 specification.
Returns the number of bytes packed into the binary buffer or a negative error code on failure.
-
int
hdmi_spd_infoframe_init
(struct hdmi_spd_infoframe * frame, const char * vendor, const char * product)¶ initialize an HDMI SPD infoframe
Parameters
struct hdmi_spd_infoframe * frame
- HDMI SPD infoframe
const char * vendor
- vendor string
const char * product
- product string
Description
Returns 0 on success or a negative error code on failure.
-
ssize_t
hdmi_spd_infoframe_pack
(struct hdmi_spd_infoframe * frame, void * buffer, size_t size)¶ write HDMI SPD infoframe to binary buffer
Parameters
struct hdmi_spd_infoframe * frame
- HDMI SPD infoframe
void * buffer
- destination buffer
size_t size
- size of buffer
Description
Packs the information contained in the frame structure into a binary representation that can be written into the corresponding controller registers. Also computes the checksum as required by section 5.3.5 of the HDMI 1.4 specification.
Returns the number of bytes packed into the binary buffer or a negative error code on failure.
-
int
hdmi_audio_infoframe_init
(struct hdmi_audio_infoframe * frame)¶ initialize an HDMI audio infoframe
Parameters
struct hdmi_audio_infoframe * frame
- HDMI audio infoframe
Description
Returns 0 on success or a negative error code on failure.
-
ssize_t
hdmi_audio_infoframe_pack
(struct hdmi_audio_infoframe * frame, void * buffer, size_t size)¶ write HDMI audio infoframe to binary buffer
Parameters
struct hdmi_audio_infoframe * frame
- HDMI audio infoframe
void * buffer
- destination buffer
size_t size
- size of buffer
Description
Packs the information contained in the frame structure into a binary representation that can be written into the corresponding controller registers. Also computes the checksum as required by section 5.3.5 of the HDMI 1.4 specification.
Returns the number of bytes packed into the binary buffer or a negative error code on failure.
-
int
hdmi_vendor_infoframe_init
(struct hdmi_vendor_infoframe * frame)¶ initialize an HDMI vendor infoframe
Parameters
struct hdmi_vendor_infoframe * frame
- HDMI vendor infoframe
Description
Returns 0 on success or a negative error code on failure.
-
ssize_t
hdmi_vendor_infoframe_pack
(struct hdmi_vendor_infoframe * frame, void * buffer, size_t size)¶ write a HDMI vendor infoframe to binary buffer
Parameters
struct hdmi_vendor_infoframe * frame
- HDMI infoframe
void * buffer
- destination buffer
size_t size
- size of buffer
Description
Packs the information contained in the frame structure into a binary representation that can be written into the corresponding controller registers. Also computes the checksum as required by section 5.3.5 of the HDMI 1.4 specification.
Returns the number of bytes packed into the binary buffer or a negative error code on failure.
-
ssize_t
hdmi_infoframe_pack
(union hdmi_infoframe * frame, void * buffer, size_t size)¶ write a HDMI infoframe to binary buffer
Parameters
union hdmi_infoframe * frame
- HDMI infoframe
void * buffer
- destination buffer
size_t size
- size of buffer
Description
Packs the information contained in the frame structure into a binary representation that can be written into the corresponding controller registers. Also computes the checksum as required by section 5.3.5 of the HDMI 1.4 specification.
Returns the number of bytes packed into the binary buffer or a negative error code on failure.
-
void
hdmi_infoframe_log
(const char * level, struct device * dev, union hdmi_infoframe * frame)¶ log info of HDMI infoframe
Parameters
const char * level
- logging level
struct device * dev
- device
union hdmi_infoframe * frame
- HDMI infoframe
-
int
hdmi_infoframe_unpack
(union hdmi_infoframe * frame, void * buffer)¶ unpack binary buffer to a HDMI infoframe
Parameters
union hdmi_infoframe * frame
- HDMI infoframe
void * buffer
- source buffer
Description
Unpacks the information contained in binary buffer buffer into a structured frame of a HDMI infoframe. Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 specification.
Returns 0 on success or a negative error code on failure.
Plane Helper Reference¶
-
int
drm_plane_helper_check_update
(struct drm_plane * plane, struct drm_crtc * crtc, struct drm_framebuffer * fb, struct drm_rect * src, struct drm_rect * dest, const struct drm_rect * clip, unsigned int rotation, int min_scale, int max_scale, bool can_position, bool can_update_disabled, bool * visible)¶ Check plane update for validity
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
struct drm_rect * src
- source coordinates in 16.16 fixed point
struct drm_rect * dest
- integer destination coordinates
const struct drm_rect * clip
- integer clipping coordinates
unsigned int rotation
- plane rotation
int min_scale
- minimum src:dest scaling factor in 16.16 fixed point
int max_scale
- maximum src:dest scaling factor in 16.16 fixed point
bool can_position
- is it legal to position the plane such that it doesn’t cover the entire crtc? This will generally only be false for primary planes.
bool can_update_disabled
- can the plane be updated while the crtc is disabled?
bool * visible
- output parameter indicating whether plane is still visible after clipping
Description
Checks that a desired plane update is valid. Drivers that provide their own plane handling rather than helper-provided implementations may still wish to call this function to avoid duplication of error checking code.
Return
Zero if update appears valid, error code on failure
-
int
drm_primary_helper_update
(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
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 for primary planes. This is handler is called in response to a userspace SetPlane operation on the plane with a non-NULL framebuffer. We call the driver’s modeset handler to update the framebuffer.
SetPlane()
on a primary plane of a disabled CRTC is not supported, and will
return an error.
Note that we make some assumptions about hardware limitations that may not be true for all hardware –
- Primary plane cannot be repositioned.
- Primary plane cannot be scaled.
- Primary plane must cover the entire CRTC.
- Subpixel positioning is not supported.
Drivers for hardware that don’t have these restrictions can provide their own implementation rather than using this helper.
Return
Zero on success, error code on failure
Parameters
struct drm_plane * plane
- plane to disable
Description
Provides a default plane disable handler for primary planes. This is handler is called in response to a userspace SetPlane operation on the plane with a NULL framebuffer parameter. It unconditionally fails the disable call with -EINVAL the only way to disable the primary plane without driver support is to disable the entier CRTC. Which does not match the plane ->disable hook.
Note that some hardware may be able to disable the primary plane without disabling the whole CRTC. Drivers for such hardware should provide their own disable handler that disables just the primary plane (and they’ll likely need to provide their own update handler as well to properly re-enable a disabled primary plane).
Return
Unconditionally returns -EINVAL.
Parameters
struct drm_plane * plane
- plane to destroy
Description
Provides a default plane destroy handler for primary planes. This handler is called during CRTC destruction. We disable the primary plane, remove it from the DRM plane list, and deallocate the plane structure.
-
int
drm_crtc_init
(struct drm_device * dev, struct drm_crtc * crtc, const struct drm_crtc_funcs * funcs)¶ Legacy CRTC initialization function
Parameters
struct drm_device * dev
- DRM device
struct drm_crtc * crtc
- CRTC object to init
const struct drm_crtc_funcs * funcs
- callbacks for the new CRTC
Description
Initialize a CRTC object with a default helper-provided primary plane and no cursor plane.
Return
Zero on success, error code on failure.
-
int
drm_plane_helper_update
(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)¶ Transitional helper for plane update
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 plane update functions. It is fully left to the driver to check plane constraints and handle corner-cases like a fully occluded or otherwise invisible plane.
This is useful for piecewise transitioning of a driver to the atomic helpers.
Return
Zero on success, error code on failure
Parameters
struct drm_plane * plane
- plane to disable
Description
Provides a default plane disable handler using the atomic plane update functions. It is fully left to the driver to check plane constraints and handle corner-cases like a fully occluded or otherwise invisible plane.
This is useful for piecewise transitioning of a driver to the atomic helpers.
Return
Zero on success, error code on failure
This helper library has two parts. The first part has support to implement
primary plane support on top of the normal CRTC configuration interface.
Since the legacy ->set_config interface ties the primary plane together with
the CRTC state this does not allow userspace to disable the primary plane
itself. To avoid too much duplicated code use
drm_plane_helper_check_update()
which can be used to enforce the same
restrictions as primary planes had thus. The default primary plane only
expose XRBG8888 and ARGB8888 as valid pixel formats for the attached
framebuffer.
Drivers are highly recommended to implement proper support for primary planes, and newly merged drivers must not rely upon these transitional helpers.
The second part also implements transitional helpers which allow drivers to gradually switch to the atomic helper infrastructure for plane updates. Once that switch is complete drivers shouldn’t use these any longer, instead using the proper legacy implementations for update and disable plane hooks provided by the atomic helpers.
Again drivers are strongly urged to switch to the new interfaces.
The plane helpers share the function table structures with other helpers,
specifically also the atomic helpers. See struct drm_plane_helper_funcs
for
the details.
Tile group¶
Tile groups are used to represent tiled monitors with a unique integer identifier. Tiled monitors using DisplayID v1.3 have a unique 8-byte handle, we store this in a tile group, so we have a common identifier for all tiles in a monitor group.
Bridges¶
Overview¶
struct drm_bridge
represents a device that hangs on to an encoder. These are
handy when a regular drm_encoder
entity isn’t enough to represent the entire
encoder chain.
A bridge is always attached to a single drm_encoder
at a time, but can be
either connected to it directly, or through an intermediate bridge:
encoder ---> bridge B ---> bridge A
Here, the output of the encoder feeds to bridge B, and that furthers feeds to bridge A.
The driver using the bridge is responsible to make the associations between
the encoder and bridges. Once these links are made, the bridges will
participate along with encoder functions to perform mode_set/enable/disable
through the ops provided in drm_bridge_funcs
.
drm_bridge, like drm_panel, aren’t drm_mode_object entities like planes, CRTCs, encoders or connectors and hence are not visible to userspace. They just provide additional hooks to get the desired output at the end of the encoder chain.
Bridges can also be chained up using the next pointer in struct drm_bridge
.
Both legacy CRTC helpers and the new atomic modeset helpers support bridges.
Default bridge callback sequence¶
The drm_bridge_funcs
ops are populated by the bridge driver. The DRM
internals (atomic and CRTC helpers) use the helpers defined in drm_bridge.c
These helpers call a specific drm_bridge_funcs
op for all the bridges
during encoder configuration.
For detailed specification of the bridge callbacks see drm_bridge_funcs
.
-
int
drm_bridge_add
(struct drm_bridge * bridge)¶ add the given bridge to the global bridge list
Parameters
struct drm_bridge * bridge
- bridge control structure
Return
Unconditionally returns Zero.
-
void
drm_bridge_remove
(struct drm_bridge * bridge)¶ remove the given bridge from the global bridge list
Parameters
struct drm_bridge * bridge
- bridge control structure
-
int
drm_bridge_attach
(struct drm_device * dev, struct drm_bridge * bridge)¶ associate given bridge to our DRM device
Parameters
struct drm_device * dev
- DRM device
struct drm_bridge * bridge
- bridge control structure
Description
called by a kms driver to link one of our encoder/bridge to the given bridge.
Note that setting up links between the bridge and our encoder/bridge objects needs to be handled by the kms driver itself
Return
Zero on success, error code on failure
-
bool
drm_bridge_mode_fixup
(struct drm_bridge * bridge, const struct drm_display_mode * mode, struct drm_display_mode * adjusted_mode)¶ fixup proposed mode for all bridges in the encoder chain
Parameters
struct drm_bridge * bridge
- bridge control structure
const struct drm_display_mode * mode
- desired mode to be set for the bridge
struct drm_display_mode * adjusted_mode
- updated mode that works for this bridge
Description
Calls ->:c:func:mode_fixup() drm_bridge_funcs
op for all the bridges in the
encoder chain, starting from the first bridge to the last.
Note
the bridge passed should be the one closest to the encoder
Return
true on success, false on failure
-
void
drm_bridge_disable
(struct drm_bridge * bridge)¶ calls ->:c:func:disable()
drm_bridge_funcs
op for all bridges in the encoder chain.
Parameters
struct drm_bridge * bridge
- bridge control structure
Description
Calls ->:c:func:disable() drm_bridge_funcs
op for all the bridges in the encoder
chain, starting from the last bridge to the first. These are called before
calling the encoder’s prepare op.
Note
the bridge passed should be the one closest to the encoder
-
void
drm_bridge_post_disable
(struct drm_bridge * bridge)¶ calls ->:c:func:post_disable()
drm_bridge_funcs
op for all bridges in the encoder chain.
Parameters
struct drm_bridge * bridge
- bridge control structure
Description
Calls ->:c:func:post_disable() drm_bridge_funcs
op for all the bridges in the
encoder chain, starting from the first bridge to the last. These are called
after completing the encoder’s prepare op.
Note
the bridge passed should be the one closest to the encoder
-
void
drm_bridge_mode_set
(struct drm_bridge * bridge, struct drm_display_mode * mode, struct drm_display_mode * adjusted_mode)¶ set proposed mode for all bridges in the encoder chain
Parameters
struct drm_bridge * bridge
- bridge control structure
struct drm_display_mode * mode
- desired mode to be set for the bridge
struct drm_display_mode * adjusted_mode
- updated mode that works for this bridge
Description
Calls ->:c:func:mode_set() drm_bridge_funcs
op for all the bridges in the
encoder chain, starting from the first bridge to the last.
Note
the bridge passed should be the one closest to the encoder
-
void
drm_bridge_pre_enable
(struct drm_bridge * bridge)¶ calls ->:c:func:pre_enable()
drm_bridge_funcs
op for all bridges in the encoder chain.
Parameters
struct drm_bridge * bridge
- bridge control structure
Description
Calls ->:c:func:pre_enable() drm_bridge_funcs
op for all the bridges in the encoder
chain, starting from the last bridge to the first. These are called
before calling the encoder’s commit op.
Note
the bridge passed should be the one closest to the encoder
-
void
drm_bridge_enable
(struct drm_bridge * bridge)¶ calls ->:c:func:enable()
drm_bridge_funcs
op for all bridges in the encoder chain.
Parameters
struct drm_bridge * bridge
- bridge control structure
Description
Calls ->:c:func:enable() drm_bridge_funcs
op for all the bridges in the encoder
chain, starting from the first bridge to the last. These are called
after completing the encoder’s commit op.
Note that the bridge passed should be the one closest to the encoder
-
struct drm_bridge *
of_drm_find_bridge
(struct device_node * np)¶ find the bridge corresponding to the device node in the global bridge list
Parameters
struct device_node * np
- device node
Return
drm_bridge control struct on success, NULL on failure
Panel Helper Reference¶
-
struct
drm_panel_funcs
¶ perform operations on a given panel
Definition
struct drm_panel_funcs {
int (* disable) (struct drm_panel *panel);
int (* unprepare) (struct drm_panel *panel);
int (* prepare) (struct drm_panel *panel);
int (* enable) (struct drm_panel *panel);
int (* get_modes) (struct drm_panel *panel);
int (* get_timings) (struct drm_panel *panel, unsigned int num_timings,struct display_timing *timings);
};
Members
int (*)(struct drm_panel *panel) disable
- disable panel (turn off back light, etc.)
int (*)(struct drm_panel *panel) unprepare
- turn off panel
int (*)(struct drm_panel *panel) prepare
- turn on panel and perform set up
int (*)(struct drm_panel *panel) enable
- enable panel (turn on back light, etc.)
int (*)(struct drm_panel *panel) get_modes
- add modes to the connector that the panel is attached to and return the number of modes added
int (*)(struct drm_panel *panel, unsigned int num_timings,struct display_timing *timings) get_timings
- copy display timings into the provided array and return the number of display timings available
Description
The .:c:func:prepare() function is typically called before the display controller starts to transmit video data. Panel drivers can use this to turn the panel on and wait for it to become ready. If additional configuration is required (via a control bus such as I2C, SPI or DSI for example) this is a good time to do that.
After the display controller has started transmitting video data, it’s safe to call the .:c:func:enable() function. This will typically enable the backlight to make the image on screen visible. Some panels require a certain amount of time or frames before the image is displayed. This function is responsible for taking this into account before enabling the backlight to avoid visual glitches.
Before stopping video transmission from the display controller it can be necessary to turn off the panel to avoid visual glitches. This is done in the .:c:func:disable() function. Analogously to .:c:func:enable() this typically involves turning off the backlight and waiting for some time to make sure no image is visible on the panel. It is then safe for the display controller to cease transmission of video data.
To save power when no video data is transmitted, a driver can power down the panel. This is the job of the .:c:func:unprepare() function.
-
struct
drm_panel
¶ DRM panel object
Definition
struct drm_panel {
struct drm_device * drm;
struct drm_connector * connector;
struct device * dev;
const struct drm_panel_funcs * funcs;
struct list_head list;
};
Members
struct drm_device * drm
- DRM device owning the panel
struct drm_connector * connector
- DRM connector that the panel is attached to
struct device * dev
- parent device of the panel
const struct drm_panel_funcs * funcs
- operations that can be performed on the panel
struct list_head list
- panel entry in registry
Parameters
struct drm_panel * panel
- DRM panel
Description
Calling this function will completely power off a panel (assert the panel’s
reset, turn off power supplies, ...). After this function has completed, it
is usually no longer possible to communicate with the panel until another
call to drm_panel_prepare()
.
Return
0 on success or a negative error code on failure.
Parameters
struct drm_panel * panel
- DRM panel
Description
This will typically turn off the panel’s backlight or disable the display drivers. For smart panels it should still be possible to communicate with the integrated circuitry via any command bus after this call.
Return
0 on success or a negative error code on failure.
Parameters
struct drm_panel * panel
- DRM panel
Description
Calling this function will enable power and deassert any reset signals to the panel. After this has completed it is possible to communicate with any integrated circuitry via a command bus.
Return
0 on success or a negative error code on failure.
Parameters
struct drm_panel * panel
- DRM panel
Description
Calling this function will cause the panel display drivers to be turned on and the backlight to be enabled. Content will be visible on screen after this call completes.
Return
0 on success or a negative error code on failure.
Parameters
struct drm_panel * panel
- DRM panel
Description
The modes probed from the panel are automatically added to the connector that the panel is attached to.
Return
The number of modes available from the panel on success or a negative error code on failure.
Parameters
struct drm_panel * panel
- DRM panel
Description
Sets up internal fields of the panel so that it can subsequently be added to the registry.
Parameters
struct drm_panel * panel
- panel to add
Description
Add a panel to the global registry so that it can be looked up by display drivers.
Return
0 on success or a negative error code on failure.
Parameters
struct drm_panel * panel
- DRM panel
Description
Removes a panel from the global registry.
-
int
drm_panel_attach
(struct drm_panel * panel, struct drm_connector * connector)¶ attach a panel to a connector
Parameters
struct drm_panel * panel
- DRM panel
struct drm_connector * connector
- DRM connector
Description
After obtaining a pointer to a DRM panel a display driver calls this function to attach a panel to a connector.
An error is returned if the panel is already attached to another connector.
Return
0 on success or a negative error code on failure.
Parameters
struct drm_panel * panel
- DRM panel
Description
Detaches a panel from the connector it is attached to. If a panel is not attached to any connector this is effectively a no-op.
Return
0 on success or a negative error code on failure.
-
struct drm_panel *
of_drm_find_panel
(struct device_node * np)¶ look up a panel using a device tree node
Parameters
struct device_node * np
- device tree node of the panel
Description
Searches the set of registered panels for one that matches the given device tree node. If a matching panel is found, return a pointer to it.
Return
A pointer to the panel registered for the specified device tree node or NULL if no panel matching the device tree node can be found.
The DRM panel helpers allow drivers to register panel objects with a central registry and provide functions to retrieve those panels in display drivers.
Simple KMS Helper Reference¶
-
struct
drm_simple_display_pipe_funcs
¶ helper operations for a simple display pipeline
Definition
struct drm_simple_display_pipe_funcs {
void (* enable) (struct drm_simple_display_pipe *pipe,struct drm_crtc_state *crtc_state);
void (* disable) (struct drm_simple_display_pipe *pipe);
int (* check) (struct drm_simple_display_pipe *pipe,struct drm_plane_state *plane_state,struct drm_crtc_state *crtc_state);
void (* update) (struct drm_simple_display_pipe *pipe,struct drm_plane_state *plane_state);
};
Members
void (*)(struct drm_simple_display_pipe *pipe,struct drm_crtc_state *crtc_state) enable
- This function should be used to enable the pipeline. It is called when the underlying crtc is enabled. This hook is optional.
void (*)(struct drm_simple_display_pipe *pipe) disable
- This function should be used to disable the pipeline. It is called when the underlying crtc is disabled. This hook is optional.
int (*)(struct drm_simple_display_pipe *pipe,struct drm_plane_state *plane_state,struct drm_crtc_state *crtc_state) check
This function is called in the check phase of an atomic update, specifically when the underlying plane is checked. The simple display pipeline helpers already check that the plane is not scaled, fills the entire visible area and is always enabled when the crtc is also enabled. This hook is optional.
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_simple_display_pipe *pipe,struct drm_plane_state *plane_state) update
- This function is called when the underlying plane state is updated. This hook is optional.
-
struct
drm_simple_display_pipe
¶ simple display pipeline
Definition
struct drm_simple_display_pipe {
struct drm_crtc crtc;
struct drm_plane plane;
struct drm_encoder encoder;
struct drm_connector * connector;
const struct drm_simple_display_pipe_funcs * funcs;
};
Members
struct drm_crtc crtc
- CRTC control structure
struct drm_plane plane
- Plane control structure
struct drm_encoder encoder
- Encoder control structure
struct drm_connector * connector
- Connector control structure
const struct drm_simple_display_pipe_funcs * funcs
- Pipeline control functions (optional)
Description
Simple display pipeline with plane, crtc and encoder collapsed into one
entity. It should be initialized by calling drm_simple_display_pipe_init()
.
-
int
drm_simple_display_pipe_init
(struct drm_device * dev, struct drm_simple_display_pipe * pipe, const struct drm_simple_display_pipe_funcs * funcs, const uint32_t * formats, unsigned int format_count, struct drm_connector * connector)¶ Initialize a simple display pipeline
Parameters
struct drm_device * dev
- DRM device
struct drm_simple_display_pipe * pipe
- simple display pipe object to initialize
const struct drm_simple_display_pipe_funcs * funcs
- callbacks for the display pipe (optional)
const uint32_t * formats
- array of supported formats (``DRM_FORMAT_``*)
unsigned int format_count
- number of elements in formats
struct drm_connector * connector
- connector to attach and register
Description
Sets up a display pipeline which consist of a really simple
plane-crtc-encoder pipe coupled with the provided connector.
Teardown of a simple display pipe is all handled automatically by the drm
core through calling drm_mode_config_cleanup()
. Drivers afterwards need to
release the memory for the structure themselves.
Return
Zero on success, negative error code on failure.
This helper library provides helpers for drivers for simple display hardware.
drm_simple_display_pipe_init()
initializes a simple display pipeline
which has only one full-screen scanout buffer feeding one output. The
pipeline is represented by struct drm_simple_display_pipe
and binds
together drm_plane
, drm_crtc
and drm_encoder
structures into one fixed
entity. Some flexibility for code reuse is provided through a separately
allocated drm_connector
object and supporting optional drm_bridge
encoder drivers.
KMS Properties¶
Drivers may need to expose additional parameters to applications than those described in the previous sections. KMS supports attaching properties to CRTCs, connectors and planes and offers a userspace API to list, get and set the property values.
Properties are identified by a name that uniquely defines the property purpose, and store an associated value. For all property types except blob properties the value is a 64-bit unsigned integer.
KMS differentiates between properties and property instances. Drivers first create properties and then create and associate individual instances of those properties to objects. A property can be instantiated multiple times and associated with different objects. Values are stored in property instances, and all other property information are stored in the property and shared between all instances of the property.
Every property is created with a type that influences how the KMS core handles the property. Supported property types are
- DRM_MODE_PROP_RANGE
- Range properties report their minimum and maximum admissible values. The KMS core verifies that values set by application fit in that range.
- DRM_MODE_PROP_ENUM
- Enumerated properties take a numerical value that ranges from 0 to the number of enumerated values defined by the property minus one, and associate a free-formed string name to each value. Applications can retrieve the list of defined value-name pairs and use the numerical value to get and set property instance values.
- DRM_MODE_PROP_BITMASK
- Bitmask properties are enumeration properties that additionally restrict all enumerated values to the 0..63 range. Bitmask property instance values combine one or more of the enumerated bits defined by the property.
- DRM_MODE_PROP_BLOB
Blob properties store a binary blob without any format restriction. The binary blobs are created as KMS standalone objects, and blob property instance values store the ID of their associated blob object.
Blob properties are only used for the connector EDID property and cannot be created by drivers.
To create a property drivers call one of the following functions depending on the property type. All property creation functions take property flags and name, as well as type-specific arguments.
- struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, const char *name, uint64_t min, uint64_t max); Create a range property with the given minimum and maximum values.
- 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 an enumerated property. The
props
argument points to an array ofnum_values
value-name pairs. - 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_values);
Create a bitmask property. The
props
argument points to an array ofnum_values
value-name pairs.
Properties can additionally be created as immutable, in which case they will be read-only for applications but can be modified by the driver. To create an immutable property drivers must set the DRM_MODE_PROP_IMMUTABLE flag at property creation time.
When no array of value-name pairs is readily available at property
creation time for enumerated or range properties, drivers can create the
property using the drm_property_create()
function and
manually add enumeration value-name pairs by calling the
drm_property_add_enum()
function. Care must be taken to
properly specify the property type through the flags
argument.
After creating properties drivers can attach property instances to CRTC,
connector and plane objects by calling the
drm_object_attach_property()
. The function takes a
pointer to the target object, a pointer to the previously created
property and an initial instance value.
Existing KMS Properties¶
The following table gives description of drm properties exposed by various modules/drivers.
Vertical Blanking¶
Vertical blanking plays a major role in graphics rendering. To achieve tear-free display, users must synchronize page flips and/or rendering to vertical blanking. The DRM API offers ioctls to perform page flips synchronized to vertical blanking and wait for vertical blanking.
The DRM core handles most of the vertical blanking management logic, which involves filtering out spurious interrupts, keeping race-free blanking counters, coping with counter wrap-around and resets and keeping use counts. It relies on the driver to generate vertical blanking interrupts and optionally provide a hardware vertical blanking counter. Drivers must implement the following operations.
- int (*enable_vblank) (struct drm_device *dev, int crtc); void (*disable_vblank) (struct drm_device *dev, int crtc); Enable or disable vertical blanking interrupts for the given CRTC.
- u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);
Retrieve the value of the vertical blanking counter for the given
CRTC. If the hardware maintains a vertical blanking counter its value
should be returned. Otherwise drivers can use the
drm_vblank_count()
helper function to handle this operation.
Drivers must initialize the vertical blanking handling core with a call
to drm_vblank_init()
in their load operation.
Vertical blanking interrupts can be enabled by the DRM core or by
drivers themselves (for instance to handle page flipping operations).
The DRM core maintains a vertical blanking use count to ensure that the
interrupts are not disabled while a user still needs them. To increment
the use count, drivers call drm_vblank_get()
. Upon
return vertical blanking interrupts are guaranteed to be enabled.
To decrement the use count drivers call
drm_vblank_put()
. Only when the use count drops to zero
will the DRM core disable the vertical blanking interrupts after a delay
by scheduling a timer. The delay is accessible through the
vblankoffdelay module parameter or the drm_vblank_offdelay
global
variable and expressed in milliseconds. Its default value is 5000 ms.
Zero means never disable, and a negative value means disable
immediately. Drivers may override the behaviour by setting the
struct drm_device
vblank_disable_immediate flag, which when set causes vblank interrupts
to be disabled immediately regardless of the drm_vblank_offdelay
value. The flag should only be set if there’s a properly working
hardware vblank counter present.
When a vertical blanking interrupt occurs drivers only need to call the
drm_handle_vblank()
function to account for the
interrupt.
Resources allocated by drm_vblank_init()
must be freed
with a call to drm_vblank_cleanup()
in the driver unload
operation handler.
Vertical Blanking and Interrupt Handling Functions Reference¶
Parameters
struct drm_crtc * crtc
- which counter to retrieve
Description
This function is similar to drm_crtc_vblank_count but this function interpolates to handle a race with vblank irq’s.
This is mostly useful for hardware that can obtain the scanout position, but doesn’t have a frame counter.
-
void
drm_vblank_cleanup
(struct drm_device * dev)¶ cleanup vblank support
Parameters
struct drm_device * dev
- DRM device
Description
This function cleans up any resources allocated in drm_vblank_init.
-
int
drm_vblank_init
(struct drm_device * dev, unsigned int num_crtcs)¶ initialize vblank support
Parameters
struct drm_device * dev
- DRM device
unsigned int num_crtcs
- number of CRTCs supported by dev
Description
This function initializes vblank support for num_crtcs display pipelines.
Return
Zero on success or a negative error code on failure.
-
int
drm_irq_install
(struct drm_device * dev, int irq)¶ install IRQ handler
Parameters
struct drm_device * dev
- DRM device
int irq
- IRQ number to install the handler for
Description
Initializes the IRQ related data. Installs the handler, calling the driver
irq_preinstall()
and irq_postinstall()
functions before and after the
installation.
This is the simplified helper interface provided for drivers with no special needs. Drivers which need to install interrupt handlers for multiple interrupts must instead set drm_device->irq_enabled to signal the DRM core that vblank interrupts are available.
Return
Zero on success or a negative error code on failure.
-
int
drm_irq_uninstall
(struct drm_device * dev)¶ uninstall the IRQ handler
Parameters
struct drm_device * dev
- DRM device
Description
Calls the driver’s irq_uninstall()
function and unregisters the IRQ handler.
This should only be called by drivers which used drm_irq_install()
to set up
their interrupt handler. Other drivers must only reset
drm_device->irq_enabled to false.
Note that for kernel modesetting drivers it is a bug if this function fails. The sanity checks are only to catch buggy user modesetting drivers which call the same function through an ioctl.
Return
Zero on success or a negative error code on failure.
-
void
drm_calc_timestamping_constants
(struct drm_crtc * crtc, const struct drm_display_mode * mode)¶ calculate vblank timestamp constants
Parameters
struct drm_crtc * crtc
- drm_crtc whose timestamp constants should be updated.
const struct drm_display_mode * mode
- display mode containing the scanout timings
Description
Calculate and store various constants which are later
needed by vblank and swap-completion timestamping, e.g,
by drm_calc_vbltimestamp_from_scanoutpos()
. They are
derived from CRTC’s true scanout timing, so they take
things like panel scaling or other adjustments into account.
-
int
drm_calc_vbltimestamp_from_scanoutpos
(struct drm_device * dev, unsigned int pipe, int * max_error, struct timeval * vblank_time, unsigned flags, const struct drm_display_mode * mode)¶ precise vblank timestamp helper
Parameters
struct drm_device * dev
- DRM device
unsigned int pipe
- index of CRTC whose vblank timestamp to retrieve
int * max_error
- Desired maximum allowable error in timestamps (nanosecs) On return contains true maximum error of timestamp
struct timeval * vblank_time
- Pointer to struct timeval which should receive the timestamp
unsigned flags
- Flags to pass to driver: 0 = Default, DRM_CALLED_FROM_VBLIRQ = If function is called from vbl IRQ handler
const struct drm_display_mode * mode
- mode which defines the scanout timings
Description
Implements calculation of exact vblank timestamps from given drm_display_mode
timings and current video scanout position of a CRTC. This can be called from
within get_vblank_timestamp()
implementation of a kms driver to implement the
actual timestamping.
Should return timestamps conforming to the OML_sync_control OpenML extension specification. The timestamp corresponds to the end of the vblank interval, aka start of scanout of topmost-leftmost display pixel in the following video frame.
Requires support for optional dev->driver->:c:func:get_scanout_position() in kms driver, plus a bit of setup code to provide a drm_display_mode that corresponds to the true scanout timing.
The current implementation only handles standard video modes. It returns as no operation if a doublescan or interlaced video mode is active. Higher level code is expected to handle this.
Return
Negative value on error, failure or if not supported in current video mode:
-EINVAL |
|
-EAGAIN |
|
-ENOTSUPP - Function not supported in current display mode. -EIO - Failed, e.g., due to failed scanout position query.
Returns or’ed positive status flags on success:
DRM_VBLANKTIME_SCANOUTPOS_METHOD - Signal this method used for timestamping. DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval.
-
u32
drm_vblank_count
(struct drm_device * dev, unsigned int pipe)¶ retrieve “cooked” vblank counter value
Parameters
struct drm_device * dev
- DRM device
unsigned int pipe
- index of CRTC for which to retrieve the counter
Description
Fetches the “cooked” vblank count value that represents the number of vblank events since the system was booted, including lost events due to modesetting activity.
This is the legacy version of drm_crtc_vblank_count()
.
Return
The software vblank counter.
Parameters
struct drm_crtc * crtc
- which counter to retrieve
Description
Fetches the “cooked” vblank count value that represents the number of vblank events since the system was booted, including lost events due to modesetting activity.
This is the native KMS version of drm_vblank_count()
.
Return
The software vblank counter.
-
u32
drm_vblank_count_and_time
(struct drm_device * dev, unsigned int pipe, struct timeval * vblanktime)¶ retrieve “cooked” vblank counter value and the system timestamp corresponding to that vblank counter value.
Parameters
struct drm_device * dev
- DRM device
unsigned int pipe
- index of CRTC whose counter to retrieve
struct timeval * vblanktime
- Pointer to struct timeval to receive the vblank timestamp.
Description
Fetches the “cooked” vblank count value that represents the number of vblank events since the system was booted, including lost events due to modesetting activity. Returns corresponding system timestamp of the time of the vblank interval that corresponds to the current vblank counter value.
This is the legacy version of drm_crtc_vblank_count_and_time()
.
-
u32
drm_crtc_vblank_count_and_time
(struct drm_crtc * crtc, struct timeval * vblanktime)¶ retrieve “cooked” vblank counter value and the system timestamp corresponding to that vblank counter value
Parameters
struct drm_crtc * crtc
- which counter to retrieve
struct timeval * vblanktime
- Pointer to struct timeval to receive the vblank timestamp.
Description
Fetches the “cooked” vblank count value that represents the number of vblank events since the system was booted, including lost events due to modesetting activity. Returns corresponding system timestamp of the time of the vblank interval that corresponds to the current vblank counter value.
This is the native KMS version of drm_vblank_count_and_time()
.
-
void
drm_crtc_arm_vblank_event
(struct drm_crtc * crtc, struct drm_pending_vblank_event * e)¶ arm vblank event after pageflip
Parameters
struct drm_crtc * crtc
- the source CRTC of the vblank event
struct drm_pending_vblank_event * e
- the event to send
Description
A lot of drivers need to generate vblank events for the very next vblank interrupt. For example when the page flip interrupt happens when the page flip gets armed, but not when it actually executes within the next vblank period. This helper function implements exactly the required vblank arming behaviour.
Caller must hold event lock. Caller must also hold a vblank reference for the event e, which will be dropped when the next vblank arrives.
-
void
drm_crtc_send_vblank_event
(struct drm_crtc * crtc, struct drm_pending_vblank_event * e)¶ helper to send vblank event after pageflip
Parameters
struct drm_crtc * crtc
- the source CRTC of the vblank event
struct drm_pending_vblank_event * e
- the event to send
Description
Updates sequence # and timestamp on event, and sends it to userspace. Caller must hold event lock.
Parameters
struct drm_crtc * crtc
- which CRTC to own
Description
Acquire a reference count on vblank events to avoid having them disabled while in use.
Return
Zero on success or a negative error code on failure.
Parameters
struct drm_crtc * crtc
- which counter to give up
Description
Release ownership of a given vblank counter, turning off interrupts if possible. Disable interrupts after drm_vblank_offdelay milliseconds.
-
void
drm_wait_one_vblank
(struct drm_device * dev, unsigned int pipe)¶ wait for one vblank
Parameters
struct drm_device * dev
- DRM device
unsigned int pipe
- CRTC index
Description
This waits for one vblank to pass on pipe, using the irq driver interfaces. It is a failure to call this when the vblank irq for pipe is disabled, e.g. due to lack of driver support or because the crtc is off.
Parameters
struct drm_crtc * crtc
- DRM crtc
Description
This waits for one vblank to pass on crtc, using the irq driver interfaces. It is a failure to call this when the vblank irq for crtc is disabled, e.g. due to lack of driver support or because the crtc is off.
-
void
drm_vblank_off
(struct drm_device * dev, unsigned int pipe)¶ disable vblank events on a CRTC
Parameters
struct drm_device * dev
- DRM device
unsigned int pipe
- CRTC index
Description
Drivers can use this function to shut down the vblank interrupt handling when
disabling a crtc. This function ensures that the latest vblank frame count is
stored so that drm_vblank_on()
can restore it again.
Drivers must use this function when the hardware vblank counter can get reset, e.g. when suspending.
This is the legacy version of drm_crtc_vblank_off()
.
Parameters
struct drm_crtc * crtc
- CRTC in question
Description
Drivers can use this function to shut down the vblank interrupt handling when disabling a crtc. This function ensures that the latest vblank frame count is stored so that drm_vblank_on can restore it again.
Drivers must use this function when the hardware vblank counter can get reset, e.g. when suspending.
This is the native kms version of drm_vblank_off()
.
Parameters
struct drm_crtc * crtc
- CRTC in question
Description
Drivers can use this function to reset the vblank state to off at load time.
Drivers should use this together with the drm_crtc_vblank_off()
and
drm_crtc_vblank_on()
functions. The difference compared to
drm_crtc_vblank_off()
is that this function doesn’t save the vblank counter
and hence doesn’t need to call any driver hooks.
-
void
drm_vblank_on
(struct drm_device * dev, unsigned int pipe)¶ enable vblank events on a CRTC
Parameters
struct drm_device * dev
- DRM device
unsigned int pipe
- CRTC index
Description
This functions restores the vblank interrupt state captured with
drm_vblank_off()
again. Note that calls to drm_vblank_on()
and
drm_vblank_off()
can be unbalanced and so can also be unconditionally called
in driver load code to reflect the current hardware state of the crtc.
This is the legacy version of drm_crtc_vblank_on()
.
Parameters
struct drm_crtc * crtc
- CRTC in question
Description
This functions restores the vblank interrupt state captured with
drm_vblank_off()
again. Note that calls to drm_vblank_on()
and
drm_vblank_off()
can be unbalanced and so can also be unconditionally called
in driver load code to reflect the current hardware state of the crtc.
This is the native kms version of drm_vblank_on()
.
-
void
drm_vblank_pre_modeset
(struct drm_device * dev, unsigned int pipe)¶ account for vblanks across mode sets
Parameters
struct drm_device * dev
- DRM device
unsigned int pipe
- CRTC index
Description
Account for vblank events across mode setting events, which will likely reset the hardware frame counter.
This is done by grabbing a temporary vblank reference to ensure that the vblank interrupt keeps running across the modeset sequence. With this the software-side vblank frame counting will ensure that there are no jumps or discontinuities.
Unfortunately this approach is racy and also doesn’t work when the vblank
interrupt stops running, e.g. across system suspend resume. It is therefore
highly recommended that drivers use the newer drm_vblank_off()
and
drm_vblank_on()
instead. drm_vblank_pre_modeset()
only works correctly when
using “cooked” software vblank frame counters and not relying on any hardware
counters.
Drivers must call drm_vblank_post_modeset()
when re-enabling the same crtc
again.
-
void
drm_vblank_post_modeset
(struct drm_device * dev, unsigned int pipe)¶ undo drm_vblank_pre_modeset changes
Parameters
struct drm_device * dev
- DRM device
unsigned int pipe
- CRTC index
Description
This function again drops the temporary vblank reference acquired in drm_vblank_pre_modeset.
-
bool
drm_handle_vblank
(struct drm_device * dev, unsigned int pipe)¶ handle a vblank event
Parameters
struct drm_device * dev
- DRM device
unsigned int pipe
- index of CRTC where this event occurred
Description
Drivers should call this routine in their vblank interrupt handlers to update the vblank counter and send any signals that may be pending.
This is the legacy version of drm_crtc_handle_vblank()
.
Parameters
struct drm_crtc * crtc
- where this event occurred
Description
Drivers should call this routine in their vblank interrupt handlers to update the vblank counter and send any signals that may be pending.
This is the native KMS version of drm_handle_vblank()
.
Return
True if the event was successfully handled, false on failure.
-
u32
drm_vblank_no_hw_counter
(struct drm_device * dev, unsigned int pipe)¶ “No hw counter” implementation of .:c:func:get_vblank_counter()
Parameters
struct drm_device * dev
- DRM device
unsigned int pipe
- CRTC for which to read the counter
Description
Drivers can plug this into the .:c:func:get_vblank_counter() function if there is no useable hardware frame counter available.
Return
0
-
wait_queue_head_t *
drm_crtc_vblank_waitqueue
(struct drm_crtc * crtc)¶ get vblank waitqueue for the CRTC
Parameters
struct drm_crtc * crtc
- which CRTC’s vblank waitqueue to retrieve
Description
This function returns a pointer to the vblank waitqueue for the CRTC.
Drivers can use this to implement vblank waits using wait_event()
& co.
Open/Close, File Operations and IOCTLs¶
Open and Close¶
int (*firstopen) (struct drm_device *); void (*lastclose) (struct drm_device *); int (*open) (struct drm_device *, struct drm_file *); void (*preclose) (struct drm_device *, struct drm_file *); void (*postclose) (struct drm_device *, struct drm_file *);
Open and close handlers. None of those methods are mandatory.
The firstopen method is called by the DRM core for legacy UMS (User Mode Setting) drivers only when an application opens a device that has no other opened file handle. UMS drivers can implement it to acquire device resources. KMS drivers can’t use the method and must acquire resources in the load method instead.
Similarly the lastclose method is called when the last application holding a file handle opened on the device closes it, for both UMS and KMS drivers. Additionally, the method is also called at module unload time or, for hot-pluggable devices, when the device is unplugged. The firstopen and lastclose calls can thus be unbalanced.
The open method is called every time the device is opened by an
application. Drivers can allocate per-file private data in this method
and store them in the struct struct drm_file
driver_priv field. Note that the open method is
called before firstopen.
The close operation is split into preclose and postclose methods. Drivers must stop and cleanup all per-file operations in the preclose method. For instance pending vertical blanking and page flip events must be cancelled. No per-file operation is allowed on the file handle after returning from the preclose method.
Finally the postclose method is called as the last step of the close operation, right before calling the lastclose method if no other open file handle exists for the device. Drivers that have allocated per-file private data in the open method should free it here.
The lastclose method should restore CRTC and plane properties to default value, so that a subsequent open of the device will not inherit state from the previous user. It can also be used to execute delayed power switching state changes, e.g. in conjunction with the vga_switcheroo infrastructure (see ?). Beyond that KMS drivers should not do any further cleanup. Only legacy UMS drivers might need to clean up device state so that the vga console or an independent fbdev driver could take over.
File Operations¶
Drivers must define the file operations structure that forms the DRM
userspace API entry point, even though most of those operations are
implemented in the DRM core. The mandatory functions are drm_open()
,
drm_read()
, drm_ioctl()
and drm_compat_ioctl if CONFIG_COMPAT is enabled.
Drivers which implement private ioctls that require 32/64 bit compatibility
support must provided their onw .:c:func:compat_ioctl() handler that processes
private ioctls and calls drm_compat_ioctl()
for core ioctls.
In addition drm_read()
and drm_poll()
provide support for DRM events. DRM
events are a generic and extensible means to send asynchronous events to
userspace through the file descriptor. They are used to send vblank event and
page flip completions by the KMS API. But drivers can also use it for their
own needs, e.g. to signal completion of rendering.
The memory mapping implementation will vary depending on how the driver
manages memory. Legacy drivers will use the deprecated drm_legacy_mmap()
function, modern drivers should use one of the provided memory-manager
specific implementations. For GEM-based drivers this is drm_gem_mmap()
.
No other file operations are supported by the DRM userspace API. Overall the following is an example #file_operations structure:
static const example_drm_fops = {
.owner = THIS_MODULE,
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
.mmap = drm_gem_mmap,
};
-
int
drm_open
(struct inode * inode, struct file * filp)¶ open method for DRM file
Parameters
struct inode * inode
- device inode
struct file * filp
- file pointer.
Description
This function must be used by drivers as their .:c:func:open() #file_operations method. It looks up the correct DRM device and instantiates all the per-file resources for it.
Return
0 on success or negative errno value on falure.
-
int
drm_release
(struct inode * inode, struct file * filp)¶ release method for DRM file
Parameters
struct inode * inode
- device inode
struct file * filp
- file pointer.
Description
This function must be used by drivers as their .:c:func:release() #file_operations
method. It frees any resources associated with the open file, and if this is
the last open file for the DRM device also proceeds to call drm_lastclose()
.
Return
Always succeeds and returns 0.
-
ssize_t
drm_read
(struct file * filp, char __user * buffer, size_t count, loff_t * offset)¶ read method for DRM file
Parameters
struct file * filp
- file pointer
char __user * buffer
- userspace destination pointer for the read
size_t count
- count in bytes to read
loff_t * offset
- offset to read
Description
This function must be used by drivers as their .:c:func:read() #file_operations method iff they use DRM events for asynchronous signalling to userspace. Since events are used by the KMS API for vblank and page flip completion this means all modern display drivers must use it.
offset is ignore, DRM events are read like a pipe. Therefore drivers also
must set the .:c:func:llseek() #file_operation to no_llseek()
. Polling support is
provided by drm_poll()
.
This function will only ever read a full event. Therefore userspace must supply a big enough buffer to fit any event to ensure forward progress. Since the maximum event space is currently 4K it’s recommended to just use that for safety.
Return
Number of bytes read (always aligned to full events, and can be 0) or a negative error code on failure.
-
unsigned int
drm_poll
(struct file * filp, struct poll_table_struct * wait)¶ poll method for DRM file
Parameters
struct file * filp
- file pointer
struct poll_table_struct * wait
- poll waiter table
Description
This function must be used by drivers as their .:c:func:read() #file_operations method iff they use DRM events for asynchronous signalling to userspace. Since events are used by the KMS API for vblank and page flip completion this means all modern display drivers must use it.
See also drm_read()
.
Return
Mask of POLL flags indicating the current status of the file.
-
int
drm_event_reserve_init_locked
(struct drm_device * dev, struct drm_file * file_priv, struct drm_pending_event * p, struct drm_event * e)¶ init a DRM event and reserve space for it
Parameters
struct drm_device * dev
- DRM device
struct drm_file * file_priv
- DRM file private data
struct drm_pending_event * p
- tracking structure for the pending event
struct drm_event * e
- actual event data to deliver to userspace
Description
This function prepares the passed in event for eventual delivery. If the event
doesn’t get delivered (because the IOCTL fails later on, before queuing up
anything) then the even must be cancelled and freed using
drm_event_cancel_free()
. Successfully initialized events should be sent out
using drm_send_event()
or drm_send_event_locked()
to signal completion of the
asynchronous event to userspace.
If callers embedded p into a larger structure it must be allocated with kmalloc and p must be the first member element.
This is the locked version of drm_event_reserve_init()
for callers which
already hold dev->event_lock.
Return
0 on success or a negative error code on failure.
-
int
drm_event_reserve_init
(struct drm_device * dev, struct drm_file * file_priv, struct drm_pending_event * p, struct drm_event * e)¶ init a DRM event and reserve space for it
Parameters
struct drm_device * dev
- DRM device
struct drm_file * file_priv
- DRM file private data
struct drm_pending_event * p
- tracking structure for the pending event
struct drm_event * e
- actual event data to deliver to userspace
Description
This function prepares the passed in event for eventual delivery. If the event
doesn’t get delivered (because the IOCTL fails later on, before queuing up
anything) then the even must be cancelled and freed using
drm_event_cancel_free()
. Successfully initialized events should be sent out
using drm_send_event()
or drm_send_event_locked()
to signal completion of the
asynchronous event to userspace.
If callers embedded p into a larger structure it must be allocated with kmalloc and p must be the first member element.
Callers which already hold dev->event_lock should use
drm_event_reserve_init()
instead.
Return
0 on success or a negative error code on failure.
-
void
drm_event_cancel_free
(struct drm_device * dev, struct drm_pending_event * p)¶ free a DRM event and release it’s space
Parameters
struct drm_device * dev
- DRM device
struct drm_pending_event * p
- tracking structure for the pending event
Description
This function frees the event p initialized with drm_event_reserve_init()
and releases any allocated space.
-
void
drm_send_event_locked
(struct drm_device * dev, struct drm_pending_event * e)¶ send DRM event to file descriptor
Parameters
struct drm_device * dev
- DRM device
struct drm_pending_event * e
- DRM event to deliver
Description
This function sends the event e, initialized with drm_event_reserve_init()
,
to its associated userspace DRM file. Callers must already hold
dev->event_lock, see drm_send_event()
for the unlocked version.
Note that the core will take care of unlinking and disarming events when the corresponding DRM file is closed. Drivers need not worry about whether the DRM file for this event still exists and can call this function upon completion of the asynchronous work unconditionally.
-
void
drm_send_event
(struct drm_device * dev, struct drm_pending_event * e)¶ send DRM event to file descriptor
Parameters
struct drm_device * dev
- DRM device
struct drm_pending_event * e
- DRM event to deliver
Description
This function sends the event e, initialized with drm_event_reserve_init()
,
to its associated userspace DRM file. This function acquires dev->event_lock,
see drm_send_event_locked()
for callers which already hold this lock.
Note that the core will take care of unlinking and disarming events when the corresponding DRM file is closed. Drivers need not worry about whether the DRM file for this event still exists and can call this function upon completion of the asynchronous work unconditionally.
IOCTLs¶
- struct drm_ioctl_desc *ioctls; int num_ioctls;
- Driver-specific ioctls descriptors table.
Driver-specific ioctls numbers start at DRM_COMMAND_BASE. The ioctls descriptors table is indexed by the ioctl number offset from the base value. Drivers can use the DRM_IOCTL_DEF_DRV() macro to initialize the table entries.
DRM_IOCTL_DEF_DRV(ioctl, func, flags)
ioctl
is the ioctl name. Drivers must define the DRM_##ioctl and
DRM_IOCTL_##ioctl macros to the ioctl number offset from
DRM_COMMAND_BASE and the ioctl number respectively. The first macro is
private to the device while the second must be exposed to userspace in a
public header.
func
is a pointer to the ioctl handler function compatible with the
drm_ioctl_t
type.
typedef int drm_ioctl_t(struct drm_device *dev, void *data,
struct drm_file *file_priv);
flags
is a bitmask combination of the following values. It restricts
how the ioctl is allowed to be called.
- DRM_AUTH - Only authenticated callers allowed
- DRM_MASTER - The ioctl can only be called on the master file handle
- DRM_ROOT_ONLY - Only callers with the SYSADMIN capability allowed
- DRM_CONTROL_ALLOW - The ioctl can only be called on a control device
- DRM_UNLOCKED - The ioctl handler will be called without locking the DRM global mutex. This is the enforced default for kms drivers (i.e. using the DRIVER_MODESET flag) and hence shouldn’t be used any more for new drivers.
-
int
drm_noop
(struct drm_device * dev, void * data, struct drm_file * file_priv)¶ DRM no-op ioctl implemntation
Parameters
struct drm_device * dev
- DRM device for the ioctl
void * data
- data pointer for the ioctl
struct drm_file * file_priv
- DRM file for the ioctl call
Description
This no-op implementation for drm ioctls is useful for deprecated functionality where we can’t return a failure code because existing userspace checks the result of the ioctl, but doesn’t care about the action.
Always returns successfully with 0.
-
int
drm_invalid_op
(struct drm_device * dev, void * data, struct drm_file * file_priv)¶ DRM invalid ioctl implemntation
Parameters
struct drm_device * dev
- DRM device for the ioctl
void * data
- data pointer for the ioctl
struct drm_file * file_priv
- DRM file for the ioctl call
Description
This no-op implementation for drm ioctls is useful for deprecated functionality where we really don’t want to allow userspace to call the ioctl any more. This is the case for old ums interfaces for drivers that transitioned to kms gradually and so kept the old legacy tables around. This only applies to radeon and i915 kms drivers, other drivers shouldn’t need to use this function.
Always fails with a return value of -EINVAL.
-
long
drm_ioctl
(struct file * filp, unsigned int cmd, unsigned long arg)¶ ioctl callback implementation for DRM drivers
Parameters
struct file * filp
- file this ioctl is called on
unsigned int cmd
- ioctl cmd number
unsigned long arg
- user argument
Description
Looks up the ioctl function in the ::ioctls table, checking for root previleges if so required, and dispatches to the respective function.
Return
Zero on success, negative error code on failure.
-
bool
drm_ioctl_flags
(unsigned int nr, unsigned int * flags)¶ Check for core ioctl and return ioctl permission flags
Parameters
unsigned int nr
- ioctl number
unsigned int * flags
- where to return the ioctl permission flags
Description
This ioctl is only used by the vmwgfx driver to augment the access checks done by the drm core and insofar a pretty decent layering violation. This shouldn’t be used by any drivers.
Return
True if the nr corresponds to a DRM core ioctl numer, false otherwise.
Legacy Support Code¶
The section very briefly covers some of the old legacy support code which is only used by old DRM drivers which have done a so-called shadow-attach to the underlying device instead of registering as a real driver. This also includes some of the old generic buffer management and command submission code. Do not use any of this in new and modern drivers.
Legacy Suspend/Resume¶
The DRM core provides some suspend/resume code, but drivers wanting full suspend/resume support should provide save() and restore() functions. These are called at suspend, hibernate, or resume time, and should perform any state save or restore required by your device across suspend or hibernate states.
int (*suspend) (struct drm_device *, pm_message_t state); int
(*resume) (struct drm_device *);
Those are legacy suspend and resume methods which only work with the
legacy shadow-attach driver registration functions. New driver should
use the power management interface provided by their bus type (usually
through the struct device_driver
dev_pm_ops) and set these methods to NULL.
Legacy DMA Services¶
This should cover how DMA mapping etc. is supported by the core. These functions are deprecated and should not be used.
Userland interfaces¶
The DRM core exports several interfaces to applications, generally intended to be used through corresponding libdrm wrapper functions. In addition, drivers export device-specific interfaces for use by userspace drivers & device-aware applications through ioctls and sysfs files.
External interfaces include: memory mapping, context management, DMA operations, AGP management, vblank control, fence management, memory management, and output management.
Cover generic ioctls and sysfs layout here. We only need high-level info, since man pages should cover the rest.
Render nodes¶
DRM core provides multiple character-devices for user-space to use. Depending on which device is opened, user-space can perform a different set of operations (mainly ioctls). The primary node is always created and called card<num>. Additionally, a currently unused control node, called controlD<num> is also created. The primary node provides all legacy operations and historically was the only interface used by userspace. With KMS, the control node was introduced. However, the planned KMS control interface has never been written and so the control node stays unused to date.
With the increased use of offscreen renderers and GPGPU applications, clients no longer require running compositors or graphics servers to make use of a GPU. But the DRM API required unprivileged clients to authenticate to a DRM-Master prior to getting GPU access. To avoid this step and to grant clients GPU access without authenticating, render nodes were introduced. Render nodes solely serve render clients, that is, no modesetting or privileged ioctls can be issued on render nodes. Only non-global rendering commands are allowed. If a driver supports render nodes, it must advertise it via the DRIVER_RENDER DRM driver capability. If not supported, the primary node must be used for render clients together with the legacy drmAuth authentication procedure.
If a driver advertises render node support, DRM core will create a separate render node called renderD<num>. There will be one render node per device. No ioctls except PRIME-related ioctls will be allowed on this node. Especially GEM_OPEN will be explicitly prohibited. Render nodes are designed to avoid the buffer-leaks, which occur if clients guess the flink names or mmap offsets on the legacy interface. Additionally to this basic interface, drivers must mark their driver-dependent render-only ioctls as DRM_RENDER_ALLOW so render clients can use them. Driver authors must be careful not to allow any privileged ioctls on render nodes.
With render nodes, user-space can now control access to the render node via basic file-system access-modes. A running graphics server which authenticates clients on the privileged primary/legacy node is no longer required. Instead, a client can open the render node and is immediately granted GPU access. Communication between clients (or servers) is done via PRIME. FLINK from render node to legacy node is not supported. New clients must not use the insecure FLINK interface.
Besides dropping all modeset/global ioctls, render nodes also drop the DRM-Master concept. There is no reason to associate render clients with a DRM-Master as they are independent of any graphics server. Besides, they must work without any running master, anyway. Drivers must be able to run without a master object if they support render nodes. If, on the other hand, a driver requires shared state between clients which is visible to user-space and accessible beyond open-file boundaries, they cannot support render nodes.
VBlank event handling¶
The DRM core exposes two vertical blank related ioctls:
- DRM_IOCTL_WAIT_VBLANK
- This takes a struct drm_wait_vblank structure as its argument, and it is used to block or request a signal when a specified vblank event occurs.
- DRM_IOCTL_MODESET_CTL
- This was only used for user-mode-settind drivers around modesetting changes to allow the kernel to update the vblank interrupt after mode setting, since on many devices the vertical blank counter is reset to 0 at some point during modeset. Modern drivers should not call this any more since with kernel mode setting it is a no-op.
This second part of the GPU Driver Developer’s Guide documents driver code, implementation details and also all the driver-specific userspace interfaces. Especially since all hardware-acceleration interfaces to userspace are driver specific for efficiency and other reasons these interfaces can be rather substantial. Hence every driver has its own chapter.
drm/i915 Intel GFX Driver¶
The drm/i915 driver supports all (with the exception of some very early models) integrated GFX chipsets with both Intel display and rendering blocks. This excludes a set of SoC platforms with an SGX rendering unit, those have basic support through the gma500 drm driver.
Core Driver Infrastructure¶
This section covers core driver infrastructure used by both the display and the GEM parts of the driver.
Runtime Power Management¶
The i915 driver supports dynamic enabling and disabling of entire hardware blocks at runtime. This is especially important on the display side where software is supposed to control many power gates manually on recent hardware, since on the GT side a lot of the power management is done by the hardware. But even there some manual control at the device level is required.
Since i915 supports a diverse set of platforms with a unified codebase and hardware engineers just love to shuffle functionality around between power domains there’s a sizeable amount of indirection required. This file provides generic functions to the driver for grabbing and releasing references for abstract power domains. It then maps those to the actual power wells present for a given platform.
-
bool
__intel_display_power_is_enabled
(struct drm_i915_private * dev_priv, enum intel_display_power_domain domain)¶ unlocked check for a power domain
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum intel_display_power_domain domain
- power domain to check
Description
This is the unlocked version of intel_display_power_is_enabled()
and should
only be used from error capture and recovery code where deadlocks are
possible.
Return
True when the power domain is enabled, false otherwise.
-
bool
intel_display_power_is_enabled
(struct drm_i915_private * dev_priv, enum intel_display_power_domain domain)¶ check for a power domain
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum intel_display_power_domain domain
- power domain to check
Description
This function can be used to check the hw power domain state. It is mostly used in hardware state readout functions. Everywhere else code should rely upon explicit power domain reference counting to ensure that the hardware block is powered up before accessing it.
Callers must hold the relevant modesetting locks to ensure that concurrent threads can’t disable the power well while the caller tries to read a few registers.
Return
True when the power domain is enabled, false otherwise.
-
void
intel_display_set_init_power
(struct drm_i915_private * dev_priv, bool enable)¶ set the initial power domain state
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
bool enable
- whether to enable or disable the initial power domain state
Description
For simplicity our driver load/unload and system suspend/resume code assumes that all power domains are always enabled. This functions controls the state of this little hack. While the initial power domain state is enabled runtime pm is effectively disabled.
-
void
intel_display_power_get
(struct drm_i915_private * dev_priv, enum intel_display_power_domain domain)¶ grab a power domain reference
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum intel_display_power_domain domain
- power domain to reference
Description
This function grabs a power domain reference for domain and ensures that the power domain and all its parents are powered up. Therefore users should only grab a reference to the innermost power domain they need.
Any power domain reference obtained by this function must have a symmetric
call to intel_display_power_put()
to release the reference again.
-
bool
intel_display_power_get_if_enabled
(struct drm_i915_private * dev_priv, enum intel_display_power_domain domain)¶ grab a reference for an enabled display power domain
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum intel_display_power_domain domain
- power domain to reference
Description
This function grabs a power domain reference for domain and ensures that the power domain and all its parents are powered up. Therefore users should only grab a reference to the innermost power domain they need.
Any power domain reference obtained by this function must have a symmetric
call to intel_display_power_put()
to release the reference again.
-
void
intel_display_power_put
(struct drm_i915_private * dev_priv, enum intel_display_power_domain domain)¶ release a power domain reference
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum intel_display_power_domain domain
- power domain to reference
Description
This function drops the power domain reference obtained by
intel_display_power_get()
and might power down the corresponding hardware
block right away if this is the last reference.
-
int
intel_power_domains_init
(struct drm_i915_private * dev_priv)¶ initializes the power domain structures
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
Initializes the power domain structures for dev_priv depending upon the supported platform.
-
void
intel_power_domains_fini
(struct drm_i915_private * dev_priv)¶ finalizes the power domain structures
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
Finalizes the power domain structures for dev_priv depending upon the supported platform. This function also disables runtime pm and ensures that the device stays powered up so that the driver can be reloaded.
-
void
intel_power_domains_init_hw
(struct drm_i915_private * dev_priv, bool resume)¶ initialize hardware power domain state
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
bool resume
- Called from resume code paths or not
Description
This function initializes the hardware power domain state and enables all
power domains using intel_display_set_init_power()
.
-
void
intel_power_domains_suspend
(struct drm_i915_private * dev_priv)¶ suspend power domain state
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This function prepares the hardware power domain state before entering
system suspend. It must be paired with intel_power_domains_init_hw()
.
-
void
intel_runtime_pm_get
(struct drm_i915_private * dev_priv)¶ grab a runtime pm reference
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This function grabs a device-level runtime pm reference (mostly used for GEM code to ensure the GTT or GT is on) and ensures that it is powered up.
Any runtime pm reference obtained by this function must have a symmetric
call to intel_runtime_pm_put()
to release the reference again.
-
bool
intel_runtime_pm_get_if_in_use
(struct drm_i915_private * dev_priv)¶ grab a runtime pm reference if device in use
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This function grabs a device-level runtime pm reference if the device is already in use and ensures that it is powered up.
Any runtime pm reference obtained by this function must have a symmetric
call to intel_runtime_pm_put()
to release the reference again.
-
void
intel_runtime_pm_get_noresume
(struct drm_i915_private * dev_priv)¶ grab a runtime pm reference
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This function grabs a device-level runtime pm reference (mostly used for GEM code to ensure the GTT or GT is on).
It will _not_ power up the device but instead only check that it’s powered on. Therefore it is only valid to call this functions from contexts where the device is known to be powered up and where trying to power it up would result in hilarity and deadlocks. That pretty much means only the system suspend/resume code where this is used to grab runtime pm references for delayed setup down in work items.
Any runtime pm reference obtained by this function must have a symmetric
call to intel_runtime_pm_put()
to release the reference again.
-
void
intel_runtime_pm_put
(struct drm_i915_private * dev_priv)¶ release a runtime pm reference
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This function drops the device-level runtime pm reference obtained by
intel_runtime_pm_get()
and might power down the corresponding
hardware block right away if this is the last reference.
-
void
intel_runtime_pm_enable
(struct drm_i915_private * dev_priv)¶ enable runtime pm
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This function enables runtime pm at the end of the driver load sequence.
Note that this function does currently not enable runtime pm for the
subordinate display power domains. That is only done on the first modeset
using intel_display_set_init_power()
.
-
void
intel_uncore_forcewake_get
(struct drm_i915_private * dev_priv, enum forcewake_domains fw_domains)¶ grab forcewake domain references
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum forcewake_domains fw_domains
- forcewake domains to get reference on
Description
This function can be used get GT’s forcewake domain references.
Normal register access will handle the forcewake domains automatically.
However if some sequence requires the GT to not power down a particular
forcewake domains this function should be called at the beginning of the
sequence. And subsequently the reference should be dropped by symmetric
call to intel_unforce_forcewake_put()
. Usually caller wants all the domains
to be kept awake so the fw_domains would be then FORCEWAKE_ALL.
-
void
intel_uncore_forcewake_get__locked
(struct drm_i915_private * dev_priv, enum forcewake_domains fw_domains)¶ grab forcewake domain references
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum forcewake_domains fw_domains
- forcewake domains to get reference on
Description
See intel_uncore_forcewake_get()
. This variant places the onus
on the caller to explicitly handle the dev_priv->uncore.lock spinlock.
-
void
intel_uncore_forcewake_put
(struct drm_i915_private * dev_priv, enum forcewake_domains fw_domains)¶ release a forcewake domain reference
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum forcewake_domains fw_domains
- forcewake domains to put references
Description
This function drops the device-level forcewakes for specified
domains obtained by intel_uncore_forcewake_get()
.
-
void
intel_uncore_forcewake_put__locked
(struct drm_i915_private * dev_priv, enum forcewake_domains fw_domains)¶ grab forcewake domain references
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum forcewake_domains fw_domains
- forcewake domains to get reference on
Description
See intel_uncore_forcewake_put()
. This variant places the onus
on the caller to explicitly handle the dev_priv->uncore.lock spinlock.
-
int
gen6_reset_engines
(struct drm_i915_private * dev_priv, unsigned engine_mask)¶ reset individual engines
Parameters
struct drm_i915_private * dev_priv
- i915 device
unsigned engine_mask
- mask of
intel_ring_flag()
engines or ALL_ENGINES for full reset
Description
This function will reset the individual engines that are set in engine_mask. If you provide ALL_ENGINES as mask, full global domain reset will be issued.
Note
It is responsibility of the caller to handle the difference between asking full domain reset versus reset for all available individual engines.
Returns 0 on success, nonzero on error.
-
enum forcewake_domains
intel_uncore_forcewake_for_reg
(struct drm_i915_private * dev_priv, i915_reg_t reg, unsigned int op)¶ which forcewake domains are needed to access a register
Parameters
struct drm_i915_private * dev_priv
- pointer to struct drm_i915_private
i915_reg_t reg
- register in question
unsigned int op
- operation bitmask of FW_REG_READ and/or FW_REG_WRITE
Description
Returns a set of forcewake domains required to be taken with for example intel_uncore_forcewake_get for the specified register to be accessible in the specified mode (read, write or read/write) with raw mmio accessors.
NOTE
On Gen6 and Gen7 write forcewake domain (FORCEWAKE_RENDER) requires the callers to do FIFO management on their own or risk losing writes.
Interrupt Handling¶
These functions provide the basic support for enabling and disabling the interrupt handling support. There’s a lot more functionality in i915_irq.c and related files, but that will be described in separate chapters.
-
void
intel_irq_init
(struct drm_i915_private * dev_priv)¶ initializes irq support
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This function initializes all the irq support including work items, timers and all the vtables. It does not setup the interrupt itself though.
-
void
intel_runtime_pm_disable_interrupts
(struct drm_i915_private * dev_priv)¶ runtime interrupt disabling
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This function is used to disable interrupts at runtime, both in the runtime pm and the system suspend/resume code.
-
void
intel_runtime_pm_enable_interrupts
(struct drm_i915_private * dev_priv)¶ runtime interrupt enabling
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This function is used to enable interrupts at runtime, both in the runtime pm and the system suspend/resume code.
Intel GVT-g Guest Support(vGPU)¶
Intel GVT-g is a graphics virtualization technology which shares the GPU among multiple virtual machines on a time-sharing basis. Each virtual machine is presented a virtual GPU (vGPU), which has equivalent features as the underlying physical GPU (pGPU), so i915 driver can run seamlessly in a virtual machine. This file provides vGPU specific optimizations when running in a virtual machine, to reduce the complexity of vGPU emulation and to improve the overall performance.
A primary function introduced here is so-called “address space ballooning” technique. Intel GVT-g partitions global graphics memory among multiple VMs, so each VM can directly access a portion of the memory without hypervisor’s intervention, e.g. filling textures or queuing commands. However with the partitioning an unmodified i915 driver would assume a smaller graphics memory starting from address ZERO, then requires vGPU emulation module to translate the graphics address between ‘guest view’ and ‘host view’, for all registers and command opcodes which contain a graphics memory address. To reduce the complexity, Intel GVT-g introduces “address space ballooning”, by telling the exact partitioning knowledge to each guest i915 driver, which then reserves and prevents non-allocated portions from allocation. Thus vGPU emulation module only needs to scan and validate graphics addresses without complexity of address translation.
-
void
i915_check_vgpu
(struct drm_i915_private * dev_priv)¶ detect virtual GPU
Parameters
struct drm_i915_private * dev_priv
- i915 device private
Description
This function is called at the initialization stage, to detect whether running on a vGPU.
-
void
intel_vgt_deballoon
(struct drm_i915_private * dev_priv)¶ deballoon reserved graphics address trunks
Parameters
struct drm_i915_private * dev_priv
- undescribed
Description
This function is called to deallocate the ballooned-out graphic memory, when driver is unloaded or when ballooning fails.
-
int
intel_vgt_balloon
(struct drm_i915_private * dev_priv)¶ balloon out reserved graphics address trunks
Parameters
struct drm_i915_private * dev_priv
- undescribed
Description
This function is called at the initialization stage, to balloon out the graphic address space allocated to other vGPUs, by marking these spaces as reserved. The ballooning related knowledge(starting address and size of the mappable/unmappable graphic memory) is described in the vgt_if structure in a reserved mmio range.
To give an example, the drawing below depicts one typical scenario after ballooning. Here the vGPU1 has 2 pieces of graphic address spaces ballooned out each for the mappable and the non-mappable part. From the vGPU1 point of view, the total size is the same as the physical one, with the start address of its graphic space being zero. Yet there are some portions ballooned out( the shadow part, which are marked as reserved by drm allocator). From the host point of view, the graphic address space is partitioned by multiple vGPUs in different VMs.
vGPU1 view Host view
0 ------> +-----------+ +-----------+
^ |###########| | vGPU3 |
| |###########| +-----------+
| |###########| | vGPU2 |
| +-----------+ +-----------+
mappable GM | available | ==> | vGPU1 |
| +-----------+ +-----------+
| |###########| | |
v |###########| | Host |
+=======+===========+ +===========+
^ |###########| | vGPU3 |
| |###########| +-----------+
| |###########| | vGPU2 |
| +-----------+ +-----------+
unmappable GM | available | ==> | vGPU1 |
| +-----------+ +-----------+
| |###########| | |
| |###########| | Host |
v |###########| | |
total GM size ——> +———–+ +———–+
Return
zero on success, non-zero if configuration invalid or ballooning failed
Display Hardware Handling¶
This section covers everything related to the display hardware including the mode setting infrastructure, plane, sprite and cursor handling and display, output probing and related topics.
Mode Setting Infrastructure¶
The i915 driver is thus far the only DRM driver which doesn’t use the common DRM helper code to implement mode setting sequences. Thus it has its own tailor-made infrastructure for executing a display configuration change.
Frontbuffer Tracking¶
Many features require us to track changes to the currently active frontbuffer, especially rendering targeted at the frontbuffer.
To be able to do so GEM tracks frontbuffers using a bitmask for all possible
frontbuffer slots through i915_gem_track_fb()
. The function in this file are
then called when the contents of the frontbuffer are invalidated, when
frontbuffer rendering has stopped again to flush out all the changes and when
the frontbuffer is exchanged with a flip. Subsystems interested in
frontbuffer changes (e.g. PSR, FBC, DRRS) should directly put their callbacks
into the relevant places and filter for the frontbuffer slots that they are
interested int.
On a high level there are two types of powersaving features. The first one work like a special cache (FBC and PSR) and are interested when they should stop caching and when to restart caching. This is done by placing callbacks into the invalidate and the flush functions: At invalidate the caching must be stopped and at flush time it can be restarted. And maybe they need to know when the frontbuffer changes (e.g. when the hw doesn’t initiate an invalidate and flush on its own) which can be achieved with placing callbacks into the flip functions.
The other type of display power saving feature only cares about busyness (e.g. DRRS). In that case all three (invalidate, flush and flip) indicate busyness. There is no direct way to detect idleness. Instead an idle timer work delayed work should be started from the flush and flip functions and cancelled as soon as busyness is detected.
Note that there’s also an older frontbuffer activity tracking scheme which just tracks general activity. This is done by the various mark_busy and mark_idle functions. For display power management features using these functions is deprecated and should be avoided.
-
void
intel_fb_obj_invalidate
(struct drm_i915_gem_object * obj, enum fb_op_origin origin)¶ invalidate frontbuffer object
Parameters
struct drm_i915_gem_object * obj
- GEM object to invalidate
enum fb_op_origin origin
- which operation caused the invalidation
Description
This function gets called every time rendering on the given object starts and frontbuffer caching (fbc, low refresh rate for DRRS, panel self refresh) must be invalidated. For ORIGIN_CS any subsequent invalidation will be delayed until the rendering completes or a flip on this frontbuffer plane is scheduled.
-
void
intel_frontbuffer_flush
(struct drm_device * dev, unsigned frontbuffer_bits, enum fb_op_origin origin)¶ flush frontbuffer
Parameters
struct drm_device * dev
- DRM device
unsigned frontbuffer_bits
- frontbuffer plane tracking bits
enum fb_op_origin origin
- which operation caused the flush
Description
This function gets called every time rendering on the given planes has completed and frontbuffer caching can be started again. Flushes will get delayed if they’re blocked by some outstanding asynchronous rendering.
Can be called without any locks held.
-
void
intel_fb_obj_flush
(struct drm_i915_gem_object * obj, bool retire, enum fb_op_origin origin)¶ flush frontbuffer object
Parameters
struct drm_i915_gem_object * obj
- GEM object to flush
bool retire
- set when retiring asynchronous rendering
enum fb_op_origin origin
- which operation caused the flush
Description
This function gets called every time rendering on the given object has completed and frontbuffer caching can be started again. If retire is true then any delayed flushes will be unblocked.
-
void
intel_frontbuffer_flip_prepare
(struct drm_device * dev, unsigned frontbuffer_bits)¶ prepare asynchronous frontbuffer flip
Parameters
struct drm_device * dev
- DRM device
unsigned frontbuffer_bits
- frontbuffer plane tracking bits
Description
This function gets called after scheduling a flip on obj. The actual frontbuffer flushing will be delayed until completion is signalled with intel_frontbuffer_flip_complete. If an invalidate happens in between this flush will be cancelled.
Can be called without any locks held.
-
void
intel_frontbuffer_flip_complete
(struct drm_device * dev, unsigned frontbuffer_bits)¶ complete asynchronous frontbuffer flip
Parameters
struct drm_device * dev
- DRM device
unsigned frontbuffer_bits
- frontbuffer plane tracking bits
Description
This function gets called after the flip has been latched and will complete on the next vblank. It will execute the flush if it hasn’t been cancelled yet.
Can be called without any locks held.
-
void
intel_frontbuffer_flip
(struct drm_device * dev, unsigned frontbuffer_bits)¶ synchronous frontbuffer flip
Parameters
struct drm_device * dev
- DRM device
unsigned frontbuffer_bits
- frontbuffer plane tracking bits
Description
This function gets called after scheduling a flip on obj. This is for synchronous plane updates which will happen on the next vblank and which will not get delayed by pending gpu rendering.
Can be called without any locks held.
-
void
i915_gem_track_fb
(struct drm_i915_gem_object * old, struct drm_i915_gem_object * new, unsigned frontbuffer_bits)¶ update frontbuffer tracking
Parameters
struct drm_i915_gem_object * old
- current GEM buffer for the frontbuffer slots
struct drm_i915_gem_object * new
- new GEM buffer for the frontbuffer slots
unsigned frontbuffer_bits
- bitmask of frontbuffer slots
Description
This updates the frontbuffer tracking bits frontbuffer_bits by clearing them from old and setting them in new. Both old and new can be NULL.
Display FIFO Underrun Reporting¶
The i915 driver checks for display fifo underruns using the interrupt signals provided by the hardware. This is enabled by default and fairly useful to debug display issues, especially watermark settings.
If an underrun is detected this is logged into dmesg. To avoid flooding logs and occupying the cpu underrun interrupts are disabled after the first occurrence until the next modeset on a given pipe.
Note that underrun detection on gmch platforms is a bit more ugly since there is no interrupt (despite that the signalling bit is in the PIPESTAT pipe interrupt register). Also on some other platforms underrun interrupts are shared, which means that if we detect an underrun we need to disable underrun reporting on all pipes.
The code also supports underrun detection on the PCH transcoder.
-
bool
intel_set_cpu_fifo_underrun_reporting
(struct drm_i915_private * dev_priv, enum pipe pipe, bool enable)¶ set cpu fifo underrrun reporting state
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum pipe pipe
- (CPU) pipe to set state for
bool enable
- whether underruns should be reported or not
Description
This function sets the fifo underrun state for pipe. It is used in the modeset code to avoid false positives since on many platforms underruns are expected when disabling or enabling the pipe.
Notice that on some platforms disabling underrun reports for one pipe disables for all due to shared interrupts. Actual reporting is still per-pipe though.
Returns the previous state of underrun reporting.
-
bool
intel_set_pch_fifo_underrun_reporting
(struct drm_i915_private * dev_priv, enum transcoder pch_transcoder, bool enable)¶ set PCH fifo underrun reporting state
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum transcoder pch_transcoder
- the PCH transcoder (same as pipe on IVB and older)
bool enable
- whether underruns should be reported or not
Description
This function makes us disable or enable PCH fifo underruns for a specific PCH transcoder. Notice that on some PCHs (e.g. CPT/PPT), disabling FIFO underrun reporting for one transcoder may also disable all the other PCH error interruts for the other transcoders, due to the fact that there’s just one interrupt mask/enable bit for all the transcoders.
Returns the previous state of underrun reporting.
-
void
intel_cpu_fifo_underrun_irq_handler
(struct drm_i915_private * dev_priv, enum pipe pipe)¶ handle CPU fifo underrun interrupt
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum pipe pipe
- (CPU) pipe to set state for
Description
This handles a CPU fifo underrun interrupt, generating an underrun warning into dmesg if underrun reporting is enabled and then disables the underrun interrupt to avoid an irq storm.
-
void
intel_pch_fifo_underrun_irq_handler
(struct drm_i915_private * dev_priv, enum transcoder pch_transcoder)¶ handle PCH fifo underrun interrupt
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum transcoder pch_transcoder
- the PCH transcoder (same as pipe on IVB and older)
Description
This handles a PCH fifo underrun interrupt, generating an underrun warning into dmesg if underrun reporting is enabled and then disables the underrun interrupt to avoid an irq storm.
-
void
intel_check_cpu_fifo_underruns
(struct drm_i915_private * dev_priv)¶ check for CPU fifo underruns immediately
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
Check for CPU fifo underruns immediately. Useful on IVB/HSW where the shared error interrupt may have been disabled, and so CPU fifo underruns won’t necessarily raise an interrupt, and on GMCH platforms where underruns never raise an interrupt.
-
void
intel_check_pch_fifo_underruns
(struct drm_i915_private * dev_priv)¶ check for PCH fifo underruns immediately
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
Check for PCH fifo underruns immediately. Useful on CPT/PPT where the shared error interrupt may have been disabled, and so PCH fifo underruns won’t necessarily raise an interrupt.
Plane Configuration¶
This section covers plane configuration and composition with the primary plane, sprites, cursors and overlays. This includes the infrastructure to do atomic vsync’ed updates of all this state and also tightly coupled topics like watermark setup and computation, framebuffer compression and panel self refresh.
Atomic Plane Helpers¶
The functions here are used by the atomic plane helper functions to implement legacy plane updates (i.e., drm_plane->:c:func:update_plane() and drm_plane->:c:func:disable_plane()). This allows plane updates to use the atomic state infrastructure and perform plane updates as separate prepare/check/commit/cleanup steps.
-
struct intel_plane_state *
intel_create_plane_state
(struct drm_plane * plane)¶ create plane state object
Parameters
struct drm_plane * plane
- drm plane
Description
Allocates a fresh plane state for the given plane and sets some of the state values to sensible initial values.
Return
A newly allocated plane state, or NULL on failure
-
struct drm_plane_state *
intel_plane_duplicate_state
(struct drm_plane * plane)¶ duplicate plane state
Parameters
struct drm_plane * plane
- drm plane
Description
Allocates and returns a copy of the plane state (both common and Intel-specific) for the specified plane.
Return
The newly allocated plane state, or NULL on failure.
-
void
intel_plane_destroy_state
(struct drm_plane * plane, struct drm_plane_state * state)¶ destroy plane state
Parameters
struct drm_plane * plane
- drm plane
struct drm_plane_state * state
- state object to destroy
Description
Destroys the plane state (both common and Intel-specific) for the specified plane.
-
int
intel_plane_atomic_get_property
(struct drm_plane * plane, const struct drm_plane_state * state, struct drm_property * property, uint64_t * val)¶ fetch plane property value
Parameters
struct drm_plane * plane
- plane to fetch property for
const struct drm_plane_state * state
- state containing the property value
struct drm_property * property
- property to look up
uint64_t * val
- pointer to write property value into
Description
The DRM core does not store shadow copies of properties for atomic-capable drivers. This entrypoint is used to fetch the current value of a driver-specific plane property.
-
int
intel_plane_atomic_set_property
(struct drm_plane * plane, struct drm_plane_state * state, struct drm_property * property, uint64_t val)¶ set plane property value
Parameters
struct drm_plane * plane
- plane to set property for
struct drm_plane_state * state
- state to update property value in
struct drm_property * property
- property to set
uint64_t val
- value to set property to
Description
Writes the specified property value for a plane into the provided atomic state object.
Returns 0 on success, -EINVAL on unrecognized properties
Output Probing¶
This section covers output probing and related infrastructure like the hotplug interrupt storm detection and mitigation code. Note that the i915 driver still uses most of the common DRM helper code for output probing, so those sections fully apply.
Hotplug¶
Simply put, hotplug occurs when a display is connected to or disconnected from the system. However, there may be adapters and docking stations and Display Port short pulses and MST devices involved, complicating matters.
Hotplug in i915 is handled in many different levels of abstraction.
The platform dependent interrupt handling code in i915_irq.c enables, disables, and does preliminary handling of the interrupts. The interrupt handlers gather the hotplug detect (HPD) information from relevant registers into a platform independent mask of hotplug pins that have fired.
The platform independent interrupt handler intel_hpd_irq_handler()
in
intel_hotplug.c does hotplug irq storm detection and mitigation, and passes
further processing to appropriate bottom halves (Display Port specific and
regular hotplug).
The Display Port work function i915_digport_work_func()
calls into
intel_dp_hpd_pulse()
via hooks, which handles DP short pulses and DP MST long
pulses, with failures and non-MST long pulses triggering regular hotplug
processing on the connector.
The regular hotplug work function i915_hotplug_work_func()
calls connector
detect hooks, and, if connector status changes, triggers sending of hotplug
uevent to userspace via drm_kms_helper_hotplug_event()
.
Finally, the userspace is responsible for triggering a modeset upon receiving the hotplug uevent, disabling or enabling the crtc as needed.
The hotplug interrupt storm detection and mitigation code keeps track of the number of interrupts per hotplug pin per a period of time, and if the number of interrupts exceeds a certain threshold, the interrupt is disabled for a while before being re-enabled. The intention is to mitigate issues raising from broken hardware triggering massive amounts of interrupts and grinding the system to a halt.
Current implementation expects that hotplug interrupt storm will not be seen when display port sink is connected, hence on platforms whose DP callback is handled by i915_digport_work_func reenabling of hpd is not performed (it was never expected to be disabled in the first place ;) ) this is specific to DP sinks handled by this routine and any other display such as HDMI or DVI enabled on the same port will have proper logic since it will use i915_hotplug_work_func where this logic is handled.
-
bool
intel_hpd_irq_storm_detect
(struct drm_i915_private * dev_priv, enum hpd_pin pin)¶ gather stats and detect HPD irq storm on a pin
Parameters
struct drm_i915_private * dev_priv
- private driver data pointer
enum hpd_pin pin
- the pin to gather stats on
Description
Gather stats about HPD irqs from the specified pin, and detect irq storms. Only the pin specific stats and state are changed, the caller is responsible for further action.
HPD_STORM_THRESHOLD irqs are allowed within HPD_STORM_DETECT_PERIOD ms, otherwise it’s considered an irq storm, and the irq state is set to HPD_MARK_DISABLED.
Return true if an irq storm was detected on pin.
-
void
intel_hpd_irq_handler
(struct drm_i915_private * dev_priv, u32 pin_mask, u32 long_mask)¶ main hotplug irq handler
Parameters
struct drm_i915_private * dev_priv
- drm_i915_private
u32 pin_mask
- a mask of hpd pins that have triggered the irq
u32 long_mask
- a mask of hpd pins that may be long hpd pulses
Description
This is the main hotplug irq handler for all platforms. The platform specific irq handlers call the platform specific hotplug irq handlers, which read and decode the appropriate registers into bitmasks about hpd pins that have triggered (pin_mask), and which of those pins may be long pulses (long_mask). The long_mask is ignored if the port corresponding to the pin is not a digital port.
Here, we do hotplug irq storm detection and mitigation, and pass further processing to appropriate bottom halves.
-
void
intel_hpd_init
(struct drm_i915_private * dev_priv)¶ initializes and enables hpd support
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This function enables the hotplug support. It requires that interrupts have
already been enabled with intel_irq_init_hw()
. From this point on hotplug and
poll request can run concurrently to other code, so locking rules must be
obeyed.
This is a separate step from interrupt enabling to simplify the locking rules in the driver load and resume code.
High Definition Audio¶
The graphics and audio drivers together support High Definition Audio over HDMI and Display Port. The audio programming sequences are divided into audio codec and controller enable and disable sequences. The graphics driver handles the audio codec sequences, while the audio driver handles the audio controller sequences.
The disable sequences must be performed before disabling the transcoder or port. The enable sequences may only be performed after enabling the transcoder and port, and after completed link training. Therefore the audio enable/disable sequences are part of the modeset sequence.
The codec and controller sequences could be done either parallel or serial, but generally the ELDV/PD change in the codec sequence indicates to the audio driver that the controller sequence should start. Indeed, most of the co-operation between the graphics and audio drivers is handled via audio related registers. (The notable exception is the power management, not covered here.)
The struct i915_audio_component is used to interact between the graphics and audio drivers. The struct i915_audio_component_ops *ops in it is defined in graphics driver and called in audio driver. The struct i915_audio_component_audio_ops *audio_ops is called from i915 driver.
-
void
intel_audio_codec_enable
(struct intel_encoder * intel_encoder)¶ Enable the audio codec for HD audio
Parameters
struct intel_encoder * intel_encoder
- encoder on which to enable audio
Description
The enable sequences may only be performed after enabling the transcoder and port, and after completed link training.
-
void
intel_audio_codec_disable
(struct intel_encoder * intel_encoder)¶ Disable the audio codec for HD audio
Parameters
struct intel_encoder * intel_encoder
- encoder on which to disable audio
Description
The disable sequences must be performed before disabling the transcoder or port.
-
void
intel_init_audio_hooks
(struct drm_i915_private * dev_priv)¶ Set up chip specific audio hooks
Parameters
struct drm_i915_private * dev_priv
- device private
-
void
i915_audio_component_init
(struct drm_i915_private * dev_priv)¶ initialize and register the audio component
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This will register with the component framework a child component which will bind dynamically to the snd_hda_intel driver’s corresponding master component when the latter is registered. During binding the child initializes an instance of struct i915_audio_component which it receives from the master. The master can then start to use the interface defined by this struct. Each side can break the binding at any point by deregistering its own component after which each side’s component unbind callback is called.
We ignore any error during registration and continue with reduced functionality (i.e. without HDMI audio).
-
void
i915_audio_component_cleanup
(struct drm_i915_private * dev_priv)¶ deregister the audio component
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
Deregisters the audio component, breaking any existing binding to the corresponding snd_hda_intel driver’s master component.
-
struct
i915_audio_component_ops
¶ Ops implemented by i915 driver, called by hda driver
Definition
struct i915_audio_component_ops {
struct module * owner;
void (* get_power) (struct device *);
void (* put_power) (struct device *);
void (* codec_wake_override) (struct device *, bool enable);
int (* get_cdclk_freq) (struct device *);
int (* sync_audio_rate) (struct device *, int port, int rate);
int (* get_eld) (struct device *, int port, bool *enabled,unsigned char *buf, int max_bytes);
};
Members
struct module * owner
- i915 module
void (*)(struct device *) get_power
get the POWER_DOMAIN_AUDIO power well
Request the power well to be turned on.
void (*)(struct device *) put_power
put the POWER_DOMAIN_AUDIO power well
Allow the power well to be turned off.
void (*)(struct device *, bool enable) codec_wake_override
- Enable/disable codec wake signal
int (*)(struct device *) get_cdclk_freq
- Get the Core Display Clock in kHz
int (*)(struct device *, int port, int rate) sync_audio_rate
set n/cts based on the sample rate
Called from audio driver. After audio driver sets the sample rate, it will call this function to set n/cts
int (*)(struct device *, int port, bool *enabled,unsigned char *buf, int max_bytes) get_eld
fill the audio state and ELD bytes for the given port
Called from audio driver to get the HDMI/DP audio state of the given digital port, and also fetch ELD bytes to the given pointer.
It returns the byte size of the original ELD (not the actually copied size), zero for an invalid ELD, or a negative error code.
Note that the returned size may be over max_bytes. Then it implies that only a part of ELD has been copied to the buffer.
-
struct
i915_audio_component_audio_ops
¶ Ops implemented by hda driver, called by i915 driver
Definition
struct i915_audio_component_audio_ops {
void * audio_ptr;
void (* pin_eld_notify) (void *audio_ptr, int port);
};
Members
void * audio_ptr
- Pointer to be used in call to pin_eld_notify
void (*)(void *audio_ptr, int port) pin_eld_notify
Notify the HDA driver that pin sense and/or ELD information has changed
Called when the i915 driver has set up audio pipeline or has just begun to tear it down. This allows the HDA driver to update its status accordingly (even when the HDA controller is in power save mode).
-
struct
i915_audio_component
¶ Used for direct communication between i915 and hda drivers
Definition
struct i915_audio_component {
struct device * dev;
int aud_sample_rate[MAX_PORTS];
const struct i915_audio_component_ops * ops;
const struct i915_audio_component_audio_ops * audio_ops;
};
Members
struct device * dev
- i915 device, used as parameter for ops
int aud_sample_rate[MAX_PORTS]
- the array of audio sample rate per port
const struct i915_audio_component_ops * ops
- Ops implemented by i915 driver, called by hda driver
const struct i915_audio_component_audio_ops * audio_ops
- Ops implemented by hda driver, called by i915 driver
Panel Self Refresh PSR (PSR/SRD)¶
Since Haswell Display controller supports Panel Self-Refresh on display panels witch have a remote frame buffer (RFB) implemented according to PSR spec in eDP1.3. PSR feature allows the display to go to lower standby states when system is idle but display is on as it eliminates display refresh request to DDR memory completely as long as the frame buffer for that display is unchanged.
Panel Self Refresh must be supported by both Hardware (source) and Panel (sink).
PSR saves power by caching the framebuffer in the panel RFB, which allows us to power down the link and memory controller. For DSI panels the same idea is called “manual mode”.
The implementation uses the hardware-based PSR support which automatically
enters/exits self-refresh mode. The hardware takes care of sending the
required DP aux message and could even retrain the link (that part isn’t
enabled yet though). The hardware also keeps track of any frontbuffer
changes to know when to exit self-refresh mode again. Unfortunately that
part doesn’t work too well, hence why the i915 PSR support uses the
software frontbuffer tracking to make sure it doesn’t miss a screen
update. For this integration intel_psr_invalidate()
and intel_psr_flush()
get called by the frontbuffer tracking code. Note that because of locking
issues the self-refresh re-enable code is done from a work queue, which
must be correctly synchronized/cancelled when shutting down the pipe.”
-
void
intel_psr_enable
(struct intel_dp * intel_dp)¶ Enable PSR
Parameters
struct intel_dp * intel_dp
- Intel DP
Description
This function can only be called after the pipe is fully trained and enabled.
-
void
intel_psr_disable
(struct intel_dp * intel_dp)¶ Disable PSR
Parameters
struct intel_dp * intel_dp
- Intel DP
Description
This function needs to be called before disabling pipe.
-
void
intel_psr_single_frame_update
(struct drm_device * dev, unsigned frontbuffer_bits)¶ Single Frame Update
Parameters
struct drm_device * dev
- DRM device
unsigned frontbuffer_bits
- frontbuffer plane tracking bits
Description
Some platforms support a single frame update feature that is used to send and update only one frame on Remote Frame Buffer. So far it is only implemented for Valleyview and Cherryview because hardware requires this to be done before a page flip.
-
void
intel_psr_invalidate
(struct drm_device * dev, unsigned frontbuffer_bits)¶ Invalidade PSR
Parameters
struct drm_device * dev
- DRM device
unsigned frontbuffer_bits
- frontbuffer plane tracking bits
Description
Since the hardware frontbuffer tracking has gaps we need to integrate with the software frontbuffer tracking. This function gets called every time frontbuffer rendering starts and a buffer gets dirtied. PSR must be disabled if the frontbuffer mask contains a buffer relevant to PSR.
Dirty frontbuffers relevant to PSR are tracked in busy_frontbuffer_bits.”
-
void
intel_psr_flush
(struct drm_device * dev, unsigned frontbuffer_bits, enum fb_op_origin origin)¶ Flush PSR
Parameters
struct drm_device * dev
- DRM device
unsigned frontbuffer_bits
- frontbuffer plane tracking bits
enum fb_op_origin origin
- which operation caused the flush
Description
Since the hardware frontbuffer tracking has gaps we need to integrate with the software frontbuffer tracking. This function gets called every time frontbuffer rendering has completed and flushed out to memory. PSR can be enabled again if no other frontbuffer relevant to PSR is dirty.
Dirty frontbuffers relevant to PSR are tracked in busy_frontbuffer_bits.
-
void
intel_psr_init
(struct drm_device * dev)¶ Init basic PSR work and mutex.
Parameters
struct drm_device * dev
- DRM device
Description
This function is called only once at driver load to initialize basic PSR stuff.
Frame Buffer Compression (FBC)¶
FBC tries to save memory bandwidth (and so power consumption) by compressing the amount of memory used by the display. It is total transparent to user space and completely handled in the kernel.
The benefits of FBC are mostly visible with solid backgrounds and variation-less patterns. It comes from keeping the memory footprint small and having fewer memory pages opened and accessed for refreshing the display.
i915 is responsible to reserve stolen memory for FBC and configure its offset on proper registers. The hardware takes care of all compress/decompress. However there are many known cases where we have to forcibly disable it to allow proper screen updates.
-
bool
intel_fbc_is_active
(struct drm_i915_private * dev_priv)¶ Is FBC active?
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This function is used to verify the current state of FBC.
FIXME: This should be tracked in the plane config eventually instead of queried at runtime for most callers.
-
void
intel_fbc_choose_crtc
(struct drm_i915_private * dev_priv, struct drm_atomic_state * state)¶ select a CRTC to enable FBC on
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
struct drm_atomic_state * state
- the atomic state structure
Description
This function looks at the proposed state for CRTCs and planes, then chooses which pipe is going to have FBC by setting intel_crtc_state->enable_fbc to true.
Later, intel_fbc_enable is going to look for state->enable_fbc and then maybe enable FBC for the chosen CRTC. If it does, it will set dev_priv->fbc.crtc.
-
void
intel_fbc_enable
(struct intel_crtc * crtc, struct intel_crtc_state * crtc_state, struct intel_plane_state * plane_state)¶
Parameters
struct intel_crtc * crtc
- the CRTC
struct intel_crtc_state * crtc_state
- undescribed
struct intel_plane_state * plane_state
- undescribed
Description
This function checks if the given CRTC was chosen for FBC, then enables it if possible. Notice that it doesn’t activate FBC. It is valid to call intel_fbc_enable multiple times for the same pipe without an intel_fbc_disable in the middle, as long as it is deactivated.
-
void
__intel_fbc_disable
(struct drm_i915_private * dev_priv)¶ disable FBC
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This is the low level function that actually disables FBC. Callers should grab the FBC lock.
-
void
intel_fbc_disable
(struct intel_crtc * crtc)¶ disable FBC if it’s associated with crtc
Parameters
struct intel_crtc * crtc
- the CRTC
Description
This function disables FBC if it’s associated with the provided CRTC.
-
void
intel_fbc_global_disable
(struct drm_i915_private * dev_priv)¶ globally disable FBC
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
This function disables FBC regardless of which CRTC is associated with it.
-
void
intel_fbc_init_pipe_state
(struct drm_i915_private * dev_priv)¶ initialize FBC’s CRTC visibility tracking
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
The FBC code needs to track CRTC visibility since the older platforms can’t have FBC enabled while multiple pipes are used. This function does the initial setup at driver load to make sure FBC is matching the real hardware.
-
void
intel_fbc_init
(struct drm_i915_private * dev_priv)¶ Initialize FBC
Parameters
struct drm_i915_private * dev_priv
- the i915 device
Description
This function might be called during PM init process.
Display Refresh Rate Switching (DRRS)¶
Display Refresh Rate Switching (DRRS) is a power conservation feature which enables swtching between low and high refresh rates, dynamically, based on the usage scenario. This feature is applicable for internal panels.
Indication that the panel supports DRRS is given by the panel EDID, which would list multiple refresh rates for one resolution.
DRRS is of 2 types - static and seamless. Static DRRS involves changing refresh rate (RR) by doing a full modeset (may appear as a blink on screen) and is used in dock-undock scenario. Seamless DRRS involves changing RR without any visual effect to the user and can be used during normal system usage. This is done by programming certain registers.
Support for static/seamless DRRS may be indicated in the VBT based on inputs from the panel spec.
DRRS saves power by switching to low RR based on usage scenarios.
The implementation is based on frontbuffer tracking implementation. When there is a disturbance on the screen triggered by user activity or a periodic system activity, DRRS is disabled (RR is changed to high RR). When there is no movement on screen, after a timeout of 1 second, a switch to low RR is made.
For integration with frontbuffer tracking code, intel_edp_drrs_invalidate()
and intel_edp_drrs_flush()
are called.
DRRS can be further extended to support other internal panels and also the scenario of video playback wherein RR is set based on the rate requested by userspace.
-
void
intel_dp_set_drrs_state
(struct drm_device * dev, int refresh_rate)¶ program registers for RR switch to take effect
Parameters
struct drm_device * dev
- DRM device
int refresh_rate
- RR to be programmed
Description
This function gets called when refresh rate (RR) has to be changed from one frequency to another. Switches can be between high and low RR supported by the panel or to any other RR based on media playback (in this case, RR value needs to be passed from user space).
The caller of this function needs to take a lock on dev_priv->drrs.
-
void
intel_edp_drrs_enable
(struct intel_dp * intel_dp)¶ init drrs struct if supported
Parameters
struct intel_dp * intel_dp
- DP struct
Description
Initializes frontbuffer_bits and drrs.dp
-
void
intel_edp_drrs_disable
(struct intel_dp * intel_dp)¶ Disable DRRS
Parameters
struct intel_dp * intel_dp
- DP struct
-
void
intel_edp_drrs_invalidate
(struct drm_device * dev, unsigned frontbuffer_bits)¶ Disable Idleness DRRS
Parameters
struct drm_device * dev
- DRM device
unsigned frontbuffer_bits
- frontbuffer plane tracking bits
Description
This function gets called everytime rendering on the given planes start. Hence DRRS needs to be Upclocked, i.e. (LOW_RR -> HIGH_RR).
Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
-
void
intel_edp_drrs_flush
(struct drm_device * dev, unsigned frontbuffer_bits)¶ Restart Idleness DRRS
Parameters
struct drm_device * dev
- DRM device
unsigned frontbuffer_bits
- frontbuffer plane tracking bits
Description
This function gets called every time rendering on the given planes has completed or flip on a crtc is completed. So DRRS should be upclocked (LOW_RR -> HIGH_RR). And also Idleness detection should be started again, if no other planes are dirty.
Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
-
struct drm_display_mode *
intel_dp_drrs_init
(struct intel_connector * intel_connector, struct drm_display_mode * fixed_mode)¶ Init basic DRRS work and mutex.
Parameters
struct intel_connector * intel_connector
- eDP connector
struct drm_display_mode * fixed_mode
- preferred mode of panel
Description
This function is called only once at driver load to initialize basic DRRS stuff.
Return
Downclock mode if panel supports it, else return NULL. DRRS support is determined by the presence of downclock mode (apart from VBT setting).
DPIO¶
VLV, CHV and BXT have slightly peculiar display PHYs for driving DP/HDMI ports. DPIO is the name given to such a display PHY. These PHYs don’t follow the standard programming model using direct MMIO registers, and instead their registers must be accessed trough IOSF sideband. VLV has one such PHY for driving ports B and C, and CHV adds another PHY for driving port D. Each PHY responds to specific IOSF-SB port.
Each display PHY is made up of one or two channels. Each channel houses a common lane part which contains the PLL and other common logic. CH0 common lane also contains the IOSF-SB logic for the Common Register Interface (CRI) ie. the DPIO registers. CRI clock must be running when any DPIO registers are accessed.
In addition to having their own registers, the PHYs are also controlled through some dedicated signals from the display controller. These include PLL reference clock enable, PLL enable, and CRI clock selection, for example.
Eeach channel also has two splines (also called data lanes), and each spline is made up of one Physical Access Coding Sub-Layer (PCS) block and two TX lanes. So each channel has two PCS blocks and four TX lanes. The TX lanes are used as DP lanes or TMDS data/clock pairs depending on the output type.
Additionally the PHY also contains an AUX lane with AUX blocks for each channel. This is used for DP AUX communication, but this fact isn’t really relevant for the driver since AUX is controlled from the display controller side. No DPIO registers need to be accessed during AUX communication,
Generally on VLV/CHV the common lane corresponds to the pipe and the spline (PCS/TX) corresponds to the port.
For dual channel PHY (VLV/CHV):
pipe A == CMN/PLL/REF CH0
pipe B == CMN/PLL/REF CH1
port B == PCS/TX CH0
port C == PCS/TX CH1
This is especially important when we cross the streams ie. drive port B with pipe B, or port C with pipe A.
For single channel PHY (CHV):
pipe C == CMN/PLL/REF CH0
port D == PCS/TX CH0
On BXT the entire PHY channel corresponds to the port. That means the PLL is also now associated with the port rather than the pipe, and so the clock needs to be routed to the appropriate transcoder. Port A PLL is directly connected to transcoder EDP and port B/C PLLs can be routed to any transcoder A/B/C.
Note: DDI0 is digital port B, DD1 is digital port C, and DDI2 is digital port D (CHV) or port A (BXT).
Dual channel PHY (VLV/CHV/BXT)
---------------------------------
| CH0 | CH1 |
| CMN/PLL/REF | CMN/PLL/REF |
|---------------|---------------| Display PHY
| PCS01 | PCS23 | PCS01 | PCS23 |
|-------|-------|-------|-------|
|TX0|TX1|TX2|TX3|TX0|TX1|TX2|TX3|
---------------------------------
| DDI0 | DDI1 | DP/HDMI ports
---------------------------------
Single channel PHY (CHV/BXT)
-----------------
| CH0 |
| CMN/PLL/REF |
|---------------| Display PHY
| PCS01 | PCS23 |
|-------|-------|
|TX0|TX1|TX2|TX3|
-----------------
| DDI2 | DP/HDMI port
-----------------
CSR firmware support for DMC¶
Display Context Save and Restore (CSR) firmware support added from gen9 onwards to drive newly added DMC (Display microcontroller) in display engine to save and restore the state of display engine when it enter into low-power state and comes back to normal.
Firmware loading status will be one of the below states: FW_UNINITIALIZED, FW_LOADED, FW_FAILED.
Once the firmware is written into the registers status will be moved from FW_UNINITIALIZED to FW_LOADED and for any erroneous condition status will be moved to FW_FAILED.
-
void
intel_csr_load_program
(struct drm_i915_private * dev_priv)¶ write the firmware from memory to register.
Parameters
struct drm_i915_private * dev_priv
- i915 drm device.
Description
CSR firmware is read from a .bin file and kept in internal memory one time. Everytime display comes back from low power state this function is called to copy the firmware from internal memory to registers.
-
void
intel_csr_ucode_init
(struct drm_i915_private * dev_priv)¶ initialize the firmware loading.
Parameters
struct drm_i915_private * dev_priv
- i915 drm device.
Description
This function is called at the time of loading the display driver to read firmware from a .bin file and copied into a internal memory.
-
void
intel_csr_ucode_suspend
(struct drm_i915_private * dev_priv)¶ prepare CSR firmware before system suspend
Parameters
struct drm_i915_private * dev_priv
- i915 drm device
Description
Prepare the DMC firmware before entering system suspend. This includes flushing pending work items and releasing any resources acquired during init.
-
void
intel_csr_ucode_resume
(struct drm_i915_private * dev_priv)¶ init CSR firmware during system resume
Parameters
struct drm_i915_private * dev_priv
- i915 drm device
Description
Reinitialize the DMC firmware during system resume, reacquiring any
resources released in intel_csr_ucode_suspend()
.
-
void
intel_csr_ucode_fini
(struct drm_i915_private * dev_priv)¶ unload the CSR firmware.
Parameters
struct drm_i915_private * dev_priv
- i915 drm device.
Description
Firmmware unloading includes freeing the internal memory and reset the firmware loading status.
Video BIOS Table (VBT)¶
The Video BIOS Table, or VBT, provides platform and board specific configuration information to the driver that is not discoverable or available through other means. The configuration is mostly related to display hardware. The VBT is available via the ACPI OpRegion or, on older systems, in the PCI ROM.
The VBT consists of a VBT Header (defined as struct vbt_header
), a BDB
Header (struct bdb_header
), and a number of BIOS Data Blocks (BDB) that
contain the actual configuration information. The VBT Header, and thus the
VBT, begins with “$VBT” signature. The VBT Header contains the offset of the
BDB Header. The data blocks are concatenated after the BDB Header. The data
blocks have a 1-byte Block ID, 2-byte Block Size, and Block Size bytes of
data. (Block 53, the MIPI Sequence Block is an exception.)
The driver parses the VBT during load. The relevant information is stored in driver private data for ease of use, and the actual VBT is not read after that.
-
bool
intel_bios_is_valid_vbt
(const void * buf, size_t size)¶ does the given buffer contain a valid VBT
Parameters
const void * buf
- pointer to a buffer to validate
size_t size
- size of the buffer
Description
Returns true on valid VBT.
-
int
intel_bios_init
(struct drm_i915_private * dev_priv)¶ find VBT and initialize settings from the BIOS
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
Loads the Video BIOS and checks that the VBT exists. Sets scratch registers to appropriate values.
Returns 0 on success, nonzero on failure.
-
bool
intel_bios_is_tv_present
(struct drm_i915_private * dev_priv)¶ is integrated TV present in VBT
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
Description
Return true if TV is present. If no child devices were parsed from VBT, assume TV is present.
-
bool
intel_bios_is_lvds_present
(struct drm_i915_private * dev_priv, u8 * i2c_pin)¶ is LVDS present in VBT
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
u8 * i2c_pin
- i2c pin for LVDS if present
Description
Return true if LVDS is present. If no child devices were parsed from VBT, assume LVDS is present.
-
bool
intel_bios_is_port_present
(struct drm_i915_private * dev_priv, enum port port)¶ is the specified digital port present
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum port port
- port to check
Description
Return true if the device in port
is present.
-
bool
intel_bios_is_port_edp
(struct drm_i915_private * dev_priv, enum port port)¶ is the device in given port eDP
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum port port
- port to check
Description
Return true if the device in port
is eDP.
-
bool
intel_bios_is_dsi_present
(struct drm_i915_private * dev_priv, enum port * port)¶ is DSI present in VBT
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum port * port
- port for DSI if present
Description
Return true if DSI is present, and return the port in port
.
-
bool
intel_bios_is_port_hpd_inverted
(struct drm_i915_private * dev_priv, enum port port)¶ is HPD inverted for
port
Parameters
struct drm_i915_private * dev_priv
- i915 device instance
enum port port
- port to check
Description
Return true if HPD should be inverted for port
.
-
struct
vbt_header
¶ VBT Header structure
Definition
struct vbt_header {
u8 signature[20];
u16 version;
u16 header_size;
u16 vbt_size;
u8 vbt_checksum;
u8 reserved0;
u32 bdb_offset;
u32 aim_offset[4];
};
Members
u8 signature[20]
- VBT signature, always starts with “$VBT”
u16 version
- Version of this structure
u16 header_size
- Size of this structure
u16 vbt_size
- Size of VBT (VBT Header, BDB Header and data blocks)
u8 vbt_checksum
- Checksum
u8 reserved0
- Reserved
u32 bdb_offset
- Offset of
struct bdb_header
from beginning of VBT u32 aim_offset[4]
- Offsets of add-in data blocks from beginning of VBT
-
struct
bdb_header
¶ BDB Header structure
Definition
struct bdb_header {
u8 signature[16];
u16 version;
u16 header_size;
u16 bdb_size;
};
Members
u8 signature[16]
- BDB signature “BIOS_DATA_BLOCK”
u16 version
- Version of the data block definitions
u16 header_size
- Size of this structure
u16 bdb_size
- Size of BDB (BDB Header and data blocks)
Memory Management and Command Submission¶
This sections covers all things related to the GEM implementation in the i915 driver.
Batchbuffer Parsing¶
Motivation: Certain OpenGL features (e.g. transform feedback, performance monitoring) require userspace code to submit batches containing commands such as MI_LOAD_REGISTER_IMM to access various registers. Unfortunately, some generations of the hardware will noop these commands in “unsecure” batches (which includes all userspace batches submitted via i915) even though the commands may be safe and represent the intended programming model of the device.
The software command parser is similar in operation to the command parsing done in hardware for unsecure batches. However, the software parser allows some operations that would be noop’d by hardware, if the parser determines the operation is safe, and submits the batch as “secure” to prevent hardware parsing.
Threats: At a high level, the hardware (and software) checks attempt to prevent granting userspace undue privileges. There are three categories of privilege.
First, commands which are explicitly defined as privileged or which should only be used by the kernel driver. The parser generally rejects such commands, though it may allow some from the drm master process.
Second, commands which access registers. To support correct/enhanced userspace functionality, particularly certain OpenGL extensions, the parser provides a whitelist of registers which userspace may safely access (for both normal and drm master processes).
Third, commands which access privileged memory (i.e. GGTT, HWS page, etc). The parser always rejects such commands.
The majority of the problematic commands fall in the MI_* range, with only a few specific commands on each ring (e.g. PIPE_CONTROL and MI_FLUSH_DW).
Implementation: Each ring maintains tables of commands and registers which the parser uses in scanning batch buffers submitted to that ring.
Since the set of commands that the parser must check for is significantly smaller than the number of commands supported, the parser tables contain only those commands required by the parser. This generally works because command opcode ranges have standard command length encodings. So for commands that the parser does not need to check, it can easily skip them. This is implemented via a per-ring length decoding vfunc.
Unfortunately, there are a number of commands that do not follow the standard length encoding for their opcode range, primarily amongst the MI_* commands. To handle this, the parser provides a way to define explicit “skip” entries in the per-ring command tables.
Other command table entries map fairly directly to high level categories mentioned above: rejected, master-only, register whitelist. The parser implements a number of checks, including the privileged memory checks, via a general bitmasking mechanism.
-
int
i915_cmd_parser_init_ring
(struct intel_engine_cs * engine)¶ set cmd parser related fields for a ringbuffer
Parameters
struct intel_engine_cs * engine
- the engine to initialize
Description
Optionally initializes fields related to batch buffer command parsing in the struct intel_engine_cs based on whether the platform requires software command parsing.
Return
non-zero if initialization fails
-
void
i915_cmd_parser_fini_ring
(struct intel_engine_cs * engine)¶ clean up cmd parser related fields
Parameters
struct intel_engine_cs * engine
- the engine to clean up
Description
Releases any resources related to command parsing that may have been initialized for the specified ring.
-
bool
i915_needs_cmd_parser
(struct intel_engine_cs * engine)¶ should a given ring use software command parsing?
Parameters
struct intel_engine_cs * engine
- the engine in question
Description
Only certain platforms require software batch buffer command parsing, and only when enabled via module parameter.
Return
true if the ring requires software command parsing
-
int
i915_parse_cmds
(struct intel_engine_cs * engine, struct drm_i915_gem_object * batch_obj, struct drm_i915_gem_object * shadow_batch_obj, u32 batch_start_offset, u32 batch_len, bool is_master)¶ parse a submitted batch buffer for privilege violations
Parameters
struct intel_engine_cs * engine
- the engine on which the batch is to execute
struct drm_i915_gem_object * batch_obj
- the batch buffer in question
struct drm_i915_gem_object * shadow_batch_obj
- copy of the batch buffer in question
u32 batch_start_offset
- byte offset in the batch at which execution starts
u32 batch_len
- length of the commands in batch_obj
bool is_master
- is the submitting process the drm master?
Description
Parses the specified batch buffer looking for privilege violations as described in the overview.
Return
non-zero if the parser finds violations or otherwise fails; -EACCES if the batch appears legal but should use hardware parsing
-
int
i915_cmd_parser_get_version
(struct drm_i915_private * dev_priv)¶ get the cmd parser version number
Parameters
struct drm_i915_private * dev_priv
- i915 device private
Description
The cmd parser maintains a simple increasing integer version number suitable for passing to userspace clients to determine what operations are permitted.
Return
the current version number of the cmd parser
Batchbuffer Pools¶
In order to submit batch buffers as ‘secure’, the software command parser must ensure that a batch buffer cannot be modified after parsing. It does this by copying the user provided batch buffer contents to a kernel owned buffer from which the hardware will actually execute, and by carefully managing the address space bindings for such buffers.
The batch pool framework provides a mechanism for the driver to manage a set of scratch buffers to use for this purpose. The framework can be extended to support other uses cases should they arise.
-
void
i915_gem_batch_pool_init
(struct drm_device * dev, struct i915_gem_batch_pool * pool)¶ initialize a batch buffer pool
Parameters
struct drm_device * dev
- the drm device
struct i915_gem_batch_pool * pool
- the batch buffer pool
-
void
i915_gem_batch_pool_fini
(struct i915_gem_batch_pool * pool)¶ clean up a batch buffer pool
Parameters
struct i915_gem_batch_pool * pool
- the pool to clean up
Note
Callers must hold the struct_mutex.
-
struct drm_i915_gem_object *
i915_gem_batch_pool_get
(struct i915_gem_batch_pool * pool, size_t size)¶ allocate a buffer from the pool
Parameters
struct i915_gem_batch_pool * pool
- the batch buffer pool
size_t size
- the minimum desired size of the returned buffer
Description
Returns an inactive buffer from pool with at least size bytes,
with the pages pinned. The caller must i915_gem_object_unpin_pages()
on the returned object.
Note
Callers must hold the struct_mutex
Return
the buffer object or an error pointer
Logical Rings, Logical Ring Contexts and Execlists¶
Motivation: GEN8 brings an expansion of the HW contexts: “Logical Ring Contexts”. These expanded contexts enable a number of new abilities, especially “Execlists” (also implemented in this file).
One of the main differences with the legacy HW contexts is that logical ring contexts incorporate many more things to the context’s state, like PDPs or ringbuffer control registers:
The reason why PDPs are included in the context is straightforward: as PPGTTs (per-process GTTs) are actually per-context, having the PDPs contained there mean you don’t need to do a ppgtt->switch_mm yourself, instead, the GPU will do it for you on the context switch.
But, what about the ringbuffer control registers (head, tail, etc..)? shouldn’t we just need a set of those per engine command streamer? This is where the name “Logical Rings” starts to make sense: by virtualizing the rings, the engine cs shifts to a new “ring buffer” with every context switch. When you want to submit a workload to the GPU you: A) choose your context, B) find its appropriate virtualized ring, C) write commands to it and then, finally, D) tell the GPU to switch to that context.
Instead of the legacy MI_SET_CONTEXT, the way you tell the GPU to switch to a contexts is via a context execution list, ergo “Execlists”.
LRC implementation: Regarding the creation of contexts, we have:
- One global default context.
- One local default context for each opened fd.
- One local extra context for each context create ioctl call.
Now that ringbuffers belong per-context (and not per-engine, like before) and that contexts are uniquely tied to a given engine (and not reusable, like before) we need:
- One ringbuffer per-engine inside each context.
- One backing object per-engine inside each context.
The global default context starts its life with these new objects fully allocated and populated. The local default context for each opened fd is more complex, because we don’t know at creation time which engine is going to use them. To handle this, we have implemented a deferred creation of LR contexts:
The local context starts its life as a hollow or blank holder, that only gets populated for a given engine once we receive an execbuffer. If later on we receive another execbuffer ioctl for the same context but a different engine, we allocate/populate a new ringbuffer and context backing object and so on.
Finally, regarding local contexts created using the ioctl call: as they are only allowed with the render ring, we can allocate & populate them right away (no need to defer anything, at least for now).
Execlists implementation: Execlists are the new method by which, on gen8+ hardware, workloads are submitted for execution (as opposed to the legacy, ringbuffer-based, method). This method works as follows:
When a request is committed, its commands (the BB start and any leading or trailing commands, like the seqno breadcrumbs) are placed in the ringbuffer for the appropriate context. The tail pointer in the hardware context is not updated at this time, but instead, kept by the driver in the ringbuffer structure. A structure representing this request is added to a request queue for the appropriate engine: this structure contains a copy of the context’s tail after the request was written to the ring buffer and a pointer to the context itself.
If the engine’s request queue was empty before the request was added, the queue is processed immediately. Otherwise the queue will be processed during a context switch interrupt. In any case, elements on the queue will get sent (in pairs) to the GPU’s ExecLists Submit Port (ELSP, for short) with a globally unique 20-bits submission ID.
When execution of a request completes, the GPU updates the context status buffer with a context complete event and generates a context switch interrupt. During the interrupt handling, the driver examines the events in the buffer: for each context complete event, if the announced ID matches that on the head of the request queue, then that request is retired and removed from the queue.
After processing, if any requests were retired and the queue is not empty then a new execution list can be submitted. The two requests at the front of the queue are next to be submitted but since a context may not occur twice in an execution list, if subsequent requests have the same ID as the first then the two requests must be combined. This is done simply by discarding requests at the head of the queue until either only one requests is left (in which case we use a NULL second context) or the first two requests have unique IDs.
By always executing the first two requests in the queue the driver ensures that the GPU is kept as busy as possible. In the case where a single context completes but a second context is still executing, the request for this second context will be at the head of the queue when we remove the first one. This request will then be resubmitted along with a new request for a different context, which will cause the hardware to continue executing the second request and queue the new request (the GPU detects the condition of a context getting preempted with the same context and optimizes the context switch flow by not doing preemption, but just sampling the new tail pointer).
-
int
intel_sanitize_enable_execlists
(struct drm_i915_private * dev_priv, int enable_execlists)¶ sanitize i915.enable_execlists
Parameters
struct drm_i915_private * dev_priv
- i915 device private
int enable_execlists
- value of i915.enable_execlists module parameter.
Description
Only certain platforms support Execlists (the prerequisites being support for Logical Ring Contexts and Aliasing PPGTT or better).
Return
1 if Execlists is supported and has to be enabled.
-
void
intel_lr_context_descriptor_update
(struct i915_gem_context * ctx, struct intel_engine_cs * engine)¶ calculate & cache the descriptor descriptor for a pinned context
Parameters
struct i915_gem_context * ctx
- Context to work on
struct intel_engine_cs * engine
- Engine the descriptor will be used with
Description
The context descriptor encodes various attributes of a context, including its GTT address and some flags. Because it’s fairly expensive to calculate, we’ll just do it once and cache the result, which remains valid until the context is unpinned.
- This is what a descriptor looks like, from LSB to MSB:
- bits 0-11: flags, GEN8_CTX_* (cached in ctx_desc_template) bits 12-31: LRCA, GTT address of (the HWSP of) this context bits 32-52: ctx ID, a globally unique tag bits 53-54: mbz, reserved for use by hardware bits 55-63: group ID, currently unused and set to 0
-
void
intel_lrc_irq_handler
(unsigned long data)¶ handle Context Switch interrupts
Parameters
unsigned long data
- tasklet handler passed in unsigned long
Description
Check the unread Context Status Buffers and manage the submission of new contexts to the ELSP accordingly.
-
int
intel_execlists_submission
(struct i915_execbuffer_params * params, struct drm_i915_gem_execbuffer2 * args, struct list_head * vmas)¶ submit a batchbuffer for execution, Execlists style
Parameters
struct i915_execbuffer_params * params
- execbuffer call parameters.
struct drm_i915_gem_execbuffer2 * args
- execbuffer call arguments.
struct list_head * vmas
- list of vmas.
Description
This is the evil twin version of i915_gem_ringbuffer_submission. It abstracts away the submission details of the execbuffer ioctl call.
Return
non-zero if the submission fails.
-
int
gen8_init_indirectctx_bb
(struct intel_engine_cs * engine, struct i915_wa_ctx_bb * wa_ctx, uint32_t *const batch, uint32_t * offset)¶ initialize indirect ctx batch with WA
Parameters
struct intel_engine_cs * engine
- only applicable for RCS
struct i915_wa_ctx_bb * wa_ctx
structure representing wa_ctx offset: specifies start of the batch, should be cache-aligned. This is updated
with the offset value received as input.size: size of the batch in DWORDS but HW expects in terms of cachelines
uint32_t *const batch
- page in which WA are loaded
uint32_t * offset
- This field specifies the start of the batch, it should be cache-aligned otherwise it is adjusted accordingly. Typically we only have one indirect_ctx and per_ctx batch buffer which are initialized at the beginning and shared across all contexts but this field helps us to have multiple batches at different offsets and select them based on a criteria. At the moment this batch always start at the beginning of the page and at this point we don’t have multiple wa_ctx batch buffers.
Description
The number of WA applied are not known at the beginning; we use this field to return the no of DWORDS written.
It is to be noted that this batch does not contain MI_BATCH_BUFFER_END so it adds NOOPs as padding to make it cacheline aligned. MI_BATCH_BUFFER_END will be added to perctx batch and both of them together makes a complete batch buffer.
Return
non-zero if we exceed the PAGE_SIZE limit.
-
int
gen8_init_perctx_bb
(struct intel_engine_cs * engine, struct i915_wa_ctx_bb * wa_ctx, uint32_t *const batch, uint32_t * offset)¶ initialize per ctx batch with WA
Parameters
struct intel_engine_cs * engine
- only applicable for RCS
struct i915_wa_ctx_bb * wa_ctx
- structure representing wa_ctx offset: specifies start of the batch, should be cache-aligned. size: size of the batch in DWORDS but HW expects in terms of cachelines
uint32_t *const batch
- page in which WA are loaded
uint32_t * offset
- This field specifies the start of this batch. This batch is started immediately after indirect_ctx batch. Since we ensure that indirect_ctx ends on a cacheline this batch is aligned automatically.
Description
The number of DWORDS written are returned using this field.This batch is terminated with MI_BATCH_BUFFER_END and so we need not add padding to align it with cacheline as padding after MI_BATCH_BUFFER_END is redundant.
-
void
intel_logical_ring_cleanup
(struct intel_engine_cs * engine)¶ deallocate the Engine Command Streamer
Parameters
struct intel_engine_cs * engine
- Engine Command Streamer.
-
int
intel_logical_rings_init
(struct drm_device * dev)¶ allocate, populate and init the Engine Command Streamers
Parameters
struct drm_device * dev
- DRM device.
Description
This function inits the engines for an Execlists submission style (the equivalent in the legacy ringbuffer submission world would be i915_gem_init_engines). It does it only for those engines that are present in the hardware.
Return
non-zero if the initialization failed.
-
uint32_t
intel_lr_context_size
(struct intel_engine_cs * engine)¶ return the size of the context for an engine
Parameters
struct intel_engine_cs * engine
- which engine to find the context size for
Description
Each engine may require a different amount of space for a context image, so when allocating (or copying) an image, this function can be used to find the right size for the specific engine.
Return
size (in bytes) of an engine-specific context image
Note
this size includes the HWSP, which is part of the context image in LRC mode, but does not include the “shared data page” used with GuC submission. The caller should account for this if using the GuC.
-
int
execlists_context_deferred_alloc
(struct i915_gem_context * ctx, struct intel_engine_cs * engine)¶ create the LRC specific bits of a context
Parameters
struct i915_gem_context * ctx
- LR context to create.
struct intel_engine_cs * engine
- engine to be used with the context.
Description
This function can be called more than once, with different engines, if we plan to use the context with them. The context backing objects and the ringbuffers (specially the ringbuffer backing objects) suck a lot of memory up, and that’s why the creation is a deferred call: it’s better to make sure first that we need to use a given ring with the context.
Return
non-zero on error.
Global GTT views¶
Background and previous state
Historically objects could exists (be bound) in global GTT space only as singular instances with a view representing all of the object’s backing pages in a linear fashion. This view will be called a normal view.
To support multiple views of the same object, where the number of mapped pages is not equal to the backing store, or where the layout of the pages is not linear, concept of a GGTT view was added.
One example of an alternative view is a stereo display driven by a single image. In this case we would have a framebuffer looking like this (2x2 pages):
12 34
Above would represent a normal GGTT view as normally mapped for GPU or CPU rendering. In contrast, fed to the display engine would be an alternative view which could look something like this:
1212 3434
In this example both the size and layout of pages in the alternative view is different from the normal view.
Implementation and usage
GGTT views are implemented using VMAs and are distinguished via enum i915_ggtt_view_type and struct i915_ggtt_view.
A new flavour of core GEM functions which work with GGTT bound objects were added with the _ggtt_ infix, and sometimes with _view postfix to avoid renaming in large amounts of code. They take the struct i915_ggtt_view parameter encapsulating all metadata required to implement a view.
As a helper for callers which are only interested in the normal view, globally const i915_ggtt_view_normal singleton instance exists. All old core GEM API functions, the ones not taking the view parameter, are operating on, or with the normal GGTT view.
Code wanting to add or use a new GGTT view needs to:
- Add a new enum with a suitable name.
- Extend the metadata in the i915_ggtt_view structure if required.
- Add support to
i915_get_vma_pages()
.
New views are required to build a scatter-gather table from within the i915_get_vma_pages function. This table is stored in the vma.ggtt_view and exists for the lifetime of an VMA.
Core API is designed to have copy semantics which means that passed in struct i915_ggtt_view does not need to be persistent (left around after calling the core API functions).
-
int
gen8_ppgtt_alloc_pagetabs
(struct i915_address_space * vm, struct i915_page_directory * pd, uint64_t start, uint64_t length, unsigned long * new_pts)¶ Allocate page tables for VA range.
Parameters
struct i915_address_space * vm
- Master vm structure.
struct i915_page_directory * pd
- Page directory for this address range.
uint64_t start
- Starting virtual address to begin allocations.
uint64_t length
- Size of the allocations.
unsigned long * new_pts
- Bitmap set by function with new allocations. Likely used by the caller to free on error.
Description
Allocate the required number of page tables. Extremely similar to
gen8_ppgtt_alloc_page_directories()
. The main difference is here we are limited by
the page directory boundary (instead of the page directory pointer). That
boundary is 1GB virtual. Therefore, unlike gen8_ppgtt_alloc_page_directories()
, it is
possible, and likely that the caller will need to use multiple calls of this
function to achieve the appropriate allocation.
Return
0 if success; negative error code otherwise.
-
int
gen8_ppgtt_alloc_page_directories
(struct i915_address_space * vm, struct i915_page_directory_pointer * pdp, uint64_t start, uint64_t length, unsigned long * new_pds)¶ Allocate page directories for VA range.
Parameters
struct i915_address_space * vm
- Master vm structure.
struct i915_page_directory_pointer * pdp
- Page directory pointer for this address range.
uint64_t start
- Starting virtual address to begin allocations.
uint64_t length
- Size of the allocations.
unsigned long * new_pds
- Bitmap set by function with new allocations. Likely used by the caller to free on error.
Description
Allocate the required number of page directories starting at the pde index of start, and ending at the pde index start + length. This function will skip over already allocated page directories within the range, and only allocate new ones, setting the appropriate pointer within the pdp as well as the correct position in the bitmap new_pds.
The function will only allocate the pages within the range for a give page directory pointer. In other words, if start + length straddles a virtually addressed PDP boundary (512GB for 4k pages), there will be more allocations required by the caller, This is not currently possible, and the BUG in the code will prevent it.
Return
0 if success; negative error code otherwise.
-
int
gen8_ppgtt_alloc_page_dirpointers
(struct i915_address_space * vm, struct i915_pml4 * pml4, uint64_t start, uint64_t length, unsigned long * new_pdps)¶ Allocate pdps for VA range.
Parameters
struct i915_address_space * vm
- Master vm structure.
struct i915_pml4 * pml4
- Page map level 4 for this address range.
uint64_t start
- Starting virtual address to begin allocations.
uint64_t length
- Size of the allocations.
unsigned long * new_pdps
- Bitmap set by function with new allocations. Likely used by the caller to free on error.
Description
Allocate the required number of page directory pointers. Extremely similar to
gen8_ppgtt_alloc_page_directories()
and gen8_ppgtt_alloc_pagetabs()
.
The main difference is here we are limited by the pml4 boundary (instead of
the page directory pointer).
Return
0 if success; negative error code otherwise.
-
void
i915_gem_init_ggtt
(struct drm_device * dev)¶ Initialize GEM for Global GTT
Parameters
struct drm_device * dev
- DRM device
-
void
i915_ggtt_cleanup_hw
(struct drm_device * dev)¶ Clean up GGTT hardware initialization
Parameters
struct drm_device * dev
- DRM device
-
int
i915_ggtt_init_hw
(struct drm_device * dev)¶ Initialize GGTT hardware
Parameters
struct drm_device * dev
- DRM device
-
int
i915_vma_bind
(struct i915_vma * vma, enum i915_cache_level cache_level, u32 flags)¶ Sets up PTEs for an VMA in it’s corresponding address space.
Parameters
struct i915_vma * vma
- VMA to map
enum i915_cache_level cache_level
- mapping cache level
u32 flags
- flags like global or local mapping
Description
DMA addresses are taken from the scatter-gather table of this object (or of this VMA in case of non-default GGTT views) and PTE entries set up. Note that DMA addresses are also the only part of the SG table we care about.
-
size_t
i915_ggtt_view_size
(struct drm_i915_gem_object * obj, const struct i915_ggtt_view * view)¶ Get the size of a GGTT view.
Parameters
struct drm_i915_gem_object * obj
- Object the view is of.
const struct i915_ggtt_view * view
- The view in question.
Description
return The size of the GGTT view in bytes.
GTT Fences and Swizzling¶
-
int
i915_gem_object_put_fence
(struct drm_i915_gem_object * obj)¶ force-remove fence for an object
Parameters
struct drm_i915_gem_object * obj
- object to map through a fence reg
Description
This function force-removes any fence from the given object, which is useful if the kernel wants to do untiled GTT access.
Return
0 on success, negative error code on failure.
-
int
i915_gem_object_get_fence
(struct drm_i915_gem_object * obj)¶ set up fencing for an object
Parameters
struct drm_i915_gem_object * obj
- object to map through a fence reg
Description
When mapping objects through the GTT, userspace wants to be able to write to them without having to worry about swizzling if the object is tiled. This function walks the fence regs looking for a free one for obj, stealing one if it can’t find any.
It then sets up the reg based on the object’s properties: address, pitch and tiling format.
For an untiled surface, this removes any existing fence.
Return
0 on success, negative error code on failure.
-
bool
i915_gem_object_pin_fence
(struct drm_i915_gem_object * obj)¶ pin fencing state
Parameters
struct drm_i915_gem_object * obj
- object to pin fencing for
Description
This pins the fencing state (whether tiled or untiled) to make sure the
object is ready to be used as a scanout target. Fencing status must be
synchronize first by calling i915_gem_object_get_fence()
:
The resulting fence pin reference must be released again with
i915_gem_object_unpin_fence()
.
Return
True if the object has a fence, false otherwise.
-
void
i915_gem_object_unpin_fence
(struct drm_i915_gem_object * obj)¶ unpin fencing state
Parameters
struct drm_i915_gem_object * obj
- object to unpin fencing for
Description
This releases the fence pin reference acquired through i915_gem_object_pin_fence. It will handle both objects with and without an attached fence correctly, callers do not need to distinguish this.
-
void
i915_gem_restore_fences
(struct drm_device * dev)¶ restore fence state
Parameters
struct drm_device * dev
- DRM device
Description
Restore the hw fence state to match the software tracking again, to be called after a gpu reset and on resume.
-
void
i915_gem_detect_bit_6_swizzle
(struct drm_device * dev)¶ detect bit 6 swizzling pattern
Parameters
struct drm_device * dev
- DRM device
Description
Detects bit 6 swizzling of address lookup between IGD access and CPU access through main memory.
-
void
i915_gem_object_do_bit_17_swizzle
(struct drm_i915_gem_object * obj)¶ fixup bit 17 swizzling
Parameters
struct drm_i915_gem_object * obj
- i915 GEM buffer object
Description
This function fixes up the swizzling in case any page frame number for this
object has changed in bit 17 since that state has been saved with
i915_gem_object_save_bit_17_swizzle()
.
This is called when pinning backing storage again, since the kernel is free to move unpinned backing storage around (either by directly moving pages or by swapping them out and back in again).
-
void
i915_gem_object_save_bit_17_swizzle
(struct drm_i915_gem_object * obj)¶ save bit 17 swizzling
Parameters
struct drm_i915_gem_object * obj
- i915 GEM buffer object
Description
This function saves the bit 17 of each page frame number so that swizzling
can be fixed up later on with i915_gem_object_do_bit_17_swizzle()
. This must
be called before the backing storage can be unpinned.
Global GTT Fence Handling¶
Important to avoid confusions: “fences” in the i915 driver are not execution fences used to track command completion but hardware detiler objects which wrap a given range of the global GTT. Each platform has only a fairly limited set of these objects.
Fences are used to detile GTT memory mappings. They’re also connected to the hardware frontbuffer render tracking and hence interact with frontbuffer compression. Furthermore on older platforms fences are required for tiled objects used by the display engine. They can also be used by the render engine - they’re required for blitter commands and are optional for render commands. But on gen4+ both display (with the exception of fbc) and rendering have their own tiling state bits and don’t need fences.
Also note that fences only support X and Y tiling and hence can’t be used for the fancier new tiling formats like W, Ys and Yf.
Finally note that because fences are such a restricted resource they’re
dynamically associated with objects. Furthermore fence state is committed to
the hardware lazily to avoid unnecessary stalls on gen2/3. Therefore code must
explicitly call i915_gem_object_get_fence()
to synchronize fencing status
for cpu access. Also note that some code wants an unfenced view, for those
cases the fence can be removed forcefully with i915_gem_object_put_fence()
.
Internally these functions will synchronize with userspace access by removing CPU ptes into GTT mmaps (not the GTT ptes themselves) as needed.
Hardware Tiling and Swizzling Details¶
The idea behind tiling is to increase cache hit rates by rearranging pixel data so that a group of pixel accesses are in the same cacheline. Performance improvement from doing this on the back/depth buffer are on the order of 30%.
Intel architectures make this somewhat more complicated, though, by adjustments made to addressing of data when the memory is in interleaved mode (matched pairs of DIMMS) to improve memory bandwidth. For interleaved memory, the CPU sends every sequential 64 bytes to an alternate memory channel so it can get the bandwidth from both.
The GPU also rearranges its accesses for increased bandwidth to interleaved memory, and it matches what the CPU does for non-tiled. However, when tiled it does it a little differently, since one walks addresses not just in the X direction but also Y. So, along with alternating channels when bit 6 of the address flips, it also alternates when other bits flip – Bits 9 (every 512 bytes, an X tile scanline) and 10 (every two X tile scanlines) are common to both the 915 and 965-class hardware.
The CPU also sometimes XORs in higher bits as well, to improve bandwidth doing strided access like we do so frequently in graphics. This is called “Channel XOR Randomization” in the MCH documentation. The result is that the CPU is XORing in either bit 11 or bit 17 to bit 6 of its address decode.
All of this bit 6 XORing has an effect on our memory management, as we need to make sure that the 3d driver can correctly address object contents.
If we don’t have interleaved memory, all tiling is safe and no swizzling is required.
When bit 17 is XORed in, we simply refuse to tile at all. Bit 17 is not just a page offset, so as we page an object out and back in, individual pages in it will have different bit 17 addresses, resulting in each 64 bytes being swapped with its neighbor!
Otherwise, if interleaved, we have to tell the 3d driver what the address swizzling it needs to do is, since it’s writing with the CPU to the pages (bit 6 and potentially bit 11 XORed in), and the GPU is reading from the pages (bit 6, 9, and 10 XORed in), resulting in a cumulative bit swizzling required by the CPU of XORing in bit 6, 9, 10, and potentially 11, in order to match what the GPU expects.
Object Tiling IOCTLs¶
-
int
i915_gem_set_tiling
(struct drm_device * dev, void * data, struct drm_file * file)¶ IOCTL handler to set tiling mode
Parameters
struct drm_device * dev
- DRM device
void * data
- data pointer for the ioctl
struct drm_file * file
- DRM file for the ioctl call
Description
Sets the tiling mode of an object, returning the required swizzling of bit 6 of addresses in the object.
Called by the user via ioctl.
Return
Zero on success, negative errno on failure.
-
int
i915_gem_get_tiling
(struct drm_device * dev, void * data, struct drm_file * file)¶ IOCTL handler to get tiling mode
Parameters
struct drm_device * dev
- DRM device
void * data
- data pointer for the ioctl
struct drm_file * file
- DRM file for the ioctl call
Description
Returns the current tiling mode and required bit 6 swizzling for the object.
Called by the user via ioctl.
Return
Zero on success, negative errno on failure.
i915_gem_set_tiling()
and i915_gem_get_tiling()
is the userspace interface to
declare fence register requirements.
In principle GEM doesn’t care at all about the internal data layout of an object, and hence it also doesn’t care about tiling or swizzling. There’s two exceptions:
- For X and Y tiling the hardware provides detilers for CPU access, so called fences. Since there’s only a limited amount of them the kernel must manage these, and therefore userspace must tell the kernel the object tiling if it wants to use fences for detiling.
- On gen3 and gen4 platforms have a swizzling pattern for tiled objects which depends upon the physical page frame number. When swapping such objects the page frame number might change and the kernel must be able to fix this up and hence now the tiling. Note that on a subset of platforms with asymmetric memory channel population the swizzling pattern changes in an unknown way, and for those the kernel simply forbids swapping completely.
Since neither of this applies for new tiling layouts on modern platforms like W, Ys and Yf tiling GEM only allows object tiling to be set to X or Y tiled. Anything else can be handled in userspace entirely without the kernel’s invovlement.
Buffer Object Eviction¶
This section documents the interface functions for evicting buffer objects to make space available in the virtual gpu address spaces. Note that this is mostly orthogonal to shrinking buffer objects caches, which has the goal to make main memory (shared with the gpu through the unified memory architecture) available.
-
int
i915_gem_evict_something
(struct drm_device * dev, struct i915_address_space * vm, int min_size, unsigned alignment, unsigned cache_level, unsigned long start, unsigned long end, unsigned flags)¶ Evict vmas to make room for binding a new one
Parameters
struct drm_device * dev
- drm_device
struct i915_address_space * vm
- address space to evict from
int min_size
- size of the desired free space
unsigned alignment
- alignment constraint of the desired free space
unsigned cache_level
- cache_level for the desired space
unsigned long start
- start (inclusive) of the range from which to evict objects
unsigned long end
- end (exclusive) of the range from which to evict objects
unsigned flags
- additional flags to control the eviction algorithm
Description
This function will try to evict vmas until a free space satisfying the requirements is found. Callers must check first whether any such hole exists already before calling this function.
This function is used by the object/vma binding code.
Since this function is only used to free up virtual address space it only ignores pinned vmas, and not object where the backing storage itself is pinned. Hence obj->pages_pin_count does not protect against eviction.
To clarify: This is for freeing up virtual address space, not for freeing memory in e.g. the shrinker.
-
int
i915_gem_evict_vm
(struct i915_address_space * vm, bool do_idle)¶ Evict all idle vmas from a vm
Parameters
struct i915_address_space * vm
- Address space to cleanse
bool do_idle
- Boolean directing whether to idle first.
Description
This function evicts all idles vmas from a vm. If all unpinned vmas should be evicted the do_idle needs to be set to true.
This is used by the execbuf code as a last-ditch effort to defragment the address space.
To clarify: This is for freeing up virtual address space, not for freeing memory in e.g. the shrinker.
Buffer Object Memory Shrinking¶
This section documents the interface function for shrinking memory usage of buffer object caches. Shrinking is used to make main memory available. Note that this is mostly orthogonal to evicting buffer objects, which has the goal to make space in gpu virtual address spaces.
-
unsigned long
i915_gem_shrink
(struct drm_i915_private * dev_priv, unsigned long target, unsigned flags)¶ Shrink buffer object caches
Parameters
struct drm_i915_private * dev_priv
- i915 device
unsigned long target
- amount of memory to make available, in pages
unsigned flags
- control flags for selecting cache types
Description
This function is the main interface to the shrinker. It will try to release up to target pages of main memory backing storage from buffer objects. Selection of the specific caches can be done with flags. This is e.g. useful when purgeable objects should be removed from caches preferentially.
Note that it’s not guaranteed that released amount is actually available as
free system memory - the pages might still be in-used to due to other reasons
(like cpu mmaps) or the mm core has reused them before we could grab them.
Therefore code that needs to explicitly shrink buffer objects caches (e.g. to
avoid deadlocks in memory reclaim) must fall back to i915_gem_shrink_all()
.
Also note that any kind of pinning (both per-vma address space pins and backing storage pins at the buffer object level) result in the shrinker code having to skip the object.
Return
The number of pages of backing storage actually released.
-
unsigned long
i915_gem_shrink_all
(struct drm_i915_private * dev_priv)¶ Shrink buffer object caches completely
Parameters
struct drm_i915_private * dev_priv
- i915 device
Description
This is a simple wraper around i915_gem_shrink()
to aggressively shrink all
caches completely. It also first waits for and retires all outstanding
requests to also be able to release backing storage for active objects.
This should only be used in code to intentionally quiescent the gpu or as a last-ditch effort when memory seems to have run out.
Return
The number of pages of backing storage actually released.
-
void
i915_gem_shrinker_init
(struct drm_i915_private * dev_priv)¶ Initialize i915 shrinker
Parameters
struct drm_i915_private * dev_priv
- i915 device
Description
This function registers and sets up the i915 shrinker and OOM handler.
-
void
i915_gem_shrinker_cleanup
(struct drm_i915_private * dev_priv)¶ Clean up i915 shrinker
Parameters
struct drm_i915_private * dev_priv
- i915 device
Description
This function unregisters the i915 shrinker and OOM handler.
GuC¶
GuC-specific firmware loader¶
intel_guc: Top level structure of guc. It handles firmware loading and manages client pool and doorbells. intel_guc owns a i915_guc_client to replace the legacy ExecList submission.
Firmware versioning: The firmware build process will generate a version header file with major and minor version defined. The versions are built into CSS header of firmware. i915 kernel driver set the minimal firmware version required per platform. The firmware installation package will install (symbolic link) proper version of firmware.
GuC address space: GuC does not allow any gfx GGTT address that falls into range [0, WOPCM_TOP), which is reserved for Boot ROM, SRAM and WOPCM. Currently this top address is 512K. In order to exclude 0-512K address space from GGTT, all gfx objects used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM.
Firmware log: Firmware log is enabled by setting i915.guc_log_level to non-negative level. Log data is printed out via reading debugfs i915_guc_log_dump. Reading from i915_guc_load_status will print out firmware loading status and scratch registers value.
-
int
intel_guc_setup
(struct drm_device * dev)¶ finish preparing the GuC for activity
Parameters
struct drm_device * dev
- drm device
Description
Called from gem_init_hw()
during driver loading and also after a GPU reset.
The main action required here it to load the GuC uCode into the device.
The firmware image should have already been fetched into memory by the
earlier call to intel_guc_init()
, so here we need only check that worked,
and then transfer the image to the h/w.
Return
non-zero code on error
-
void
intel_guc_init
(struct drm_device * dev)¶ define parameters and fetch firmware
Parameters
struct drm_device * dev
- drm device
Description
Called early during driver load, but after GEM is initialised.
The firmware will be transferred to the GuC’s memory later,
when intel_guc_setup()
is called.
-
void
intel_guc_fini
(struct drm_device * dev)¶ clean up all allocated resources
Parameters
struct drm_device * dev
- drm device
GuC-based command submission¶
i915_guc_client: We use the term client to avoid confusion with contexts. A i915_guc_client is equivalent to GuC object guc_context_desc. This context descriptor is allocated from a pool of 1024 entries. Kernel driver will allocate doorbell and workqueue for it. Also the process descriptor (guc_process_desc), which is mapped to client space. So the client can write Work Item then ring the doorbell.
To simplify the implementation, we allocate one gem object that contains all pages for doorbell, process descriptor and workqueue.
The Scratch registers:
There are 16 MMIO-based registers start from 0xC180. The kernel driver writes
a value to the action register (SOFT_SCRATCH_0) along with any data. It then
triggers an interrupt on the GuC via another register write (0xC4C8).
Firmware writes a success/fail code back to the action register after
processes the request. The kernel driver polls waiting for this update and
then proceeds.
See host2guc_action()
Doorbells: Doorbells are interrupts to uKernel. A doorbell is a single cache line (QW) mapped into process space.
Work Items:
There are several types of work items that the host may place into a
workqueue, each with its own requirements and limitations. Currently only
WQ_TYPE_INORDER is needed to support legacy submission via GuC, which
represents in-order queue. The kernel driver packs ring tail pointer and an
ELSP context descriptor dword into Work Item.
See guc_add_workqueue_item()
-
int
i915_guc_wq_check_space
(struct drm_i915_gem_request * request)¶ check that the GuC can accept a request
Parameters
struct drm_i915_gem_request * request
- request associated with the commands
Return
- 0 if space is available
- -EAGAIN if space is not currently available
This function must be called (and must return 0) before a request
is submitted to the GuC via i915_guc_submit()
below. Once a result
of 0 has been returned, it remains valid until (but only until)
the next call to submit()
.
This precheck allows the caller to determine in advance that space will be available for the next submission before committing resources to it, and helps avoid late failures with complicated recovery paths.
-
int
i915_guc_submit
(struct drm_i915_gem_request * rq)¶ Submit commands through GuC
Parameters
struct drm_i915_gem_request * rq
- request associated with the commands
Return
- 0 on success, otherwise an errno.
- (Note: nonzero really shouldn’t happen!)
The caller must have already called i915_guc_wq_check_space()
above
with a result of 0 (success) since the last request submission. This
guarantees that there is space in the work queue for the new request,
so enqueuing the item cannot fail.
Bad Things Will Happen if the caller violates this protocol e.g. calls
submit()
when check()
says there’s no space, or calls submit()
multiple
times with no intervening check()
.
The only error here arises if the doorbell hardware isn’t functioning as expected, which really shouln’t happen.
-
struct drm_i915_gem_object *
gem_allocate_guc_obj
(struct drm_i915_private * dev_priv, u32 size)¶ Allocate gem object for GuC usage
Parameters
struct drm_i915_private * dev_priv
- driver private data structure
u32 size
- size of object
Description
This is a wrapper to create a gem obj. In order to use it inside GuC, the object needs to be pinned lifetime. Also we must pin it to gtt space other than [0, GUC_WOPCM_TOP) because this range is reserved inside GuC.
Return
A drm_i915_gem_object if successful, otherwise NULL.
-
void
gem_release_guc_obj
(struct drm_i915_gem_object * obj)¶ Release gem object allocated for GuC usage
Parameters
struct drm_i915_gem_object * obj
- gem obj to be released
-
struct i915_guc_client *
guc_client_alloc
(struct drm_i915_private * dev_priv, uint32_t priority, struct i915_gem_context * ctx)¶ Allocate an i915_guc_client
Parameters
struct drm_i915_private * dev_priv
- driver private data structure
uint32_t priority
- four levels priority _CRITICAL, _HIGH, _NORMAL and _LOW The kernel client to replace ExecList submission is created with NORMAL priority. Priority of a client for scheduler can be HIGH, while a preemption context can use CRITICAL.
struct i915_gem_context * ctx
- the context that owns the client (we use the default render context)
Return
An i915_guc_client object if success, else NULL.
-
int
intel_guc_suspend
(struct drm_device * dev)¶ notify GuC entering suspend state
Parameters
struct drm_device * dev
- drm device
-
int
intel_guc_resume
(struct drm_device * dev)¶ notify GuC resuming from suspend state
Parameters
struct drm_device * dev
- drm device
GuC Firmware Layout¶
The GuC firmware layout looks like this:
guc_css_headercontains major/minor version
uCode RSA signature modulus key exponent val
The firmware may or may not have modulus key and exponent data. The header, uCode and RSA signature are must-have components that will be used by driver. Length of each components, which is all in dwords, can be found in header. In the case that modulus and exponent are not present in fw, a.k.a truncated image, the length value still appears in header.
Driver will do some basic fw size validation based on the following rules:
- Header, uCode and RSA are must-have components.
2. All firmware components, if they present, are in the sequence illustrated in the layout table above. 3. Length info of each component can be found in header, in dwords. 4. Modulus and exponent key are not required by driver. They may not appear in fw. So driver will load a truncated firmware in this case.
Tracing¶
This sections covers all things related to the tracepoints implemented in the i915 driver.
i915_ppgtt_create and i915_ppgtt_release¶
With full ppgtt enabled each process using drm will allocate at least one translation table. With these traces it is possible to keep track of the allocation and of the lifetime of the tables; this can be used during testing/debug to verify that we are not leaking ppgtts. These traces identify the ppgtt through the vm pointer, which is also printed by the i915_vma_bind and i915_vma_unbind tracepoints.
i915_context_create and i915_context_free¶
These tracepoints are used to track creation and deletion of contexts. If full ppgtt is enabled, they also print the address of the vm assigned to the context.
switch_mm¶
This tracepoint allows tracking of the mm switch, which is an important point in the lifetime of the vm in the legacy submission path. This tracepoint is called only if full ppgtt is enabled.
vga_switcheroo is the Linux subsystem for laptop hybrid graphics. These come in two flavors:
muxed: Dual GPUs with a multiplexer chip to switch outputs between GPUs.
- muxless: Dual GPUs but only one of them is connected to outputs.
The other one is merely used to offload rendering, its results are copied over PCIe into the framebuffer. On Linux this is supported with DRI PRIME.
Hybrid graphics started to appear in the late Naughties and were initially all muxed. Newer laptops moved to a muxless architecture for cost reasons. A notable exception is the MacBook Pro which continues to use a mux. Muxes come with varying capabilities: Some switch only the panel, others can also switch external displays. Some switch all display pins at once while others can switch just the DDC lines. (To allow EDID probing for the inactive GPU.) Also, muxes are often used to cut power to the discrete GPU while it is not used.
DRM drivers register GPUs with vga_switcheroo, these are henceforth called clients. The mux is called the handler. Muxless machines also register a handler to control the power state of the discrete GPU, its ->switchto callback is a no-op for obvious reasons. The discrete GPU is often equipped with an HDA controller for the HDMI/DP audio signal, this will also register as a client so that vga_switcheroo can take care of the correct suspend/resume order when changing the discrete GPU’s power state. In total there can thus be up to three clients: Two vga clients (GPUs) and one audio client (on the discrete GPU). The code is mostly prepared to support machines with more than two GPUs should they become available.
The GPU to which the outputs are currently switched is called the active client in vga_switcheroo parlance. The GPU not in use is the inactive client. When the inactive client’s DRM driver is loaded, it will be unable to probe the panel’s EDID and hence depends on VBIOS to provide its display modes. If the VBIOS modes are bogus or if there is no VBIOS at all (which is common on the MacBook Pro), a client may alternatively request that the DDC lines are temporarily switched to it, provided that the handler supports this. Switching only the DDC lines and not the entire output avoids unnecessary flickering.
Modes of Use¶
Manual switching and manual power control¶
In this mode of use, the file /sys/kernel/debug/vgaswitcheroo/switch can be read to retrieve the current vga_switcheroo state and commands can be written to it to change the state. The file appears as soon as two GPU drivers and one handler have registered with vga_switcheroo. The following commands are understood:
OFF: Power off the device not in use.
ON: Power on the device not in use.
- IGD: Switch to the integrated graphics device.
Power on the integrated GPU if necessary, power off the discrete GPU. Prerequisite is that no user space processes (e.g. Xorg, alsactl) have opened device files of the GPUs or the audio client. If the switch fails, the user may invoke lsof(8) or fuser(1) on /dev/dri/ and /dev/snd/controlC1 to identify processes blocking the switch.
DIS: Switch to the discrete graphics device.
- DIGD: Delayed switch to the integrated graphics device.
This will perform the switch once the last user space process has closed the device files of the GPUs and the audio client.
DDIS: Delayed switch to the discrete graphics device.
- MIGD: Mux-only switch to the integrated graphics device.
Does not remap console or change the power state of either gpu. If the integrated GPU is currently off, the screen will turn black. If it is on, the screen will show whatever happens to be in VRAM. Either way, the user has to blindly enter the command to switch back.
MDIS: Mux-only switch to the discrete graphics device.
For GPUs whose power state is controlled by the driver’s runtime pm, the ON and OFF commands are a no-op (see next section).
For muxless machines, the IGD/DIS, DIGD/DDIS and MIGD/MDIS commands should not be used.
Driver power control¶
In this mode of use, the discrete GPU automatically powers up and down at the discretion of the driver’s runtime pm. On muxed machines, the user may still influence the muxer state by way of the debugfs interface, however the ON and OFF commands become a no-op for the discrete GPU.
This mode is the default on Nvidia HybridPower/Optimus and ATI PowerXpress. Specifying nouveau.runpm=0, radeon.runpm=0 or amdgpu.runpm=0 on the kernel command line disables it.
When the driver decides to power up or down, it notifies vga_switcheroo
thereof so that it can (a) power the audio device on the GPU up or down,
and (b) update its internal power state representation for the device.
This is achieved by vga_switcheroo_set_dynamic_switch()
.
After the GPU has been suspended, the handler needs to be called to cut
power to the GPU. Likewise it needs to reinstate power before the GPU
can resume. This is achieved by vga_switcheroo_init_domain_pm_ops()
,
which augments the GPU’s suspend/resume functions by the requisite
calls to the handler.
When the audio device resumes, the GPU needs to be woken. This is achieved
by vga_switcheroo_init_domain_pm_optimus_hdmi_audio()
, which augments the
audio device’s resume function.
On muxed machines, if the mux is initially switched to the discrete GPU, the user ends up with a black screen when the GPU powers down after boot. As a workaround, the mux is forced to the integrated GPU on runtime suspend, cf. https://bugs.freedesktop.org/show_bug.cgi?id=75917
API¶
Public functions¶
-
int
vga_switcheroo_register_handler
(const struct vga_switcheroo_handler * handler, enum vga_switcheroo_handler_flags_t handler_flags)¶ register handler
Parameters
const struct vga_switcheroo_handler * handler
- handler callbacks
enum vga_switcheroo_handler_flags_t handler_flags
- handler flags
Description
Register handler. Enable vga_switcheroo if two vga clients have already registered.
Return
0 on success, -EINVAL if a handler was already registered.
-
void
vga_switcheroo_unregister_handler
(void)¶ unregister handler
Parameters
void
- no arguments
Description
Unregister handler. Disable vga_switcheroo.
-
enum vga_switcheroo_handler_flags_t
vga_switcheroo_handler_flags
(void)¶ obtain handler flags
Parameters
void
- no arguments
Description
Helper for clients to obtain the handler flags bitmask.
Return
Handler flags. A value of 0 means that no handler is registered or that the handler has no special capabilities.
-
int
vga_switcheroo_register_client
(struct pci_dev * pdev, const struct vga_switcheroo_client_ops * ops, bool driver_power_control)¶ register vga client
Parameters
struct pci_dev * pdev
- client pci device
const struct vga_switcheroo_client_ops * ops
- client callbacks
bool driver_power_control
- whether power state is controlled by the driver’s runtime pm
Description
Register vga client (GPU). Enable vga_switcheroo if another GPU and a
handler have already registered. The power state of the client is assumed
to be ON. Beforehand, vga_switcheroo_client_probe_defer()
shall be called
to ensure that all prerequisites are met.
Return
0 on success, -ENOMEM on memory allocation error.
-
int
vga_switcheroo_register_audio_client
(struct pci_dev * pdev, const struct vga_switcheroo_client_ops * ops, enum vga_switcheroo_client_id id)¶ register audio client
Parameters
struct pci_dev * pdev
- client pci device
const struct vga_switcheroo_client_ops * ops
- client callbacks
enum vga_switcheroo_client_id id
- client identifier
Description
Register audio client (audio device on a GPU). The power state of the
client is assumed to be ON. Beforehand, vga_switcheroo_client_probe_defer()
shall be called to ensure that all prerequisites are met.
Return
0 on success, -ENOMEM on memory allocation error.
-
bool
vga_switcheroo_client_probe_defer
(struct pci_dev * pdev)¶ whether to defer probing a given client
Parameters
struct pci_dev * pdev
- client pci device
Description
Determine whether any prerequisites are not fulfilled to probe a given
client. Drivers shall invoke this early on in their ->probe callback
and return -EPROBE_DEFER
if it evaluates to true
. Thou shalt not
register the client ere thou hast called this.
Return
true
if probing should be deferred, otherwise false
.
-
enum vga_switcheroo_state
vga_switcheroo_get_client_state
(struct pci_dev * pdev)¶ obtain power state of a given client
Parameters
struct pci_dev * pdev
- client pci device
Description
Obtain power state of a given client as seen from vga_switcheroo. The function is only called from hda_intel.c.
Return
Power state.
-
void
vga_switcheroo_unregister_client
(struct pci_dev * pdev)¶ unregister client
Parameters
struct pci_dev * pdev
- client pci device
Description
Unregister client. Disable vga_switcheroo if this is a vga client (GPU).
-
void
vga_switcheroo_client_fb_set
(struct pci_dev * pdev, struct fb_info * info)¶ set framebuffer of a given client
Parameters
struct pci_dev * pdev
- client pci device
struct fb_info * info
- framebuffer
Description
Set framebuffer of a given client. The console will be remapped to this on switching.
-
int
vga_switcheroo_lock_ddc
(struct pci_dev * pdev)¶ temporarily switch DDC lines to a given client
Parameters
struct pci_dev * pdev
- client pci device
Description
Temporarily switch DDC lines to the client identified by pdev
(but leave the outputs otherwise switched to where they are).
This allows the inactive client to probe EDID. The DDC lines must
afterwards be switched back by calling vga_switcheroo_unlock_ddc()
,
even if this function returns an error.
Return
Previous DDC owner on success or a negative int on error.
Specifically, -ENODEV
if no handler has registered or if the handler
does not support switching the DDC lines. Also, a negative value
returned by the handler is propagated back to the caller.
The return value has merely an informational purpose for any caller
which might be interested in it. It is acceptable to ignore the return
value and simply rely on the result of the subsequent EDID probe,
which will be NULL
if DDC switching failed.
-
int
vga_switcheroo_unlock_ddc
(struct pci_dev * pdev)¶ switch DDC lines back to previous owner
Parameters
struct pci_dev * pdev
- client pci device
Description
Switch DDC lines back to the previous owner after calling
vga_switcheroo_lock_ddc()
. This must be called even if
vga_switcheroo_lock_ddc()
returned an error.
Return
Previous DDC owner on success (i.e. the client identifier of pdev)
or a negative int on error.
Specifically, -ENODEV
if no handler has registered or if the handler
does not support switching the DDC lines. Also, a negative value
returned by the handler is propagated back to the caller.
Finally, invoking this function without calling vga_switcheroo_lock_ddc()
first is not allowed and will result in -EINVAL
.
-
int
vga_switcheroo_process_delayed_switch
(void)¶ helper for delayed switching
Parameters
void
- no arguments
Description
Process a delayed switch if one is pending. DRM drivers should call this from their ->lastclose callback.
Return
0 on success. -EINVAL if no delayed switch is pending, if the client has unregistered in the meantime or if there are other clients blocking the switch. If the actual switch fails, an error is reported and 0 is returned.
-
void
vga_switcheroo_set_dynamic_switch
(struct pci_dev * pdev, enum vga_switcheroo_state dynamic)¶ helper for driver power control
Parameters
struct pci_dev * pdev
- client pci device
enum vga_switcheroo_state dynamic
- new power state
Description
Helper for GPUs whose power state is controlled by the driver’s runtime pm. When the driver decides to power up or down, it notifies vga_switcheroo thereof using this helper so that it can (a) power the audio device on the GPU up or down, and (b) update its internal power state representation for the device.
-
int
vga_switcheroo_init_domain_pm_ops
(struct device * dev, struct dev_pm_domain * domain)¶ helper for driver power control
Parameters
struct device * dev
- vga client device
struct dev_pm_domain * domain
- power domain
Description
Helper for GPUs whose power state is controlled by the driver’s runtime pm. After the GPU has been suspended, the handler needs to be called to cut power to the GPU. Likewise it needs to reinstate power before the GPU can resume. To this end, this helper augments the suspend/resume functions by the requisite calls to the handler. It needs only be called on platforms where the power switch is separate to the device being powered down.
-
int
vga_switcheroo_init_domain_pm_optimus_hdmi_audio
(struct device * dev, struct dev_pm_domain * domain)¶ helper for driver power control
Parameters
struct device * dev
- audio client device
struct dev_pm_domain * domain
- power domain
Description
Helper for GPUs whose power state is controlled by the driver’s runtime pm. When the audio device resumes, the GPU needs to be woken. This helper augments the audio device’s resume function to do that.
Return
0 on success, -EINVAL if no power management operations are defined for this device.
Public structures¶
-
struct
vga_switcheroo_handler
¶ handler callbacks
Definition
struct vga_switcheroo_handler {
int (* init) (void);
int (* switchto) (enum vga_switcheroo_client_id id);
int (* switch_ddc) (enum vga_switcheroo_client_id id);
int (* power_state) (enum vga_switcheroo_client_id id,enum vga_switcheroo_state state);
enum vga_switcheroo_client_id (* get_client_id) (struct pci_dev *pdev);
};
Members
int (*)(void) init
- initialize handler. Optional. This gets called when vga_switcheroo is enabled, i.e. when two vga clients have registered. It allows the handler to perform some delayed initialization that depends on the existence of the vga clients. Currently only the radeon and amdgpu drivers use this. The return value is ignored
int (*)(enum vga_switcheroo_client_id id) switchto
- switch outputs to given client. Mandatory. For muxless machines this should be a no-op. Returning 0 denotes success, anything else failure (in which case the switch is aborted)
int (*)(enum vga_switcheroo_client_id id) switch_ddc
- switch DDC lines to given client. Optional. Should return the previous DDC owner on success or a negative int on failure
int (*)(enum vga_switcheroo_client_id id,enum vga_switcheroo_state state) power_state
- cut or reinstate power of given client. Optional. The return value is ignored
enum vga_switcheroo_client_id (*)(struct pci_dev *pdev) get_client_id
- determine if given pci device is integrated or discrete GPU. Mandatory
Description
Handler callbacks. The multiplexer itself. The switchto and get_client_id methods are mandatory, all others may be set to NULL.
-
struct
vga_switcheroo_client_ops
¶ client callbacks
Definition
struct vga_switcheroo_client_ops {
void (* set_gpu_state) (struct pci_dev *dev, enum vga_switcheroo_state);
void (* reprobe) (struct pci_dev *dev);
bool (* can_switch) (struct pci_dev *dev);
};
Members
void (*)(struct pci_dev *dev, enum vga_switcheroo_state) set_gpu_state
- do the equivalent of suspend/resume for the card. Mandatory. This should not cut power to the discrete GPU, which is the job of the handler
void (*)(struct pci_dev *dev) reprobe
- poll outputs. Optional. This gets called after waking the GPU and switching the outputs to it
bool (*)(struct pci_dev *dev) can_switch
- check if the device is in a position to switch now. Mandatory. The client should return false if a user space process has one of its device files open
Description
Client callbacks. A client can be either a GPU or an audio device on a GPU. The set_gpu_state and can_switch methods are mandatory, reprobe may be set to NULL. For audio clients, the reprobe member is bogus.
Public constants¶
-
enum
vga_switcheroo_handler_flags_t
¶ handler flags bitmask
Constants
VGA_SWITCHEROO_CAN_SWITCH_DDC
- whether the handler is able to switch the
DDC lines separately. This signals to clients that they should call
drm_get_edid_switcheroo()
to probe the EDID VGA_SWITCHEROO_NEEDS_EDP_CONFIG
- whether the handler is unable to switch the AUX channel separately. This signals to clients that the active GPU needs to train the link and communicate the link parameters to the inactive GPU (mediated by vga_switcheroo). The inactive GPU may then skip the AUX handshake and set up its output with these pre-calibrated values (DisplayPort specification v1.1a, section 2.5.3.3)
Description
Handler flags bitmask. Used by handlers to declare their capabilities upon registering with vga_switcheroo.
-
enum
vga_switcheroo_client_id
¶ client identifier
Constants
VGA_SWITCHEROO_UNKNOWN_ID
- initial identifier assigned to vga clients.
Determining the id requires the handler, so GPUs are given their
true id in a delayed fashion in
vga_switcheroo_enable()
VGA_SWITCHEROO_IGD
- integrated graphics device
VGA_SWITCHEROO_DIS
- discrete graphics device
VGA_SWITCHEROO_MAX_CLIENTS
- currently no more than two GPUs are supported
Description
Client identifier. Audio clients use the same identifier & 0x100.
-
enum
vga_switcheroo_state
¶ client power state
Constants
VGA_SWITCHEROO_OFF
- off
VGA_SWITCHEROO_ON
- on
VGA_SWITCHEROO_NOT_FOUND
- client has not registered with vga_switcheroo.
Only used in
vga_switcheroo_get_client_state()
which in turn is only called from hda_intel.c
Description
Client power state.
Private structures¶
-
struct
vgasr_priv
¶ vga_switcheroo private data
Definition
struct vgasr_priv {
bool active;
bool delayed_switch_active;
enum vga_switcheroo_client_id delayed_client_id;
struct dentry * debugfs_root;
struct dentry * switch_file;
int registered_clients;
struct list_head clients;
const struct vga_switcheroo_handler * handler;
enum vga_switcheroo_handler_flags_t handler_flags;
struct mutex mux_hw_lock;
int old_ddc_owner;
};
Members
bool active
- whether vga_switcheroo is enabled. Prerequisite is the registration of two GPUs and a handler
bool delayed_switch_active
- whether a delayed switch is pending
enum vga_switcheroo_client_id delayed_client_id
- client to which a delayed switch is pending
struct dentry * debugfs_root
- directory for vga_switcheroo debugfs interface
struct dentry * switch_file
- file for vga_switcheroo debugfs interface
int registered_clients
- number of registered GPUs (counting only vga clients, not audio clients)
struct list_head clients
- list of registered clients
const struct vga_switcheroo_handler * handler
- registered handler
enum vga_switcheroo_handler_flags_t handler_flags
- flags of registered handler
struct mutex mux_hw_lock
- protects mux state (in particular while DDC lines are temporarily switched)
int old_ddc_owner
- client to which DDC lines will be switched back on unlock
Description
vga_switcheroo private data. Currently only one vga_switcheroo instance per system is supported.
-
struct
vga_switcheroo_client
¶ registered client
Definition
struct vga_switcheroo_client {
struct pci_dev * pdev;
struct fb_info * fb_info;
enum vga_switcheroo_state pwr_state;
const struct vga_switcheroo_client_ops * ops;
enum vga_switcheroo_client_id id;
bool active;
bool driver_power_control;
struct list_head list;
};
Members
struct pci_dev * pdev
- client pci device
struct fb_info * fb_info
- framebuffer to which console is remapped on switching
enum vga_switcheroo_state pwr_state
- current power state
const struct vga_switcheroo_client_ops * ops
- client callbacks
enum vga_switcheroo_client_id id
- client identifier. Determining the id requires the handler,
so gpus are initially assigned VGA_SWITCHEROO_UNKNOWN_ID
and later given their true id in
vga_switcheroo_enable()
bool active
- whether the outputs are currently switched to this client
bool driver_power_control
- whether power state is controlled by the driver’s runtime pm. If true, writing ON and OFF to the vga_switcheroo debugfs interface is a no-op so as not to interfere with runtime pm
struct list_head list
- client list
Description
Registered client. A client can be either a GPU or an audio device on a GPU. For audio clients, the fb_info, active and driver_power_control members are bogus.
Handlers¶
apple-gmux Handler¶
1: | http://www.latticesemi.com/en/Products/FPGAandCPLD/LatticeXP2.aspx |
---|---|
2: | http://www.renesas.com/products/mpumcu/h8s/h8s2100/h8s2113/index.jsp |
gmux is a microcontroller built into the MacBook Pro to support dual GPUs: A {1}[Lattice XP2] on pre-retinas, a {2}[Renesas R4F2113] on retinas.
(The MacPro6,1 2013 also has a gmux, however it is unclear why since it has dual GPUs but no built-in display.)
gmux is connected to the LPC bus of the southbridge. Its I/O ports are accessed differently depending on the microcontroller: Driver functions to access a pre-retina gmux are infixed _pio_, those for a retina gmux are infixed _index_.
gmux is also connected to a GPIO pin of the southbridge and thereby is able to trigger an ACPI GPE. On the MBP5 2008/09 it’s GPIO pin 22 of the Nvidia MCP79, on all following generations it’s GPIO pin 6 of the Intel PCH. The GPE merely signals that an interrupt occurred, the actual type of event is identified by reading a gmux register.
Graphics mux¶
On pre-retinas, the LVDS outputs of both GPUs feed into gmux which muxes either of them to the panel. One of the tricks gmux has up its sleeve is to lengthen the blanking interval of its output during a switch to synchronize it with the GPU switched to. This allows for a flicker-free switch that is imperceptible by the user ({5}[US 8,687,007 B2]).
On retinas, muxing is no longer done by gmux itself, but by a separate chip which is controlled by gmux. The chip is triple sourced, it is either an {6}[NXP CBTL06142], {7}[TI HD3SS212] or {8}[Pericom PI3VDP12412]. The panel is driven with eDP instead of LVDS since the pixel clock required for retina resolution exceeds LVDS’ limits.
Pre-retinas are able to switch the panel’s DDC pins separately. This is handled by a {9}[TI SN74LV4066A] which is controlled by gmux. The inactive GPU can thus probe the panel’s EDID without switching over the entire panel. Retinas lack this functionality as the chips used for eDP muxing are incapable of switching the AUX channel separately (see the linked data sheets, Pericom would be capable but this is unused). However the retina panel has the NO_AUX_HANDSHAKE_LINK_TRAINING bit set in its DPCD, allowing the inactive GPU to skip the AUX handshake and set up the output with link parameters pre-calibrated by the active GPU.
The external DP port is only fully switchable on the first two unibody MacBook Pro generations, MBP5 2008/09 and MBP6 2010. This is done by an {6}[NXP CBTL06141] which is controlled by gmux. It’s the predecessor of the eDP mux on retinas, the difference being support for 2.7 versus 5.4 Gbit/s.
The following MacBook Pro generations replaced the external DP port with a combined DP/Thunderbolt port and lost the ability to switch it between GPUs, connecting it either to the discrete GPU or the Thunderbolt controller. Oddly enough, while the full port is no longer switchable, AUX and HPD are still switchable by way of an {10}[NXP CBTL03062] (on pre-retinas MBP8 2011 and MBP9 2012) or two {11}[TI TS3DS10224] (on retinas) under the control of gmux. Since the integrated GPU is missing the main link, external displays appear to it as phantoms which fail to link-train.
gmux receives the HPD signal of all display connectors and sends an interrupt on hotplug. On generations which cannot switch external ports, the discrete GPU can then be woken to drive the newly connected display. The ability to switch AUX on these generations could be used to improve reliability of hotplug detection by having the integrated GPU poll the ports while the discrete GPU is asleep, but currently we do not make use of this feature.
gmux’ initial switch state on bootup is user configurable via the EFI variable gpu-power-prefs-fa4ce28d-b62f-4c99-9cc3-6815686e30f9 (5th byte, 1 = IGD, 0 = DIS). Based on this setting, the EFI firmware tells gmux to switch the panel and the external DP connector and allocates a framebuffer for the selected GPU.
Power control¶
gmux is able to cut power to the discrete GPU. It automatically takes care of the correct sequence to tear down and bring up the power rails for core voltage, VRAM and PCIe.
Backlight control¶
3: | http://www.ti.com/lit/ds/symlink/lp8543.pdf |
---|---|
4: | http://www.ti.com/lit/ds/symlink/lp8545.pdf |
On single GPU MacBooks, the PWM signal for the backlight is generated by the GPU. On dual GPU MacBook Pros by contrast, either GPU may be suspended to conserve energy. Hence the PWM signal needs to be generated by a separate backlight driver which is controlled by gmux. The earliest generation MBP5 2008/09 uses a {3}[TI LP8543] backlight driver. All newer models use a {4}[TI LP8545].
Public functions¶
-
bool
apple_gmux_present
(void)¶ detect if gmux is built into the machine
Parameters
void
- no arguments
Description
Drivers may use this to activate quirks specific to dual GPU MacBook Pros and Mac Pros, e.g. for deferred probing, runtime pm and backlight.
Return
true
if gmux is present and the kernel was configured
with CONFIG_APPLE_GMUX, false
otherwise.