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
drm_crtc_funcs,
drm_encoder_funcs and
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.
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.
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.
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.
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 ->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.
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.
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.
Provides helper functions for creating a cma (contiguous memory allocator) backed framebuffer.
drm_fb_cma_create
is used in the drm_mode_config_funcs ->fb_create
callback function to create a cma backed framebuffer.
An fbdev framebuffer backed by cma is also available by calling
drm_fbdev_cma_init
. drm_fbdev_cma_fini
tears it down.
If the drm_framebuffer_funcs ->dirty callback is set, fb_deferred_io
will be set up automatically. dirty
is called by
drm_fb_helper_deferred_io
in process context (struct delayed_work).
Example fbdev deferred io code:
static int driver_fbdev_fb_dirty(struct drm_framebuffer *fb, struct drm_file *file_priv, unsigned flags, unsigned color, struct drm_clip_rect *clips, unsigned num_clips) { struct drm_gem_cma_object *cma = drm_fb_cma_get_gem_obj(fb, 0); ... push changes ... return 0; }
static struct drm_framebuffer_funcs driver_fbdev_fb_funcs = { .destroy = drm_fb_cma_destroy, .create_handle = drm_fb_cma_create_handle, .dirty = driver_fbdev_fb_dirty, };
static int driver_fbdev_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { return drm_fbdev_cma_create_with_funcs(helper, sizes, driver_fbdev_fb_funcs); }
static const struct drm_fb_helper_funcs driver_fb_helper_funcs = { .fb_probe = driver_fbdev_create, };
Initialize: fbdev = drm_fbdev_cma_init_with_funcs(dev, 16, dev->mode_config.num_crtc, dev->mode_config.num_connector, driver_fb_helper_funcs);
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 .transfer
implementation.
Both native and I2C-over-AUX transactions are supported.
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.
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.
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.
Utility functions to help manage rectangular areas for clipping, scaling, etc. calculations.
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.
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.
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 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.
disable
drm_bridge_funcs op for all bridges in the encoder chain.
post_disable
drm_bridge_funcs op for all bridges in the encoder chain.
pre_enable
drm_bridge_funcs op for all bridges in the encoder chain.
enable
drm_bridge_funcs op for all bridges in the encoder chain.
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.
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.
The DRM panel helpers allow drivers to register panel objects with a central registry and provide functions to retrieve those panels in display drivers.