Kernel Mode Setting (KMS)¶
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.
Overview¶
KMS Display Pipeline Overview
The basic object structure KMS presents to userspace is fairly simple.
Framebuffers (represented by struct drm_framebuffer
,
see Frame Buffer Abstraction) feed into planes. Planes are represented by
struct drm_plane
, see Plane Abstraction for more
details. One or more (or even no) planes feed their pixel data into a CRTC
(represented by struct drm_crtc
, see CRTC Abstraction)
for blending. The precise blending step is explained in more detail in Plane
Composition Properties and related chapters.
For the output routing the first step is encoders (represented by
struct drm_encoder
, see Encoder Abstraction). Those
are really just internal artifacts of the helper libraries used to implement KMS
drivers. Besides that they make it unecessarily more complicated for userspace
to figure out which connections between a CRTC and a connector are possible, and
what kind of cloning is supported, they serve no purpose in the userspace API.
Unfortunately encoders have been exposed to userspace, hence can’t remove them
at this point. Futhermore the exposed restrictions are often wrongly set by
drivers, and in many cases not powerful enough to express the real restrictions.
A CRTC can be connected to multiple encoders, and for an active CRTC there must
be at least one encoder.
The final, and real, endpoint in the display chain is the connector (represented
by struct drm_connector
, see Connector
Abstraction). Connectors can have different possible encoders, but the kernel
driver selects which encoder to use for each connector. The use case is DVI,
which could switch between an analog and a digital encoder. Encoders can also
drive multiple different connectors. There is exactly one active connector for
every active encoder.
Internally the output pipeline is a bit more complex and matches today’s hardware more closely:
KMS Output Pipeline
Internally two additional helper objects come into play. First, to be able to
share code for encoders (sometimes on the same SoC, sometimes off-chip) one or
more Framebuffer GEM Helper Reference (represented by struct drm_bridge
) can be linked to an encoder. This link is static and cannot be
changed, which means the cross-bar (if there is any) needs to be mapped between
the CRTC and any encoders. Often for drivers with bridges there’s no code left
at the encoder level. Atomic drivers can leave out all the encoder callbacks to
essentially only leave a dummy routing object behind, which is needed for
backwards compatibility since encoders are exposed to userspace.
The second object is for panels, represented by struct drm_panel
, see Panel Helper Reference. Panels do not have a fixed binding
point, but are generally linked to the driver private structure that embeds
struct drm_connector
.
Note that currently the bridge chaining and interactions with connectors and panels are still in-flux and not really fully sorted out yet.
KMS Core Structures and Functions¶
-
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);
const struct drm_format_info *(*get_format_info)(const struct drm_mode_fb_cmd2 *mode_cmd);
void (*output_poll_changed)(struct drm_device *dev);
enum drm_mode_status (*mode_valid)(struct drm_device *dev, const struct drm_display_mode *mode);
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
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()
.get_format_info
Allows a driver to return custom format information for special fb layouts (eg. ones with auxiliary compression control planes).
RETURNS:
The format information specific to the given fb metadata, or NULL if none is found.
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.
mode_valid
- Device specific validation of display modes. Can be used to reject modes that can never be supported. Only device wide constraints can be checked here. crtc/encoder/bridge/connector specific constraints should be checked in the .:c:func:mode_valid() hook for each specific object.
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 in this callback.
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.
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 each CRTC’sdrm_crtc_state.event
. See the documentation fordrm_crtc_state.event
for more details about the precise semantics of this event.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).
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.Subclassing of
drm_atomic_state
is deprecated in favour of usingdrm_private_state
anddrm_private_obj
.RETURNS:
A new
drm_atomic_state
on success or NULL on failure.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_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.Subclassing of
drm_atomic_state
is deprecated in favour of usingdrm_private_state
anddrm_private_obj
.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_release()
to release common resources.Subclassing of
drm_atomic_state
is deprecated in favour of usingdrm_private_state
anddrm_private_obj
.
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;
spinlock_t connector_list_lock;
int num_connector;
struct ida connector_ida;
struct list_head connector_list;
struct llist_head connector_free_list;
struct work_struct connector_free_work;
int num_encoder;
struct list_head encoder_list;
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, min_height;
int max_width, 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 *edid_property;
struct drm_property *dpms_property;
struct drm_property *path_property;
struct drm_property *tile_property;
struct drm_property *link_status_property;
struct drm_property *plane_type_property;
struct drm_property *prop_src_x;
struct drm_property *prop_src_y;
struct drm_property *prop_src_w;
struct drm_property *prop_src_h;
struct drm_property *prop_crtc_x;
struct drm_property *prop_crtc_y;
struct drm_property *prop_crtc_w;
struct drm_property *prop_crtc_h;
struct drm_property *prop_fb_id;
struct drm_property *prop_in_fence_fd;
struct drm_property *prop_out_fence_ptr;
struct drm_property *prop_crtc_id;
struct drm_property *prop_active;
struct drm_property *prop_mode_id;
struct drm_property *dvi_i_subconnector_property;
struct drm_property *dvi_i_select_subconnector_property;
struct drm_property *tv_subconnector_property;
struct drm_property *tv_select_subconnector_property;
struct drm_property *tv_mode_property;
struct drm_property *tv_left_margin_property;
struct drm_property *tv_right_margin_property;
struct drm_property *tv_top_margin_property;
struct drm_property *tv_bottom_margin_property;
struct drm_property *tv_brightness_property;
struct drm_property *tv_contrast_property;
struct drm_property *tv_flicker_reduction_property;
struct drm_property *tv_overscan_property;
struct drm_property *tv_saturation_property;
struct drm_property *tv_hue_property;
struct drm_property *scaling_mode_property;
struct drm_property *aspect_ratio_property;
struct drm_property *content_type_property;
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;
struct drm_property *suggested_x_property;
struct drm_property *suggested_y_property;
struct drm_property *non_desktop_property;
struct drm_property *panel_orientation_property;
struct drm_property *writeback_fb_id_property;
struct drm_property *writeback_pixel_formats_property;
struct drm_property *writeback_out_fence_ptr_property;
uint32_t preferred_depth, prefer_shadow;
bool async_page_flip;
bool allow_fb_modifiers;
bool normalize_zpos;
struct drm_property *modifiers_property;
uint32_t cursor_width, cursor_height;
struct drm_atomic_state *suspend_state;
const struct drm_mode_config_helper_funcs *helper_private;
};
Members
mutex
This is the big scary modeset BKL which protects everything that isn’t protect otherwise. Scope is unclear and fuzzy, try to remove anything from under it’s protection and move it into more well-scoped locks.
The one important thing this protects is the use of acquire_ctx.
connection_mutex
This protects connector state and the connector to encoder to CRTC routing chain.
For atomic drivers specifically this protects
drm_connector.state
.acquire_ctx
- Global implicit acquire context used by atomic drivers for legacy
IOCTLs. Deprecated, since implicit locking contexts make it
impossible to use driver-private
struct drm_modeset_lock
. Users of this must hold mutex. idr_mutex
- Mutex for KMS ID allocation and management. Protects both crtc_idr and tile_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.
tile_idr
- Use this idr for allocating new IDs for tiled sinks like use in some high-res DP MST screens.
fb_lock
- Mutex to protect fb the global fb_list and num_fb.
num_fb
- Number of entries on fb_list.
fb_list
- List of all
struct drm_framebuffer
. connector_list_lock
- Protects num_connector and connector_list and connector_free_list.
num_connector
- Number of connectors on this device. Protected by connector_list_lock.
connector_ida
- ID allocator for connector indices.
connector_list
- List of connector objects linked with
drm_connector.head
. Protected by connector_list_lock. Only usedrm_for_each_connector_iter()
andstruct drm_connector_list_iter
to walk this list. connector_free_list
- List of connector objects linked with
drm_connector.free_head
. Protected by connector_list_lock. Used bydrm_for_each_connector_iter()
andstruct drm_connector_list_iter
to savely free connectors using connector_free_work. connector_free_work
- Work to clean up connector_free_list.
num_encoder
- Number of encoders on this device. This is invariant over the lifetime of a device and hence doesn’t need any locks.
encoder_list
- List of encoder objects linked with
drm_encoder.head
. This is invariant over the lifetime of a device and hence doesn’t need any locks. num_total_plane
- Number of universal (i.e. with primary/curso) planes on this device. This is invariant over the lifetime of a device and hence doesn’t need any locks.
plane_list
- List of plane objects linked with
drm_plane.head
. This is invariant over the lifetime of a device and hence doesn’t need any locks. num_crtc
- Number of CRTCs on this device linked with
drm_crtc.head
. This is invariant over the lifetime of a device and hence doesn’t need any locks. crtc_list
- List of CRTC objects linked with
drm_crtc.head
. This is invariant over the lifetime of a device and hence doesn’t need any locks. property_list
- List of property type objects linked with
drm_property.head
. This is invariant over the lifetime of a device and hence doesn’t need any locks. min_width
- minimum fb pixel width on this device
min_height
- minimum fb pixel height on this device
max_width
- maximum fb pixel width on this device
max_height
- maximum fb pixel height on this device
funcs
- core driver provided mode setting functions
fb_base
- base address of the framebuffer
poll_enabled
- track polling support for this device
poll_running
- track polling status for this device
delayed_event
- track delayed poll uevent deliver for this device
output_poll_work
- delayed work for polling in process context
blob_lock
- Mutex for blob property allocation and management, protects
property_blob_list and
drm_file.blobs
. property_blob_list
- List of all the blob property objects linked with
drm_property_blob.head
. Protected by blob_lock. edid_property
- Default connector property to hold the EDID of the currently connected sink, if any.
dpms_property
- Default connector property to control the connector’s DPMS state.
path_property
- Default connector property to hold the DP MST path for the port.
tile_property
- Default connector property to store the tile position of a tiled screen, for sinks which need to be driven with multiple CRTCs.
link_status_property
- Default connector property for link status of a connector
plane_type_property
- Default plane property to differentiate CURSOR, PRIMARY and OVERLAY legacy uses of planes.
prop_src_x
- Default atomic plane property for the plane source
position in the connected
drm_framebuffer
. prop_src_y
- Default atomic plane property for the plane source
position in the connected
drm_framebuffer
. prop_src_w
- Default atomic plane property for the plane source
position in the connected
drm_framebuffer
. prop_src_h
- Default atomic plane property for the plane source
position in the connected
drm_framebuffer
. prop_crtc_x
- Default atomic plane property for the plane destination
position in the
drm_crtc
is is being shown on. prop_crtc_y
- Default atomic plane property for the plane destination
position in the
drm_crtc
is is being shown on. prop_crtc_w
- Default atomic plane property for the plane destination
position in the
drm_crtc
is is being shown on. prop_crtc_h
- Default atomic plane property for the plane destination
position in the
drm_crtc
is is being shown on. prop_fb_id
- Default atomic plane property to specify the
drm_framebuffer
. prop_in_fence_fd
- Sync File fd representing the incoming fences for a Plane.
prop_out_fence_ptr
- Sync File fd pointer representing the outgoing fences for a CRTC. Userspace should provide a pointer to a value of type s32, and then cast that pointer to u64.
prop_crtc_id
- Default atomic plane property to specify the
drm_crtc
. prop_active
- Default atomic CRTC property to control the active state, which is the simplified implementation for DPMS in atomic drivers.
prop_mode_id
- Default atomic CRTC property to set the mode for a CRTC. A 0 mode implies that the CRTC is entirely disabled - all connectors must be of and active must be set to disabled, too.
dvi_i_subconnector_property
- Optional DVI-I property to differentiate between analog or digital mode.
dvi_i_select_subconnector_property
- Optional DVI-I property to select between analog or digital mode.
tv_subconnector_property
- Optional TV property to differentiate between different TV connector types.
tv_select_subconnector_property
- Optional TV property to select between different TV connector types.
tv_mode_property
- Optional TV property to select the output TV mode.
tv_left_margin_property
- Optional TV property to set the left margin.
tv_right_margin_property
- Optional TV property to set the right margin.
tv_top_margin_property
- Optional TV property to set the right margin.
tv_bottom_margin_property
- Optional TV property to set the right margin.
tv_brightness_property
- Optional TV property to set the brightness.
tv_contrast_property
- Optional TV property to set the contrast.
tv_flicker_reduction_property
- Optional TV property to control the flicker reduction mode.
tv_overscan_property
- Optional TV property to control the overscan setting.
tv_saturation_property
- Optional TV property to set the saturation.
tv_hue_property
- Optional TV property to set the hue.
scaling_mode_property
- Optional connector property to control the upscaling, mostly used for built-in panels.
aspect_ratio_property
- Optional connector property to control the HDMI infoframe aspect ratio setting.
content_type_property
- Optional connector property to control the HDMI infoframe content type setting.
degamma_lut_property
- Optional CRTC property to set the LUT used to convert the framebuffer’s colors to linear gamma.
degamma_lut_size_property
- Optional CRTC property for the size of the degamma LUT as supported by the driver (read-only).
ctm_property
- Optional CRTC property to set the matrix used to convert colors after the lookup in the degamma LUT.
gamma_lut_property
- Optional CRTC property to set the LUT used to convert the colors, after the CTM matrix, to the gamma space of the connected screen.
gamma_lut_size_property
- Optional CRTC property for the size of the gamma LUT as supported by the driver (read-only).
suggested_x_property
- Optional connector property with a hint for the position of the output on the host’s screen.
suggested_y_property
- Optional connector property with a hint for the position of the output on the host’s screen.
non_desktop_property
- Optional connector property with a hint that device isn’t a standard display, and the console/desktop, should not be displayed on it.
panel_orientation_property
- Optional connector property indicating how the lcd-panel is mounted inside the casing (e.g. normal or upside-down).
writeback_fb_id_property
- Property for writeback connectors, storing
the ID of the output framebuffer.
See also:
drm_writeback_connector_init()
writeback_pixel_formats_property
- Property for writeback connectors,
storing an array of the supported pixel formats for the writeback
engine (read-only).
See also:
drm_writeback_connector_init()
writeback_out_fence_ptr_property
- Property for writeback connectors,
fd pointer representing the outgoing fences for a writeback
connector. Userspace should provide a pointer to a value of type s32,
and then cast that pointer to u64.
See also:
drm_writeback_connector_init()
preferred_depth
- preferred RBG pixel depth, used by fb helpers
prefer_shadow
- hint to userspace to prefer shadow-fb rendering
async_page_flip
- Does this device support async flips on the primary plane?
allow_fb_modifiers
- Whether the driver supports fb modifiers in the ADDFB2.1 ioctl call.
normalize_zpos
- If true the drm core will call
drm_atomic_normalize_zpos()
as part of atomic mode checking fromdrm_atomic_helper_check()
modifiers_property
- Plane property to list support modifier/format combination.
cursor_width
- hint to userspace for max cursor width
cursor_height
- hint to userspace for max cursor height
suspend_state
- Atomic state when suspended.
Set by
drm_mode_config_helper_suspend()
and cleared bydrm_mode_config_helper_resume()
. 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.
-
void
drm_mode_config_reset
(struct drm_device * dev)¶ call ->reset callbacks
Parameters
struct drm_device * dev
- drm device
Description
This functions calls all the crtc’s, encoder’s and connector’s ->reset callback. Drivers can use this in e.g. their driver load or resume code to reset hardware and software state.
-
void
drm_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
Modeset Base Object Abstraction¶
Mode Objects and Properties
The base structure for all KMS objects is struct drm_mode_object
. One of the base services it provides is tracking properties,
which are especially important for the atomic IOCTL (see Atomic Mode
Setting). The somewhat surprising part here is that properties are not
directly instantiated on each object, but free-standing mode objects themselves,
represented by struct drm_property
, which only specify
the type and value range of a property. Any given property can be attached
multiple times to different objects using drm_object_attach_property()
.
-
struct
drm_mode_object
¶ base structure for modeset objects
Definition
struct drm_mode_object {
uint32_t id;
uint32_t type;
struct drm_object_properties *properties;
struct kref refcount;
void (*free_cb)(struct kref *kref);
};
Members
id
- userspace visible identifier
type
- type of the object, one of DRM_MODE_OBJECT_*
properties
- properties attached to this object, including values
refcount
- reference count for objects which with dynamic lifetime
free_cb
- free function callback, only set for objects with dynamic lifetime
Description
Base structure for modeset objects visible to userspace. Objects can be
looked up using drm_mode_object_find()
. Besides basic uapi interface
properties like id and type it provides two services:
- It tracks attached properties and their values. This is used by
drm_crtc
,drm_plane
anddrm_connector
. Properties are attached by callingdrm_object_attach_property()
before the object is visible to userspace. - For objects with dynamic lifetimes (as indicated by a non-NULL free_cb) it
provides reference counting through
drm_mode_object_get()
anddrm_mode_object_put()
. This is used bydrm_framebuffer
,drm_connector
anddrm_property_blob
. These objects provide specialized reference counting wrappers.
-
struct
drm_object_properties
¶ property tracking for
drm_mode_object
Definition
struct drm_object_properties {
int count;
struct drm_property *properties[DRM_OBJECT_MAX_PROPERTY];
uint64_t values[DRM_OBJECT_MAX_PROPERTY];
};
Members
count
- number of valid properties, must be less than or equal to DRM_OBJECT_MAX_PROPERTY.
properties
Array of pointers to
drm_property
.NOTE: if we ever start dynamically destroying properties (ie. not at
drm_mode_config_cleanup()
time), then we’d have to do a better job of detaching property from mode objects to avoid dangling property pointers:values
Array to store the property values, matching properties. Do not read/write values directly, but use
drm_object_property_get_value()
anddrm_object_property_set_value()
.Note that atomic drivers do not store mutable properties in this array, but only the decoded values in the corresponding state structure. The decoding is done using the
drm_crtc.atomic_get_property
anddrm_crtc.atomic_set_property
hooks forstruct drm_crtc
. Forstruct drm_plane
the hooks aredrm_plane_funcs.atomic_get_property
anddrm_plane_funcs.atomic_set_property
. And forstruct drm_connector
the hooks aredrm_connector_funcs.atomic_get_property
anddrm_connector_funcs.atomic_set_property
.Hence atomic drivers should not use
drm_object_property_set_value()
anddrm_object_property_get_value()
on mutable objects, i.e. those without the DRM_MODE_PROP_IMMUTABLE flag set.
-
struct drm_mode_object *
drm_mode_object_find
(struct drm_device * dev, struct drm_file * file_priv, uint32_t id, uint32_t type)¶ look up a drm object with static lifetime
Parameters
struct drm_device * dev
- drm device
struct drm_file * file_priv
- drm file
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_put()
.
-
void
drm_mode_object_put
(struct drm_mode_object * obj)¶ release a mode object reference
Parameters
struct drm_mode_object * obj
- DRM mode object
Description
This function 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_get()
.
-
void
drm_mode_object_get
(struct drm_mode_object * obj)¶ acquire a mode object reference
Parameters
struct drm_mode_object * obj
- DRM mode object
Description
This function 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_put()
.
-
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 function 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.
Note that atomic drivers should not have any need to call this, the core will ensure consistency of values reported back to userspace through the appropriate ->atomic_get_property callback. Only legacy drivers should call this function to update the tracked value (after clamping and other restrictions have been applied).
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.
Atomic drivers should never call this function directly, the core will read out property values through the various ->atomic_get_property callbacks.
Return
Zero on success, error code on failure.
Atomic Mode Setting¶
Mode Objects and Properties
Atomic provides transactional modeset (including planes) updates, but a bit differently from the usual transactional approach of try-commit and rollback:
- Firstly, no hardware changes are allowed when the commit would fail. This allows us to implement the DRM_MODE_ATOMIC_TEST_ONLY mode, which allows userspace to explore whether certain configurations would work or not.
- This would still allow setting and rollback of just the software state, simplifying conversion of existing drivers. But auditing drivers for correctness of the atomic_check code becomes really hard with that: Rolling back changes in data structures all over the place is hard to get right.
- Lastly, for backwards compatibility and to support all use-cases, atomic updates need to be incremental and be able to execute in parallel. Hardware doesn’t always allow it, but where possible plane updates on different CRTCs should not interfere, and not get stalled due to output routing changing on different CRTCs.
Taken all together there’s two consequences for the atomic design:
- The overall state is split up into per-object state structures:
struct drm_plane_state
for planes,struct drm_crtc_state
for CRTCs andstruct drm_connector_state
for connectors. These are the only objects with userspace-visible and settable state. For internal state drivers can subclass these structures through embeddeding, or add entirely new state structures for their globally shared hardware functions. - An atomic update is assembled and validated as an entirely free-standing pile
of structures within the
drm_atomic_state
container. Driver private state structures are also tracked in the same structure; see the next chapter. Only when a state is committed is it applied to the driver and modeset objects. This way rolling back an update boils down to releasing memory and unreferencing objects like framebuffers.
Read on in this chapter, and also in Atomic Modeset Helper Functions Reference for more detailed coverage of specific topics.
Handling Driver Private State¶
Very often the DRM objects exposed to userspace in the atomic modeset api
(drm_connector
, drm_crtc
and drm_plane
) do not map neatly to the
underlying hardware. Especially for any kind of shared resources (e.g. shared
clocks, scaler units, bandwidth and fifo limits shared among a group of
planes or CRTCs, and so on) it makes sense to model these as independent
objects. Drivers then need to do similar state tracking and commit ordering for
such private (since not exposed to userpace) objects as the atomic core and
helpers already provide for connectors, planes and CRTCs.
To make this easier on drivers the atomic core provides some support to track
driver private state objects using struct drm_private_obj
, with the
associated state struct drm_private_state
.
Similar to userspace-exposed objects, private state structures can be
acquired by calling drm_atomic_get_private_obj_state()
. Since this function
does not take care of locking, drivers should wrap it for each type of
private state object they have with the required call to drm_modeset_lock()
for the corresponding drm_modeset_lock
.
All private state structures contained in a drm_atomic_state
update can be
iterated using for_each_oldnew_private_obj_in_state()
,
for_each_new_private_obj_in_state()
and for_each_old_private_obj_in_state()
.
Drivers are recommended to wrap these for each type of driver private state
object they have, filtering on drm_private_obj.funcs
using for_each_if()
, at
least if they want to iterate over all objects of a given type.
An earlier way to handle driver private state was by subclassing struct
drm_atomic_state
. But since that encourages non-standard ways to implement
the check/commit split atomic requires (by using e.g. “check and rollback or
commit instead” of “duplicate state, check, then either commit or release
duplicated state) it is deprecated in favour of using drm_private_state
.
Atomic Mode Setting Function Reference¶
-
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;
bool abort_completion;
};
Members
crtc
- DRM CRTC for this commit.
ref
- Reference count for this structure. Needed to allow blocking on completions without the risk of the completion disappearing meanwhile.
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.
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.
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. commit_entry
- Entry on the per-CRTC
drm_crtc.commit_list
. Protected by $drm_crtc.commit_lock. event
drm_pending_vblank_event
pointer to clean up private events.abort_completion
- A flag that’s set after drm_atomic_helper_setup_commit takes a second reference for the completion of $drm_crtc_state.event. It’s used by the free code to remove the second reference if commit fails.
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_private_state_funcs
¶ atomic state functions for private objects
Definition
struct drm_private_state_funcs {
struct drm_private_state *(*atomic_duplicate_state)(struct drm_private_obj *obj);
void (*atomic_destroy_state)(struct drm_private_obj *obj, struct drm_private_state *state);
};
Members
atomic_duplicate_state
Duplicate the current state of the private object and return it. It is an error to call this before obj->state has been initialized.
RETURNS:
Duplicated atomic state or NULL when obj->state is not initialized or allocation failed.
atomic_destroy_state
- Frees the private object state created with atomic_duplicate_state.
Description
These hooks are used by atomic helpers to create, swap and destroy states of
private objects. The structure itself is used as a vtable to identify the
associated private object type. Each private object type that needs to be
added to the atomic states is expected to have an implementation of these
hooks and pass a pointer to it’s drm_private_state_funcs struct to
drm_atomic_get_private_obj_state()
.
-
struct
drm_private_obj
¶ base struct for driver private atomic object
Definition
struct drm_private_obj {
struct drm_private_state *state;
const struct drm_private_state_funcs *funcs;
};
Members
state
- Current atomic state for this driver private object.
funcs
- Functions to manipulate the state of this driver private object, see
drm_private_state_funcs
.
Description
A driver private object is initialized by calling
drm_atomic_private_obj_init()
and cleaned up by calling
drm_atomic_private_obj_fini()
.
Currently only tracks the state update functions and the opaque driver
private state itself, but in the future might also track which
drm_modeset_lock
is required to duplicate and update this object’s state.
-
struct
drm_private_state
¶ base struct for driver private object state
Definition
struct drm_private_state {
struct drm_atomic_state *state;
};
Members
state
- backpointer to global drm_atomic_state
Description
Currently only contains a backpointer to the overall atomic update, but in
the future also might hold synchronization information similar to e.g.
drm_crtc.commit
.
-
struct
drm_atomic_state
¶ the global state object for atomic updates
Definition
struct drm_atomic_state {
struct kref ref;
struct drm_device *dev;
bool allow_modeset : 1;
bool legacy_cursor_update : 1;
bool async_update : 1;
struct __drm_planes_state *planes;
struct __drm_crtcs_state *crtcs;
int num_connector;
struct __drm_connnectors_state *connectors;
int num_private_objs;
struct __drm_private_objs_state *private_objs;
struct drm_modeset_acquire_ctx *acquire_ctx;
struct drm_crtc_commit *fake_commit;
struct work_struct commit_work;
};
Members
ref
- count of all references to this state (will not be freed until zero)
dev
- parent DRM device
allow_modeset
- allow full modeset
legacy_cursor_update
- hint to enforce legacy cursor IOCTL semantics
async_update
- hint for asynchronous plane update
planes
- pointer to array of structures with per-plane data
crtcs
- pointer to array of CRTC pointers
num_connector
- size of the connectors and connector_states arrays
connectors
- pointer to array of structures with per-connector data
num_private_objs
- size of the private_objs array
private_objs
- pointer to array of private object pointers
acquire_ctx
- acquire context for this atomic modeset state update
fake_commit
Used for signaling unbound planes/connectors. When a connector or plane is not bound to any CRTC, it’s still important to preserve linearity to prevent the atomic states from being freed to early.
This commit (if set) is not bound to any crtc, but will be completed when
drm_atomic_helper_commit_hw_done()
is called.commit_work
- Work item which can be used by the driver or helpers to execute the commit without blocking.
Description
States are added to an atomic update by calling drm_atomic_get_crtc_state()
,
drm_atomic_get_plane_state()
, drm_atomic_get_connector_state()
, or for
private state structures, drm_atomic_get_private_obj_state()
.
-
struct drm_crtc_commit *
drm_crtc_commit_get
(struct drm_crtc_commit * commit)¶ acquire a reference to the CRTC commit
Parameters
struct drm_crtc_commit * commit
- CRTC commit
Description
Increases the reference of commit.
Return
The pointer to commit, with reference increased.
-
void
drm_crtc_commit_put
(struct drm_crtc_commit * commit)¶ release a reference to the CRTC commmit
Parameters
struct drm_crtc_commit * commit
- CRTC commit
Description
This releases a reference to commit which is freed after removing the final reference. No locking required and callable from any context.
-
struct drm_atomic_state *
drm_atomic_state_get
(struct drm_atomic_state * state)¶ acquire a reference to the atomic state
Parameters
struct drm_atomic_state * state
- The atomic state
Description
Returns a new reference to the state
-
void
drm_atomic_state_put
(struct drm_atomic_state * state)¶ release a reference to the atomic state
Parameters
struct drm_atomic_state * state
- The atomic state
Description
This releases a reference to state which is freed after removing the final reference. No locking required and callable from any context.
-
struct drm_crtc_state *
drm_atomic_get_existing_crtc_state
(struct drm_atomic_state * state, struct drm_crtc * crtc)¶ get crtc state, if it exists
Parameters
struct drm_atomic_state * state
- global atomic state object
struct drm_crtc * crtc
- crtc to grab
Description
This function returns the crtc state for the given crtc, or NULL if the crtc is not part of the global atomic state.
This function is deprecated, drm_atomic_get_old_crtc_state or drm_atomic_get_new_crtc_state should be used instead.
-
struct drm_crtc_state *
drm_atomic_get_old_crtc_state
(struct drm_atomic_state * state, struct drm_crtc * crtc)¶ get old crtc state, if it exists
Parameters
struct drm_atomic_state * state
- global atomic state object
struct drm_crtc * crtc
- crtc to grab
Description
This function returns the old crtc state for the given crtc, or NULL if the crtc is not part of the global atomic state.
-
struct drm_crtc_state *
drm_atomic_get_new_crtc_state
(struct drm_atomic_state * state, struct drm_crtc * crtc)¶ get new crtc state, if it exists
Parameters
struct drm_atomic_state * state
- global atomic state object
struct drm_crtc * crtc
- crtc to grab
Description
This function returns the new crtc state for the given crtc, or NULL if the crtc is not part of the global atomic state.
-
struct drm_plane_state *
drm_atomic_get_existing_plane_state
(struct drm_atomic_state * state, struct drm_plane * plane)¶ get plane state, if it exists
Parameters
struct drm_atomic_state * state
- global atomic state object
struct drm_plane * plane
- plane to grab
Description
This function returns the plane state for the given plane, or NULL if the plane is not part of the global atomic state.
This function is deprecated, drm_atomic_get_old_plane_state or drm_atomic_get_new_plane_state should be used instead.
-
struct drm_plane_state *
drm_atomic_get_old_plane_state
(struct drm_atomic_state * state, struct drm_plane * plane)¶ get plane state, if it exists
Parameters
struct drm_atomic_state * state
- global atomic state object
struct drm_plane * plane
- plane to grab
Description
This function returns the old plane state for the given plane, or NULL if the plane is not part of the global atomic state.
-
struct drm_plane_state *
drm_atomic_get_new_plane_state
(struct drm_atomic_state * state, struct drm_plane * plane)¶ get plane state, if it exists
Parameters
struct drm_atomic_state * state
- global atomic state object
struct drm_plane * plane
- plane to grab
Description
This function returns the new plane state for the given plane, or NULL if the plane is not part of the global atomic state.
-
struct drm_connector_state *
drm_atomic_get_existing_connector_state
(struct drm_atomic_state * state, struct drm_connector * connector)¶ get connector state, if it exists
Parameters
struct drm_atomic_state * state
- global atomic state object
struct drm_connector * connector
- connector to grab
Description
This function returns the connector state for the given connector, or NULL if the connector is not part of the global atomic state.
This function is deprecated, drm_atomic_get_old_connector_state or drm_atomic_get_new_connector_state should be used instead.
-
struct drm_connector_state *
drm_atomic_get_old_connector_state
(struct drm_atomic_state * state, struct drm_connector * connector)¶ get connector state, if it exists
Parameters
struct drm_atomic_state * state
- global atomic state object
struct drm_connector * connector
- connector to grab
Description
This function returns the old connector state for the given connector, or NULL if the connector is not part of the global atomic state.
-
struct drm_connector_state *
drm_atomic_get_new_connector_state
(struct drm_atomic_state * state, struct drm_connector * connector)¶ get connector state, if it exists
Parameters
struct drm_atomic_state * state
- global atomic state object
struct drm_connector * connector
- connector to grab
Description
This function returns the new connector state for the given connector, or NULL if the connector is not part of the global atomic state.
-
const struct drm_plane_state *
__drm_atomic_get_current_plane_state
(struct drm_atomic_state * state, struct drm_plane * plane)¶ get current plane state
Parameters
struct drm_atomic_state * state
- global atomic state object
struct drm_plane * plane
- plane to grab
Description
This function returns the plane state for the given plane, either from state, or if the plane isn’t part of the atomic state update, from plane. This is useful in atomic check callbacks, when drivers need to peek at, but not change, state of other planes, since it avoids threading an error code back up the call chain.
WARNING:
Note that this function is in general unsafe since it doesn’t check for the required locking for access state structures. Drivers must ensure that it is safe to access the returned state structure through other means. One common example is when planes are fixed to a single CRTC, and the driver knows that the CRTC lock is held already. In that case holding the CRTC lock gives a read-lock on all planes connected to that CRTC. But if planes can be reassigned things get more tricky. In that case it’s better to use drm_atomic_get_plane_state and wire up full error handling.
Return
Read-only pointer to the current plane state.
-
for_each_oldnew_connector_in_state
(__state, connector, old_connector_state, new_connector_state, __i)¶ iterate over all connectors in an atomic update
Parameters
__state
struct drm_atomic_state
pointerconnector
struct drm_connector
iteration cursorold_connector_state
struct drm_connector_state
iteration cursor for the old statenew_connector_state
struct drm_connector_state
iteration cursor for the new state__i
- int iteration cursor, for macro-internal use
Description
This iterates over all connectors in an atomic update, tracking both old and new state. This is useful in places where the state delta needs to be considered, for example in atomic check functions.
-
for_each_old_connector_in_state
(__state, connector, old_connector_state, __i)¶ iterate over all connectors in an atomic update
Parameters
__state
struct drm_atomic_state
pointerconnector
struct drm_connector
iteration cursorold_connector_state
struct drm_connector_state
iteration cursor for the old state__i
- int iteration cursor, for macro-internal use
Description
This iterates over all connectors in an atomic update, tracking only the old state. This is useful in disable functions, where we need the old state the hardware is still in.
-
for_each_new_connector_in_state
(__state, connector, new_connector_state, __i)¶ iterate over all connectors in an atomic update
Parameters
__state
struct drm_atomic_state
pointerconnector
struct drm_connector
iteration cursornew_connector_state
struct drm_connector_state
iteration cursor for the new state__i
- int iteration cursor, for macro-internal use
Description
This iterates over all connectors in an atomic update, tracking only the new state. This is useful in enable functions, where we need the new state the hardware should be in when the atomic commit operation has completed.
-
for_each_oldnew_crtc_in_state
(__state, crtc, old_crtc_state, new_crtc_state, __i)¶ iterate over all CRTCs in an atomic update
Parameters
__state
struct drm_atomic_state
pointercrtc
struct drm_crtc
iteration cursorold_crtc_state
struct drm_crtc_state
iteration cursor for the old statenew_crtc_state
struct drm_crtc_state
iteration cursor for the new state__i
- int iteration cursor, for macro-internal use
Description
This iterates over all CRTCs in an atomic update, tracking both old and new state. This is useful in places where the state delta needs to be considered, for example in atomic check functions.
-
for_each_old_crtc_in_state
(__state, crtc, old_crtc_state, __i)¶ iterate over all CRTCs in an atomic update
Parameters
__state
struct drm_atomic_state
pointercrtc
struct drm_crtc
iteration cursorold_crtc_state
struct drm_crtc_state
iteration cursor for the old state__i
- int iteration cursor, for macro-internal use
Description
This iterates over all CRTCs in an atomic update, tracking only the old state. This is useful in disable functions, where we need the old state the hardware is still in.
-
for_each_new_crtc_in_state
(__state, crtc, new_crtc_state, __i)¶ iterate over all CRTCs in an atomic update
Parameters
__state
struct drm_atomic_state
pointercrtc
struct drm_crtc
iteration cursornew_crtc_state
struct drm_crtc_state
iteration cursor for the new state__i
- int iteration cursor, for macro-internal use
Description
This iterates over all CRTCs in an atomic update, tracking only the new state. This is useful in enable functions, where we need the new state the hardware should be in when the atomic commit operation has completed.
-
for_each_oldnew_plane_in_state
(__state, plane, old_plane_state, new_plane_state, __i)¶ iterate over all planes in an atomic update
Parameters
__state
struct drm_atomic_state
pointerplane
struct drm_plane
iteration cursorold_plane_state
struct drm_plane_state
iteration cursor for the old statenew_plane_state
struct drm_plane_state
iteration cursor for the new state__i
- int iteration cursor, for macro-internal use
Description
This iterates over all planes in an atomic update, tracking both old and new state. This is useful in places where the state delta needs to be considered, for example in atomic check functions.
-
for_each_oldnew_plane_in_state_reverse
(__state, plane, old_plane_state, new_plane_state, __i)¶ iterate over all planes in an atomic update in reverse order
Parameters
__state
struct drm_atomic_state
pointerplane
struct drm_plane
iteration cursorold_plane_state
struct drm_plane_state
iteration cursor for the old statenew_plane_state
struct drm_plane_state
iteration cursor for the new state__i
- int iteration cursor, for macro-internal use
Description
This iterates over all planes in an atomic update in reverse order, tracking both old and new state. This is useful in places where the state delta needs to be considered, for example in atomic check functions.
-
for_each_old_plane_in_state
(__state, plane, old_plane_state, __i)¶ iterate over all planes in an atomic update
Parameters
__state
struct drm_atomic_state
pointerplane
struct drm_plane
iteration cursorold_plane_state
struct drm_plane_state
iteration cursor for the old state__i
- int iteration cursor, for macro-internal use
Description
This iterates over all planes in an atomic update, tracking only the old state. This is useful in disable functions, where we need the old state the hardware is still in.
-
for_each_new_plane_in_state
(__state, plane, new_plane_state, __i)¶ iterate over all planes in an atomic update
Parameters
__state
struct drm_atomic_state
pointerplane
struct drm_plane
iteration cursornew_plane_state
struct drm_plane_state
iteration cursor for the new state__i
- int iteration cursor, for macro-internal use
Description
This iterates over all planes in an atomic update, tracking only the new state. This is useful in enable functions, where we need the new state the hardware should be in when the atomic commit operation has completed.
-
for_each_oldnew_private_obj_in_state
(__state, obj, old_obj_state, new_obj_state, __i)¶ iterate over all private objects in an atomic update
Parameters
__state
struct drm_atomic_state
pointerobj
struct drm_private_obj
iteration cursorold_obj_state
struct drm_private_state
iteration cursor for the old statenew_obj_state
struct drm_private_state
iteration cursor for the new state__i
- int iteration cursor, for macro-internal use
Description
This iterates over all private objects in an atomic update, tracking both old and new state. This is useful in places where the state delta needs to be considered, for example in atomic check functions.
-
for_each_old_private_obj_in_state
(__state, obj, old_obj_state, __i)¶ iterate over all private objects in an atomic update
Parameters
__state
struct drm_atomic_state
pointerobj
struct drm_private_obj
iteration cursorold_obj_state
struct drm_private_state
iteration cursor for the old state__i
- int iteration cursor, for macro-internal use
Description
This iterates over all private objects in an atomic update, tracking only the old state. This is useful in disable functions, where we need the old state the hardware is still in.
-
for_each_new_private_obj_in_state
(__state, obj, new_obj_state, __i)¶ iterate over all private objects in an atomic update
Parameters
__state
struct drm_atomic_state
pointerobj
struct drm_private_obj
iteration cursornew_obj_state
struct drm_private_state
iteration cursor for the new state__i
- int iteration cursor, for macro-internal use
Description
This iterates over all private objects in an atomic update, tracking only the new state. This is useful in enable functions, where we need the new state the hardware should be in when the atomic commit operation has completed.
-
bool
drm_atomic_crtc_needs_modeset
(const struct drm_crtc_state * state)¶ compute combined modeset need
Parameters
const struct drm_crtc_state * state
drm_crtc_state
for the CRTC
Description
To give drivers flexibility struct drm_crtc_state
has 3 booleans to track
whether the state CRTC changed enough to need a full modeset cycle:
mode_changed, active_changed and connectors_changed. This helper simply
combines these three to compute the overall need for a modeset for state.
The atomic helper code sets these booleans, but drivers can and should change them appropriately to accurately represent whether a modeset is really needed. In general, drivers should avoid full modesets whenever possible.
For example if the CRTC mode has changed, and the hardware is able to enact
the requested mode change without going through a full modeset, the driver
should clear mode_changed in its drm_mode_config_funcs.atomic_check
implementation.
-
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 should only be used by drivers which are still subclassing
drm_atomic_state
and haven’t switched to drm_private_state
yet.
-
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 should only be used by drivers which are still subclassing
drm_atomic_state
and haven’t switched to drm_private_state
yet.
-
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 should only be used by drivers which are still subclassing
drm_atomic_state
and haven’t switched to drm_private_state
yet.
-
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
drm_mode_config_funcs.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 kref * ref)¶ free all memory for an atomic state
Parameters
struct kref * ref
- This 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, const struct drm_display_mode * mode)¶ set mode for CRTC
Parameters
struct drm_crtc_state * state
- the CRTC whose incoming state to update
const 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 and update the enable property.
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
This function handles generic/core properties and calls out to driver’s
drm_crtc_funcs.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.
-
void
drm_atomic_private_obj_init
(struct drm_private_obj * obj, struct drm_private_state * state, const struct drm_private_state_funcs * funcs)¶ initialize private object
Parameters
struct drm_private_obj * obj
- private object
struct drm_private_state * state
- initial private object state
const struct drm_private_state_funcs * funcs
- pointer to the struct of function pointers that identify the object type
Description
Initialize the private object, which can be embedded into any driver private object that needs its own atomic state.
-
void
drm_atomic_private_obj_fini
(struct drm_private_obj * obj)¶ finalize private object
Parameters
struct drm_private_obj * obj
- private object
Description
Finalize the private object.
-
struct drm_private_state *
drm_atomic_get_private_obj_state
(struct drm_atomic_state * state, struct drm_private_obj * obj)¶ get private object state
Parameters
struct drm_atomic_state * state
- global atomic state
struct drm_private_obj * obj
- private object to get the state for
Description
This function returns the private object state for the given private object, allocating the state if needed. It does not grab any locks as the caller is expected to care of any required locking.
Return
Either the allocated state or the error code encoded into a pointer.
-
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_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.
-
void
drm_atomic_set_fence_for_plane
(struct drm_plane_state * plane_state, struct dma_fence * fence)¶ set fence for plane
Parameters
struct drm_plane_state * plane_state
- atomic state object for the plane
struct dma_fence * fence
- dma_fence to use for the plane
Description
Helper to setup the plane_state fence in case it is not set yet. By using this drivers doesn’t need to worry if the user choose implicit or explicit fencing.
This function will not set the fence to the state if it was set
via explicit fencing interfaces on the atomic ioctl. In that case it will
drop the reference to the fence as we are not storing it anywhere.
Otherwise, if drm_plane_state.fence
is not set this function we just set it
with the received implicit fence. In both cases this function consumes a
reference for fence.
This way explicit fencing can be used to overrule implicit fencing, which is important to make explicit fencing use-cases work: One example is using one buffer for 2 screens with different refresh rates. Implicit fencing will clamp rendering to the refresh rate of the slower screen, whereas explicit fence allows 2 independent render and display loops on a single buffer. If a driver allows obeys both implicit and explicit fences for plane updates, then it will break all the benefits of explicit fencing.
-
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_set_writeback_fb_for_connector
(struct drm_connector_state * conn_state, struct drm_framebuffer * fb)¶ set writeback framebuffer
Parameters
struct drm_connector_state * conn_state
- atomic state object for the connector
struct drm_framebuffer * fb
- fb to use for the connector
Description
This is used to set the framebuffer for a writeback connector, which outputs to a buffer instead of an actual physical connector. Changing the assigned framebuffer 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.
Note
The only way conn_state can already have an fb set is if the commit sets the property more than once.
See also: drm_writeback_connector_init()
Return
0 on success
-
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.
-
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.
This function will take its own reference on state.
Callers should always release their reference with drm_atomic_state_put()
.
Return
0 on success, negative error code on failure.
-
int
drm_atomic_nonblocking_commit
(struct drm_atomic_state * state)¶ atomic nonblocking 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.
This function will take its own reference on state.
Callers should always release their reference with drm_atomic_state_put()
.
Return
0 on success, negative error code on failure.
-
void
drm_state_dump
(struct drm_device * dev, struct drm_printer * p)¶ dump entire device atomic state
Parameters
struct drm_device * dev
- the drm device
struct drm_printer * p
- where to print the state to
Description
Just for debugging. Drivers might want an option to dump state to dmesg in case of error irq’s. (Hint, you probably want to ratelimit this!)
The caller must drm_modeset_lock_all()
, or if this is called
from error irq handler, it should not be enabled by default.
(Ie. if you are debugging errors you might not care that this
is racey. But calling this without all modeset locks held is
not inherently safe.)
-
int
drm_atomic_replace_property_blob_from_id
(struct drm_device * dev, struct drm_property_blob ** blob, uint64_t blob_id, ssize_t expected_size, ssize_t expected_elem_size, bool * replaced)¶ lookup the new blob and replace the old one with it
Parameters
struct drm_device * dev
- DRM device
struct drm_property_blob ** blob
- a pointer to the member blob to be replaced
uint64_t blob_id
- ID of the new blob
ssize_t expected_size
- total expected size of the blob data (in bytes)
ssize_t expected_elem_size
- expected element size of the blob data (in bytes)
bool * replaced
- did the blob get replaced?
Description
Replace blob with another blob with the ID blob_id. If blob_id is zero blob becomes NULL.
If expected_size is positive the new blob length is expected to be equal to expected_size bytes. If expected_elem_size is positive the new blob length is expected to be a multiple of expected_elem_size bytes. Otherwise an error is returned.
replaced will indicate to the caller whether the blob was replaced or not. If the old and new blobs were in fact the same blob replaced will be false otherwise it will be true.
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
drm_crtc_funcs.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_connector_check
(struct drm_connector * connector, struct drm_connector_state * state)¶ check connector state
Parameters
struct drm_connector * connector
- connector to check
struct drm_connector_state * state
- connector state to check
Description
Provides core sanity checks for connector state.
Return
Zero on success, error code on failure
-
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
This function handles generic/core properties and calls out to driver’s
drm_plane_funcs.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_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
drm_plane_funcs.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_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
This function handles generic/core properties and calls out to driver’s
drm_connector_funcs.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_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
drm_connector_funcs.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
CRTC Abstraction¶
A CRTC represents the overall display pipeline. It receives pixel data from
drm_plane
and blends them together. The drm_display_mode
is also attached
to the CRTC, specifying display timings. On the output side the data is fed
to one or more drm_encoder
, which are then each connected to one
drm_connector
.
To create a CRTC, a KMS drivers allocates and zeroes an instances of
struct drm_crtc
(possibly as part of a larger structure) and registers it
with a call to drm_crtc_init_with_planes()
.
The CRTC is also the entry point for legacy modeset operations, see
drm_crtc_funcs.set_config
, legacy plane operations, see
drm_crtc_funcs.page_flip
and drm_crtc_funcs.cursor_set2
, and other legacy
operations like drm_crtc_funcs.gamma_set
. For atomic drivers all these
features are controlled through drm_property
and
drm_mode_config_funcs.atomic_check
and drm_mode_config_funcs.atomic_check
.
CRTC Functions Reference¶
-
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 zpos_changed : 1;
bool color_mgmt_changed : 1;
bool no_vblank : 1;
u32 plane_mask;
u32 connector_mask;
u32 encoder_mask;
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;
u32 target_vblank;
u32 pageflip_flags;
struct drm_pending_vblank_event *event;
struct drm_crtc_commit *commit;
struct drm_atomic_state *state;
};
Members
crtc
- backpointer to the CRTC
enable
- Whether the CRTC should be enabled, gates all other state. This controls reservations of shared resources. Actual hardware state is controlled by active.
active
Whether the CRTC is actively displaying (used for DPMS). Implies that enable is set. The driver must not release any shared resources if active is set to false but enable still true, because userspace expects that a DPMS ON always succeeds.
Hence drivers must not consult active in their various
drm_mode_config_funcs.atomic_check
callback to reject an atomic commit. They can consult it to aid in the computation of derived hardware state, since even in the DPMS OFF state the display hardware should be as much powered down as when the CRTC is completely disabled through setting enable to false.planes_changed
- Planes on this crtc are updated. Used by the atomic helpers and drivers to steer the atomic commit control flow.
mode_changed
mode or enable has been changed. Used by the atomic helpers and drivers to steer the atomic commit control flow. See also
drm_atomic_crtc_needs_modeset()
.Drivers are supposed to set this for any CRTC state changes that require a full modeset. They can also reset it to false if e.g. a mode change can be done without a full modeset by only changing scaler settings.
active_changed
- active has been toggled. Used by the atomic
helpers and drivers to steer the atomic commit control flow. See also
drm_atomic_crtc_needs_modeset()
. connectors_changed
Connectors to this crtc have been updated, either in their state or routing. Used by the atomic helpers and drivers to steer the atomic commit control flow. See also
drm_atomic_crtc_needs_modeset()
.Drivers are supposed to set this as-needed from their own atomic check code, e.g. from
drm_encoder_helper_funcs.atomic_check
zpos_changed
- zpos values of planes on this crtc have been updated. Used by the atomic helpers and drivers to steer the atomic commit control flow.
color_mgmt_changed
- Color management properties have changed (gamma_lut, degamma_lut or ctm). Used by the atomic helpers and drivers to steer the atomic commit control flow.
no_vblank
Reflects the ability of a CRTC to send VBLANK events. This state usually depends on the pipeline configuration, and the main usuage is CRTCs feeding a writeback connector operating in oneshot mode. In this case the VBLANK event is only generated when a job is queued to the writeback connector, and we want the core to fake VBLANK events when this part of the pipeline hasn’t changed but others had or when the CRTC and connectors are being disabled.
__drm_atomic_helper_crtc_duplicate_state()
will not reset the value from the current state, the CRTC driver is then responsible for updating this field when needed.Note that the combination of
drm_crtc_state.event
== NULL anddrm_crtc_state.no_blank
== true is valid and usually used when the writeback connector attached to the CRTC has a new job queued. In this case the driver will send the VBLANK event on its own when the writeback job is complete.plane_mask
- Bitmask of drm_plane_mask(plane) of planes attached to this CRTC.
connector_mask
- Bitmask of drm_connector_mask(connector) of connectors attached to this CRTC.
encoder_mask
- Bitmask of drm_encoder_mask(encoder) of encoders attached to this CRTC.
adjusted_mode
Internal display timings which can be used by the driver to handle differences between the mode requested by userspace in mode and what is actually programmed into the hardware.
For drivers using
drm_bridge
, this stores hardware display timings used between the CRTC and the first bridge. For other drivers, the meaning of the adjusted_mode field is purely driver implementation defined information, and will usually be used to store the hardware display timings used between the CRTC and encoder blocks.mode
Display timings requested by userspace. The driver should try to match the refresh rate as close as possible (but note that it’s undefined what exactly is close enough, e.g. some of the HDMI modes only differ in less than 1% of the refresh rate). The active width and height as observed by userspace for positioning planes must match exactly.
For external connectors where the sink isn’t fixed (like with a built-in panel), this mode here should match the physical mode on the wire to the last details (i.e. including sync polarities and everything).
mode_blob
drm_property_blob
for mode, for exposing the mode to atomic userspace.degamma_lut
- Lookup table for converting framebuffer pixel data before apply the
color conversion matrix ctm. See
drm_crtc_enable_color_mgmt()
. The blob (if not NULL) is an array ofstruct drm_color_lut
. ctm
- Color transformation matrix. See
drm_crtc_enable_color_mgmt()
. The blob (if not NULL) is astruct drm_color_ctm
. gamma_lut
- Lookup table for converting pixel data after the color conversion
matrix ctm. See
drm_crtc_enable_color_mgmt()
. The blob (if not NULL) is an array ofstruct drm_color_lut
. target_vblank
- Target vertical blank period when a page flip should take effect.
pageflip_flags
- DRM_MODE_PAGE_FLIP_* flags, as passed to the page flip ioctl. Zero in any other case.
event
Optional pointer to a DRM event to signal upon completion of the state update. The driver must send out the event when the atomic commit operation completes. There are two cases:
- The event is for a CRTC which is being disabled through this
atomic commit. In that case the event can be send out any time
after the hardware has stopped scanning out the current
framebuffers. It should contain the timestamp and counter for the
last vblank before the display pipeline was shut off. The simplest
way to achieve that is calling
drm_crtc_send_vblank_event()
somewhen afterdrm_crtc_vblank_off()
has been called. - For a CRTC which is enabled at the end of the commit (even when it undergoes an full modeset) the vblank timestamp and counter must be for the vblank right before the first frame that scans out the new set of buffers. Again the event can only be sent out after the hardware has stopped scanning out the old buffers.
- Events for disabled CRTCs are not allowed, and drivers can ignore that case.
This can be handled by the
drm_crtc_send_vblank_event()
function, which the driver should call on the provided event upon completion of the 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.For hardware which supports some means to synchronize vblank interrupt delivery with committing display state there’s also
drm_crtc_arm_vblank_event()
. See the documentation of that function for a detailed discussion of the constraints it needs to be used safely.If the device can’t notify of flip completion in a race-free way at all, then the event should be armed just after the page flip is committed. In the worst case the driver will send the event to userspace one frame too late. This doesn’t allow for a real atomic update, but it should avoid tearing.
- The event is for a CRTC which is being disabled through this
atomic commit. In that case the event can be send out any time
after the hardware has stopped scanning out the current
framebuffers. It should contain the timestamp and counter for the
last vblank before the display pipeline was shut off. The simplest
way to achieve that is calling
commit
- This tracks how the commit for this update proceeds through the various phases. This is never cleared, except when we destroy the state, so that subsequent commits can synchronize with previous ones.
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 drm_mode_config_funcs.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.
The three booleans active_changed, connectors_changed and mode_changed are
intended to indicate whether a full modeset is needed, rather than strictly
describing what has changed in a commit. See also:
drm_atomic_crtc_needs_modeset()
WARNING: Transitional helpers (like drm_helper_crtc_mode_set()
or
drm_helper_crtc_mode_set_base()
) do not maintain many of the derived control
state like plane_mask so drivers not converted over to atomic helpers should
not rely on these being accurate!
-
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, struct drm_modeset_acquire_ctx *ctx);
void (*destroy)(struct drm_crtc *crtc);
int (*set_config)(struct drm_mode_set *set, struct drm_modeset_acquire_ctx *ctx);
int (*page_flip)(struct drm_crtc *crtc,struct drm_framebuffer *fb,struct drm_pending_vblank_event *event,uint32_t flags, struct drm_modeset_acquire_ctx *ctx);
int (*page_flip_target)(struct drm_crtc *crtc,struct drm_framebuffer *fb,struct drm_pending_vblank_event *event,uint32_t flags, uint32_t target, struct drm_modeset_acquire_ctx *ctx);
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);
int (*late_register)(struct drm_crtc *crtc);
void (*early_unregister)(struct drm_crtc *crtc);
int (*set_crc_source)(struct drm_crtc *crtc, const char *source, size_t *values_cnt);
void (*atomic_print_state)(struct drm_printer *p, const struct drm_crtc_state *state);
u32 (*get_vblank_counter)(struct drm_crtc *crtc);
int (*enable_vblank)(struct drm_crtc *crtc);
void (*disable_vblank)(struct drm_crtc *crtc);
};
Members
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.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.
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.
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.
gamma_set
Set gamma on the CRTC.
This callback is optional.
Atomic drivers who want to support gamma tables should implement the atomic color management support, enabled by calling
drm_crtc_enable_color_mgmt()
, which then supports the legacy gamma interface through thedrm_atomic_helper_legacy_gamma_set()
compatibility implementation.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. 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.
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 this hook 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.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 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.page_flip_target
Same as page_flip but with an additional parameter specifying the absolute target vertical blank period (as reported by
drm_crtc_vblank_count()
) when the flip should take effect.Note that the core code calls drm_crtc_vblank_get before this entry point, and will call drm_crtc_vblank_put if this entry point returns any non-0 error code. It’s the driver’s responsibility to call drm_crtc_vblank_put after this entry point returns 0, typically when the flip completes.
set_property
This is the legacy entry point to update a property attached to the CRTC.
This callback is optional if the driver does not support any legacy driver-private properties. For atomic drivers it is not used because property handling is done entirely in the DRM core.
RETURNS:
0 on success or a negative error code on failure.
atomic_duplicate_state
Duplicate the current atomic state for this CRTC and return it. The core and helpers guarantee that any atomic state duplicated with this hook and still owned by the caller (i.e. not transferred to the driver by calling
drm_mode_config_funcs.atomic_commit
) will be cleaned up by calling the atomic_destroy_state hook in this structure.This callback is mandatory for atomic drivers.
Atomic drivers which don’t subclass
struct drm_crtc_state
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
drm_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.
atomic_destroy_state
Destroy a state duplicated with atomic_duplicate_state and release or unreference all resources it references
This callback is mandatory for atomic drivers.
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.
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).
late_register
This optional hook can be used to register additional userspace interfaces attached to the crtc like debugfs interfaces. It is called late in the driver load sequence from
drm_dev_register()
. Everything added from this callback should be unregistered in the early_unregister callback.Returns:
0 on success, or a negative error code on failure.
early_unregister
- This optional hook should be used to unregister the additional
userspace interfaces attached to the crtc from
late_register. It is called from
drm_dev_unregister()
, early in the driver unload sequence to disable userspace access before data structures are torndown. set_crc_source
Changes the source of CRC checksums of frames at the request of userspace, typically for testing purposes. The sources available are specific of each driver and a
NULL
value indicates that CRC generation is to be switched off.When CRC generation is enabled, the driver should call
drm_crtc_add_crc_entry()
at each frame, providing any information that characterizes the frame contents in the crcN arguments, as provided from the configured source. Drivers must accept an “auto” source name that will select a default source for this CRTC.Note that “auto” can depend upon the current modeset configuration, e.g. it could pick an encoder or output specific CRC sampling point.
This callback is optional if the driver does not support any CRC generation functionality.
RETURNS:
0 on success or a negative error code on failure.
atomic_print_state
If driver subclasses
struct drm_crtc_state
, it should implement this optional hook for printing additional driver specific state.Do not call this directly, use
drm_atomic_crtc_print_state()
instead.get_vblank_counter
Driver callback for fetching a raw hardware vblank counter for the CRTC. It’s meant to be used by new drivers as the replacement of
drm_driver.get_vblank_counter
hook.This callback is optional. If a device doesn’t have a hardware counter, the driver can simply leave the hook as NULL. The DRM core will account for missed vblank events while interrupts where disabled based on system timestamps.
Wraparound handling and loss of events due to modesetting is dealt with in the DRM core code, as long as drivers call
drm_crtc_vblank_off()
anddrm_crtc_vblank_on()
when disabling or enabling a CRTC.See also
drm_device.vblank_disable_immediate
anddrm_device.max_vblank_count
.Returns:
Raw vblank counter value.
enable_vblank
Enable vblank interrupts for the CRTC. It’s meant to be used by new drivers as the replacement of
drm_driver.enable_vblank
hook.Returns:
Zero on success, appropriate errno if the vblank interrupt cannot be enabled.
disable_vblank
- Disable vblank interrupts for the CRTC. It’s meant to be used by
new drivers as the replacement of
drm_driver.disable_vblank
hook.
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;
unsigned index;
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;
#ifdef CONFIG_DEBUG_FS;
struct dentry *debugfs_entry;
#endif;
struct drm_crtc_crc crc;
unsigned int fence_context;
spinlock_t fence_lock;
unsigned long fence_seqno;
char timeline_name[32];
};
Members
dev
- parent DRM device
port
- OF node used by
drm_of_find_possible_crtcs()
. head
- List of all CRTCs on dev, linked from
drm_mode_config.crtc_list
. Invariant over the lifetime of dev and therefore does not need locking. name
- human readable name, can be overwritten by the driver
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 ...). A full modeset also need to grab
drm_mode_config.connection_mutex
.For atomic drivers specifically this protects state.
base
- base KMS object for ID tracking etc.
primary
- Primary plane for this CRTC. Note that this is only relevant for legacy IOCTL, it specifies the plane implicitly used by the SETCRTC and PAGE_FLIP IOCTLs. It does not have any significance beyond that.
cursor
- Cursor plane for this CRTC. Note that this is only relevant for legacy IOCTL, it specifies the plane implicitly used by the SETCURSOR and SETCURSOR2 IOCTLs. It does not have any significance beyond that.
index
- Position inside the mode_config.list, can be used as an array index. It is invariant over the lifetime of the CRTC.
cursor_x
- Current x position of the cursor, used for universal
cursor planes because the SETCURSOR IOCTL only can update the
framebuffer without supplying the coordinates. Drivers should not use
this directly, atomic drivers should look at
drm_plane_state.crtc_x
of the cursor plane instead. cursor_y
- Current y position of the cursor, used for universal
cursor planes because the SETCURSOR IOCTL only can update the
framebuffer without supplying the coordinates. Drivers should not use
this directly, atomic drivers should look at
drm_plane_state.crtc_y
of the cursor plane instead. enabled
- Is this CRTC enabled? Should only be used by legacy drivers, atomic
drivers should instead consult
drm_crtc_state.enable
anddrm_crtc_state.active
. Atomic drivers can update this by callingdrm_atomic_helper_update_legacy_modeset_state()
. mode
- Current mode timings. Should only be used by legacy drivers, atomic
drivers should instead consult
drm_crtc_state.mode
. Atomic drivers can update this by callingdrm_atomic_helper_update_legacy_modeset_state()
. hwmode
Programmed mode in hw, after adjustments for encoders, crtc, panel scaling etc. Should only be used by legacy drivers, for high precision vblank timestamps in
drm_calc_vbltimestamp_from_scanoutpos()
.Note that atomic drivers should not use this, but instead use
drm_crtc_state.adjusted_mode
. And for high-precision timestampsdrm_calc_vbltimestamp_from_scanoutpos()
useddrm_vblank_crtc.hwmode
, which is filled out by callingdrm_calc_timestamping_constants()
.x
- x position on screen. Should only be used by legacy drivers, atomic
drivers should look at
drm_plane_state.crtc_x
of the primary plane instead. Updated by callingdrm_atomic_helper_update_legacy_modeset_state()
. y
- y position on screen. Should only be used by legacy drivers, atomic
drivers should look at
drm_plane_state.crtc_y
of the primary plane instead. Updated by callingdrm_atomic_helper_update_legacy_modeset_state()
. funcs
- CRTC control functions
gamma_size
- Size of legacy gamma ramp reported to userspace. Set up
by calling
drm_mode_crtc_set_gamma_size()
. gamma_store
- Gamma ramp values used by the legacy SETGAMMA and
GETGAMMA IOCTls. Set up by calling
drm_mode_crtc_set_gamma_size()
. helper_private
- mid-layer private data
properties
- property tracking for this CRTC
state
Current atomic state for this CRTC.
This is protected by mutex. Note that nonblocking atomic commits access the current CRTC state without taking locks. Either by going through the
struct drm_atomic_state
pointers, seefor_each_oldnew_crtc_in_state()
,for_each_old_crtc_in_state()
andfor_each_new_crtc_in_state()
. Or through careful ordering of atomic commit operations as implemented in the atomic helpers, seestruct drm_crtc_commit
.commit_list
List of
drm_crtc_commit
structures tracking pending commits. Protected by commit_lock. This list holds its own full reference, as does the ongoing commit.“Note that the commit for a state change is also tracked in
drm_crtc_state.commit
. For accessing the immediately preceding commit in an atomic update it is recommended to just use that pointer in the old CRTC state, since accessing that doesn’t need any locking or list-walking. commit_list should only be used to stall for framebuffer cleanup that’s signalled throughdrm_crtc_commit.cleanup_done
.”commit_lock
- Spinlock to protect commit_list.
debugfs_entry
- Debugfs directory for this CRTC.
crc
- Configuration settings of CRC capture.
fence_context
- timeline context used for fence operations.
fence_lock
- spinlock to protect the fences in the fence_context.
fence_seqno
- Seqno variable used as monotonic counter for the fences created on the CRTC’s timeline.
timeline_name
- The name of the CRTC’s fence timeline.
Description
Each CRTC may have one or more connectors associated with it. This structure allows the CRTC to be controlled.
-
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
fb
- framebuffer to use for new config
crtc
- CRTC whose configuration we’re about to change
mode
- mode timings to use
x
- position of this CRTC relative to fb
y
- position of this CRTC relative to fb
connectors
- array of connectors to drive with this CRTC if possible
num_connectors
- size of connectors array
Description
This represents a modeset configuration for the legacy SETCRTC ioctl and is
also used internally. Atomic drivers instead use drm_atomic_state
.
Parameters
const 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
const struct drm_crtc * crtc
- CRTC to find mask for
Description
Given a registered CRTC, return the mask bit of that CRTC for the
drm_encoder.possible_crtcs
and drm_plane.possible_crtcs
fields.
-
struct drm_crtc *
drm_crtc_find
(struct drm_device * dev, struct drm_file * file_priv, uint32_t id)¶ look up a CRTC object from its ID
Parameters
struct drm_device * dev
- DRM device
struct drm_file * file_priv
- drm file to check for lease against.
uint32_t id
drm_mode_object
ID
Description
This can be used to look up a CRTC from its userspace ID. Only used by
drivers for legacy IOCTLs and interface, nowadays extensions to the KMS
userspace interface should be done using drm_property
.
-
drm_for_each_crtc
(crtc, dev)¶ iterate over all CRTCs
Parameters
crtc
- a
struct drm_crtc
as the loop cursor dev
- the
struct drm_device
Description
Iterate over all CRTCs of dev.
-
struct drm_crtc *
drm_crtc_from_index
(struct drm_device * dev, int idx)¶ find the registered CRTC at an index
Parameters
struct drm_device * dev
- DRM device
int idx
- index of registered CRTC to find for
Description
Given a CRTC index, return the registered CRTC from DRM device’s
list of CRTCs with matching index. This is the inverse of drm_crtc_index()
.
It’s useful in the vblank callbacks (like drm_driver.enable_vblank
or
drm_driver.disable_vblank
), since that still deals with indices instead
of pointers to struct drm_crtc
.”
Parameters
struct drm_crtc * crtc
- CRTC to turn off
Note
This should only be used by non-atomic legacy drivers.
Return
Zero on success, error code on failure.
-
int
drm_crtc_force_disable_all
(struct drm_device * dev)¶ Forcibly turn off all enabled CRTCs
Parameters
struct drm_device * dev
- DRM device whose CRTCs to turn off
Description
Drivers may want to call this on unload to ensure that all displays are unlit and the GPU is in a consistent, low power state. Takes modeset locks.
Note
This should only be used by non-atomic legacy drivers. For an atomic
version look at drm_atomic_helper_shutdown()
.
Return
Zero on success, error code on failure.
-
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. Drivers
should use this function instead of drm_crtc_init()
, which is only provided
for backwards compatibility with drivers which do not yet support universal
planes). For really simple hardware which has only 1 plane look at
drm_simple_display_pipe_init()
instead.
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_mode_set_config_internal
(struct drm_mode_set * set)¶ helper to call
drm_mode_config_funcs.set_config
Parameters
struct drm_mode_set * set
- modeset config to set
Description
This is a little helper to wrap internal calls to the
drm_mode_config_funcs.set_config
driver interface. The only thing it adds is
correct refcounting dance.
This should only be used by non-atomic legacy drivers.
Return
Zero on success, negative errno on failure.
-
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
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 underlying memory manager for allocating backing
storage. When creating a frame buffer applications pass a memory handle
(or a list of memory handles for multi-planar formats) through the
struct 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.
Framebuffers are tracked with struct drm_framebuffer
. They are published
using drm_framebuffer_init()
- after calling that function userspace can use
and access the framebuffer object. The helper function
drm_helper_mode_fill_fb_struct()
can be used to pre-fill the required
metadata fields.
The lifetime of a drm framebuffer is controlled with a reference count,
drivers can grab additional references with drm_framebuffer_get()
and drop
them again with drm_framebuffer_put()
. 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()
. But doing this is not
recommended, and it’s better to have a normal free-standing struct
drm_framebuffer
.
Frame Buffer Functions Reference¶
-
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
destroy
- Clean up framebuffer resources, specifically also unreference the
backing storage. The core guarantees to call this function for every
framebuffer successfully created by calling
drm_mode_config_funcs.fb_create
. Drivers must also calldrm_framebuffer_cleanup()
to release DRM core resources for this framebuffer. 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.
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_framebuffer
¶ frame buffer object
Definition
struct drm_framebuffer {
struct drm_device *dev;
struct list_head head;
struct drm_mode_object base;
char comm[TASK_COMM_LEN];
const struct drm_format_info *format;
const struct drm_framebuffer_funcs *funcs;
unsigned int pitches[4];
unsigned int offsets[4];
uint64_t modifier;
unsigned int width;
unsigned int height;
int flags;
int hot_x;
int hot_y;
struct list_head filp_head;
struct drm_gem_object *obj[4];
};
Members
dev
- DRM device this framebuffer belongs to
head
- Place on the
drm_mode_config.fb_list
, access protected bydrm_mode_config.fb_lock
. base
- base modeset object structure, contains the reference count.
comm
- Name of the process allocating the fb, used for fb dumping.
format
- framebuffer format information
funcs
- framebuffer vfunc table
pitches
- Line stride per buffer. For userspace created object this is copied from drm_mode_fb_cmd2.
offsets
Offset from buffer start to the actual pixel data in bytes, per buffer. For userspace created object this is copied from drm_mode_fb_cmd2.
Note that this is a linear offset and does not take into account tiling or buffer laytou per modifier. It meant to be used when the actual pixel data for this framebuffer plane starts at an offset, e.g. when multiple planes are allocated within the same backing storage buffer object. For tiled layouts this generally means it offsets must at least be tile-size aligned, but hardware often has stricter requirements.
This should not be used to specifiy x/y pixel offsets into the buffer data (even for linear buffers). Specifying an x/y pixel offset is instead done through the source rectangle in
struct drm_plane_state
.modifier
- Data layout modifier. This is used to describe tiling, or also special layouts (like compression) of auxiliary buffers. For userspace created object this is copied from drm_mode_fb_cmd2.
width
- Logical width of the visible area of the framebuffer, in pixels.
height
- Logical height of the visible area of the framebuffer, in pixels.
flags
- Framebuffer flags like DRM_MODE_FB_INTERLACED or DRM_MODE_FB_MODIFIERS.
hot_x
- X coordinate of the cursor hotspot. Used by the legacy cursor IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR universal plane.
hot_y
- Y coordinate of the cursor hotspot. Used by the legacy cursor IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR universal plane.
filp_head
- Placed on
drm_file.fbs
, protected bydrm_file.fbs_lock
. obj
GEM objects backing the framebuffer, one per plane (optional).
This is used by the GEM framebuffer helpers, see e.g.
drm_gem_fb_create()
.
Description
Note that the fb is refcounted for the benefit of driver internals,
for example some hw, disabling a CRTC/plane is asynchronous, and
scanout does not actually complete until the next vblank. So some
cleanup (like releasing the reference(s) on the backing GEM bo(s))
should be deferred. In cases like this, the driver would like to
hold a ref to the fb even though it has already been removed from
userspace perspective. See drm_framebuffer_get()
and
drm_framebuffer_put()
.
The refcount is stored inside the mode object base.
-
void
drm_framebuffer_get
(struct drm_framebuffer * fb)¶ acquire a framebuffer reference
Parameters
struct drm_framebuffer * fb
- DRM framebuffer
Description
This function increments the framebuffer’s reference count.
-
void
drm_framebuffer_put
(struct drm_framebuffer * fb)¶ release a framebuffer reference
Parameters
struct drm_framebuffer * fb
- DRM framebuffer
Description
This function decrements the framebuffer’s reference count and frees the framebuffer if the reference count drops to zero.
-
void
drm_framebuffer_reference
(struct drm_framebuffer * fb)¶ acquire a framebuffer reference
Parameters
struct drm_framebuffer * fb
- DRM framebuffer
Description
This is a compatibility alias for drm_framebuffer_get()
and should not be
used by new code.
-
void
drm_framebuffer_unreference
(struct drm_framebuffer * fb)¶ release a framebuffer reference
Parameters
struct drm_framebuffer * fb
- DRM framebuffer
Description
This is a compatibility alias for drm_framebuffer_put()
and should not be
used by new code.
-
uint32_t
drm_framebuffer_read_refcount
(const struct drm_framebuffer * fb)¶ read the framebuffer reference count.
Parameters
const struct drm_framebuffer * fb
- framebuffer
Description
This functions returns the framebuffer’s reference count.
-
void
drm_framebuffer_assign
(struct drm_framebuffer ** p, struct drm_framebuffer * fb)¶ store a reference to the fb
Parameters
struct drm_framebuffer ** p
- location to store framebuffer
struct drm_framebuffer * fb
- new framebuffer (maybe NULL)
Description
This functions sets the location to store a reference to the framebuffer, unreferencing the framebuffer that was previously stored in that location.
-
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, struct drm_file * file_priv, uint32_t id)¶ look up a drm framebuffer and grab a reference
Parameters
struct drm_device * dev
- drm device
struct drm_file * file_priv
- drm file to check for lease against.
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_put()
.
-
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).
NOTE
This function is deprecated. For driver-private framebuffers it is not
recommended to embed a framebuffer struct info fbdev struct, instead, a
framebuffer pointer is preferred and drm_framebuffer_put()
should be called
when the framebuffer is to be cleaned up.
-
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
drm_framebuffer_funcs.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 usage - 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_framebuffer_plane_width
(int width, const struct drm_framebuffer * fb, int plane)¶ width of the plane given the first plane
Parameters
int width
- width of the first plane
const struct drm_framebuffer * fb
- the framebuffer
int plane
- plane index
Return
The width of plane, given that the width of the first plane is width.
-
int
drm_framebuffer_plane_height
(int height, const struct drm_framebuffer * fb, int plane)¶ height of the plane given the first plane
Parameters
int height
- height of the first plane
const struct drm_framebuffer * fb
- the framebuffer
int plane
- plane index
Return
The height of plane, given that the height of the first plane is height.
DRM Format Handling¶
-
struct
drm_format_info
¶ information about a DRM format
Definition
struct drm_format_info {
u32 format;
u8 depth;
u8 num_planes;
u8 cpp[3];
u8 hsub;
u8 vsub;
bool has_alpha;
bool is_yuv;
};
Members
format
- 4CC format identifier (DRM_FORMAT_*)
depth
- Color depth (number of bits per pixel excluding padding bits), valid for a subset of RGB formats only. This is a legacy field, do not use in new code and set to 0 for new formats.
num_planes
- Number of color planes (1 to 3)
cpp
- Number of bytes per pixel (per plane)
hsub
- Horizontal chroma subsampling factor
vsub
- Vertical chroma subsampling factor
has_alpha
- Does the format embeds an alpha component?
is_yuv
- Is it a YUV format?
-
struct
drm_format_name_buf
¶ name of a DRM format
Definition
struct drm_format_name_buf {
char str[32];
};
Members
str
- string buffer containing the format name
-
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.
-
const char *
drm_get_format_name
(uint32_t format, struct drm_format_name_buf * buf)¶ fill a string with a drm fourcc format’s name
Parameters
uint32_t format
- format to compute name of
struct drm_format_name_buf * buf
- caller-supplied buffer
-
const struct drm_format_info *
drm_format_info
(u32 format) query information for a given format
Parameters
u32 format
- pixel format (DRM_FORMAT_*)
Description
The caller should only pass a supported pixel format to this function. Unsupported pixel formats will generate a warning in the kernel log.
Return
The instance of struct drm_format_info that describes the pixel format, or NULL if the format is unsupported.
-
const struct drm_format_info *
drm_get_format_info
(struct drm_device * dev, const struct drm_mode_fb_cmd2 * mode_cmd)¶ query information for a given framebuffer configuration
Parameters
struct drm_device * dev
- DRM device
const struct drm_mode_fb_cmd2 * mode_cmd
- metadata from the userspace fb creation request
Return
The instance of struct drm_format_info that describes the pixel format, or NULL if the format is unsupported.
-
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 drm_driver.dumb_create
operation. drm_driver.dumb_destroy
defaults to drm_gem_dumb_destroy()
if
not set and drm_driver.dumb_map_offset
defaults to
drm_gem_dumb_map_offset()
. See the callbacks for further details.
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.
Plane Abstraction¶
A plane represents an image source that can be blended with or overlayed on
top of a CRTC during the scanout process. Planes take their input data from a
drm_framebuffer
object. The plane itself specifies the cropping and scaling
of that image, and where it is placed on the visible are of a display
pipeline, represented by drm_crtc
. A plane can also have additional
properties that specify how the pixels are positioned and blended, like
rotation or Z-position. All these properties are stored in drm_plane_state
.
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()
.
Cursor and overlay planes are optional. All drivers should provide one
primary plane per CRTC to avoid surprising userspace too much. See enum
drm_plane_type for a more in-depth discussion of these special uapi-relevant
plane types. Special planes are associated with their CRTC by calling
drm_crtc_init_with_planes()
.
The type of a plane is exposed in the immutable “type” enumeration property, which has one of the following values: “Overlay”, “Primary”, “Cursor”.
Plane Functions Reference¶
-
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 dma_fence *fence;
int32_t crtc_x;
int32_t crtc_y;
uint32_t crtc_w, crtc_h;
uint32_t src_x;
uint32_t src_y;
uint32_t src_h, src_w;
u16 alpha;
unsigned int rotation;
unsigned int zpos;
unsigned int normalized_zpos;
enum drm_color_encoding color_encoding;
enum drm_color_range color_range;
struct drm_rect src, dst;
bool visible;
struct drm_crtc_commit *commit;
struct drm_atomic_state *state;
};
Members
plane
- backpointer to the plane
crtc
- Currently bound CRTC, NULL if disabled. Do not this write directly,
use
drm_atomic_set_crtc_for_plane()
fb
- Currently bound framebuffer. Do not write this directly, use
drm_atomic_set_fb_for_plane()
fence
Optional fence to wait for before scanning out fb. The core atomic code will set this when userspace is using explicit fencing. Do not write this directly for a driver’s implicit fence, use
drm_atomic_set_fence_for_plane()
to ensure that an explicit fence is preserved.Drivers should store any implicit fence in this from their
drm_plane_helper_funcs.prepare_fb
callback. Seedrm_gem_fb_prepare_fb()
anddrm_gem_fb_simple_display_pipe_prepare_fb()
for suitable helpers.crtc_x
- Left position of visible portion of plane on crtc, signed dest location allows it to be partially off screen.
crtc_y
- Upper position of visible portion of plane on crtc, signed dest location allows it to be partially off screen.
crtc_w
- width of visible portion of plane on crtc
crtc_h
- height of visible portion of plane on crtc
src_x
- left position of visible portion of plane within plane (in 16.16 fixed point).
src_y
- upper position of visible portion of plane within plane (in 16.16 fixed point).
src_h
- height of visible portion of plane (in 16.16)
src_w
- width of visible portion of plane (in 16.16)
alpha
- Opacity of the plane with 0 as completely transparent and 0xffff as
completely opaque. See
drm_plane_create_alpha_property()
for more details. rotation
- Rotation of the plane. See
drm_plane_create_rotation_property()
for more details. zpos
Priority of the given plane on crtc (optional).
Note that multiple active planes on the same crtc can have an identical zpos value. The rule to solving the conflict is to compare the plane object IDs; the plane with a higher ID must be stacked on top of a plane with a lower ID.
See
drm_plane_create_zpos_property()
anddrm_plane_create_zpos_immutable_property()
for more details.normalized_zpos
- Normalized value of zpos: unique, range from 0 to N-1 where N is the
number of active planes for given crtc. Note that the driver must set
drm_mode_config.normalize_zpos
or calldrm_atomic_normalize_zpos()
to update this before it can be trusted. color_encoding
- Color encoding for non RGB formats
color_range
- Color range for non RGB formats
src
- clipped source coordinates of the plane (in 16.16)
dst
- clipped destination coordinates of the plane
visible
- Visibility of the plane. This can be false even if fb!=NULL and crtc!=NULL, due to clipping.
commit
Tracks the pending commit to prevent use-after-free conditions, and for async plane updates.
May be NULL.
state
- backpointer to global drm_atomic_state
Description
Please not that the destination coordinates crtc_x, crtc_y, crtc_h and
crtc_w and the source coordinates src_x, src_y, src_h and src_w are the
raw coordinates provided by userspace. Drivers should use
drm_atomic_helper_check_plane_state()
and only use the derived rectangles in
src and dst to program the hardware.
-
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, struct drm_modeset_acquire_ctx *ctx);
int (*disable_plane)(struct drm_plane *plane, struct drm_modeset_acquire_ctx *ctx);
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);
int (*late_register)(struct drm_plane *plane);
void (*early_unregister)(struct drm_plane *plane);
void (*atomic_print_state)(struct drm_printer *p, const struct drm_plane_state *state);
bool (*format_mod_supported)(struct drm_plane *plane, uint32_t format, uint64_t modifier);
};
Members
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.
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.
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. 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.set_property
This is the legacy entry point to update a property attached to the plane.
This callback is optional if the driver does not support any legacy driver-private properties. For atomic drivers it is not used because property handling is done entirely in the DRM core.
RETURNS:
0 on success or a negative error code on failure.
atomic_duplicate_state
Duplicate the current atomic state for this plane and return it. The core and helpers guarantee that any atomic state duplicated with this hook and still owned by the caller (i.e. not transferred to the driver by calling
drm_mode_config_funcs.atomic_commit
) will be cleaned up by calling the atomic_destroy_state hook in this structure.This callback is mandatory for atomic drivers.
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
drm_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.
atomic_destroy_state
Destroy a state duplicated with atomic_duplicate_state and release or unreference all resources it references
This callback is mandatory for atomic drivers.
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.
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).
late_register
This optional hook can be used to register additional userspace interfaces attached to the plane like debugfs interfaces. It is called late in the driver load sequence from
drm_dev_register()
. Everything added from this callback should be unregistered in the early_unregister callback.Returns:
0 on success, or a negative error code on failure.
early_unregister
- This optional hook should be used to unregister the additional
userspace interfaces attached to the plane from
late_register. It is called from
drm_dev_unregister()
, early in the driver unload sequence to disable userspace access before data structures are torndown. atomic_print_state
If driver subclasses
struct drm_plane_state
, it should implement this optional hook for printing additional driver specific state.Do not call this directly, use
drm_atomic_plane_print_state()
instead.format_mod_supported
This optional hook is used for the DRM to determine if the given format/modifier combination is valid for the plane. This allows the DRM to generate the correct format bitmask (which formats apply to which modifier), and to valdiate modifiers at atomic_check time.
If not present, then any modifier in the plane’s modifier list is allowed with any of the plane’s formats.
Returns:
True if the given modifier is valid for that format on the plane. False otherwise.
-
enum
drm_plane_type
¶ uapi plane type enumeration
Constants
DRM_PLANE_TYPE_OVERLAY
- Overlay planes represent all non-primary, non-cursor planes. Some drivers refer to these types of planes as “sprites” internally.
DRM_PLANE_TYPE_PRIMARY
- Primary planes represent a “main” plane for a CRTC. Primary planes
are the planes operated upon by CRTC modesetting and flipping
operations described in the
drm_crtc_funcs.page_flip
anddrm_crtc_funcs.set_config
hooks. DRM_PLANE_TYPE_CURSOR
- Cursor planes represent 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.
Description
For historical reasons not all planes are made the same. This enumeration is used to tell the different types of planes apart to implement the different uapi semantics for them. For userspace which is universal plane aware and which is using that atomic IOCTL there’s no difference between these planes (beyong what the driver and hardware can support of course).
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. See also
drm_for_each_legacy_plane()
.
WARNING: The values of this enum is UABI since they’re exposed in the “type” property.
-
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;
uint64_t *modifiers;
unsigned int modifier_count;
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;
unsigned index;
const struct drm_plane_helper_funcs *helper_private;
struct drm_plane_state *state;
struct drm_property *alpha_property;
struct drm_property *zpos_property;
struct drm_property *rotation_property;
struct drm_property *color_encoding_property;
struct drm_property *color_range_property;
};
Members
dev
- DRM device this plane belongs to
head
- List of all planes on dev, linked from
drm_mode_config.plane_list
. Invariant over the lifetime of dev and therefore does not need locking. name
- human readable name, can be overwritten by the driver
mutex
Protects modeset plane state, together with the
drm_crtc.mutex
of CRTC this plane is linked to (when active, getting activated or getting disabled).For atomic drivers specifically this protects state.
base
- base mode object
possible_crtcs
- pipes this plane can be bound to constructed from
drm_crtc_mask()
format_types
- array of formats supported by this plane
format_count
- Size of the array pointed at by format_types.
format_default
- driver hasn’t supplied supported formats for the plane. Used by the drm_plane_init compatibility wrapper only.
modifiers
- array of modifiers supported by this plane
modifier_count
- Size of the array pointed at by modifier_count.
crtc
- Currently bound CRTC, only meaningful for non-atomic drivers. For
atomic drivers this is forced to be NULL, atomic drivers should
instead check
drm_plane_state.crtc
. fb
- Currently bound framebuffer, only meaningful for non-atomic drivers.
For atomic drivers this is forced to be NULL, atomic drivers should
instead check
drm_plane_state.fb
. old_fb
- Temporary tracking of the old fb while a modeset is ongoing. Only used by non-atomic drivers, forced to be NULL for atomic drivers.
funcs
- plane control functions
properties
- property tracking for this plane
type
- Type of plane, see
enum drm_plane_type
for details. index
- Position inside the mode_config.list, can be used as an array index. It is invariant over the lifetime of the plane.
helper_private
- mid-layer private data
state
Current atomic state for this plane.
This is protected by mutex. Note that nonblocking atomic commits access the current plane state without taking locks. Either by going through the
struct drm_atomic_state
pointers, seefor_each_oldnew_plane_in_state()
,for_each_old_plane_in_state()
andfor_each_new_plane_in_state()
. Or through careful ordering of atomic commit operations as implemented in the atomic helpers, seestruct drm_crtc_commit
.alpha_property
- Optional alpha property for this plane. See
drm_plane_create_alpha_property()
. zpos_property
- Optional zpos property for this plane. See
drm_plane_create_zpos_property()
. rotation_property
- Optional rotation property for this plane. See
drm_plane_create_rotation_property()
. color_encoding_property
- Optional “COLOR_ENCODING” enum property for specifying
color encoding for non RGB formats.
See
drm_plane_create_color_properties()
. color_range_property
- Optional “COLOR_RANGE” enum property for specifying
color range for non RGB formats.
See
drm_plane_create_color_properties()
.
Description
Planes represent the scanout hardware of a display block. They receive their
input data from a drm_framebuffer
and feed it to a drm_crtc
. Planes control
the color conversion, see Plane Composition Properties for more details,
and are also involved in the color conversion of input pixels, see Color
Management Properties for details on that.
Parameters
const 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.
Parameters
const struct drm_plane * plane
- plane to find mask for
-
struct drm_plane *
drm_plane_find
(struct drm_device * dev, struct drm_file * file_priv, uint32_t id)¶ find a
drm_plane
Parameters
struct drm_device * dev
- DRM device
struct drm_file * file_priv
- drm file to check for lease against.
uint32_t id
- plane id
Description
Returns the plane with id, NULL if it doesn’t exist. Simple wrapper around
drm_mode_object_find()
.
-
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_legacy_plane
(plane, dev)¶ iterate over all planes for legacy userspace
Parameters
plane
- the loop cursor
dev
- the DRM device
Description
Iterate over all legacy planes of dev, excluding primary and cursor planes.
This is useful for implementing userspace apis when userspace is not
universal plane aware. See also enum drm_plane_type
.
-
drm_for_each_plane
(plane, dev)¶ iterate over all planes
Parameters
plane
- the loop cursor
dev
- the DRM device
Description
Iterate over all planes of dev, include primary and cursor planes.
-
int
drm_universal_plane_init
(struct drm_device * dev, struct drm_plane * plane, uint32_t possible_crtcs, const struct drm_plane_funcs * funcs, const uint32_t * formats, unsigned int format_count, const uint64_t * format_modifiers, 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
uint32_t 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
const uint64_t * format_modifiers
- array of struct drm_format modifiers terminated by DRM_FORMAT_MOD_INVALID
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, uint32_t 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
uint32_t 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. This is the inverse of drm_plane_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.
Note that this function is not suitable for atomic drivers, since it doesn’t
wire through the lock acquisition context properly and hence can’t handle
retries or driver private locks. You probably want to use
drm_atomic_helper_disable_plane()
or
drm_atomic_helper_disable_planes_on_crtc()
instead.
-
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.
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_NO_420
- ycbcr 420 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;
struct list_head export_head;
};
Members
head
- struct list_head for mode lists.
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.
name
- Human-readable name of the mode, filled out with
drm_mode_set_name()
. status
- Status of the mode, used to filter out modes not supported by the
hardware. See enum
drm_mode_status
. type
A bitmask of flags, mostly about the source of a mode. Possible flags are:
- 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.
- DRM_MODE_TYPE_USERDEF: Mode defined via kernel command line
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. We no longer accept modes with these types though:
- DRM_MODE_TYPE_BUILTIN: Meant for hard-coded modes, unused. Use DRM_MODE_TYPE_DRIVER instead.
- 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.
clock
- Pixel clock in kHz.
hdisplay
- horizontal display size
hsync_start
- horizontal sync start
hsync_end
- horizontal sync end
htotal
- horizontal total size
hskew
- horizontal skew?!
vdisplay
- vertical display size
vsync_start
- vertical sync start
vsync_end
- vertical sync end
vtotal
- vertical total size
vscan
- vertical scan?!
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: <deprecated>
- DRM_MODE_FLAG_PIXMUX: <deprecated>
- 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.
width_mm
- Addressable size of the output in mm, projectors should set this to 0.
height_mm
- Addressable size of the output in mm, projectors should set this to 0.
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.
crtc_hdisplay
- hardware mode horizontal display size
crtc_hblank_start
- hardware mode horizontal blank start
crtc_hblank_end
- hardware mode horizontal blank end
crtc_hsync_start
- hardware mode horizontal sync start
crtc_hsync_end
- hardware mode horizontal sync end
crtc_htotal
- hardware mode horizontal total size
crtc_hskew
- hardware mode horizontal skew?!
crtc_vdisplay
- hardware mode vertical display size
crtc_vblank_start
- hardware mode vertical blank start
crtc_vblank_end
- hardware mode vertical blank end
crtc_vsync_start
- hardware mode vertical sync start
crtc_vsync_end
- hardware mode vertical sync end
crtc_vtotal
- hardware mode vertical total size
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.
private_flags
- Similar to private, but just an integer.
vrefresh
Vertical refresh rate, for debug output in human readable form. Not used in a functional way.
This value is in Hz.
hsync
Horizontal refresh rate, for debug output in human readable form. Not used in a functional way.
This value is in kHz.
picture_aspect_ratio
- Field for setting the HDMI picture aspect ratio of a mode.
export_head
- struct list_head for modes to be exposed to the userspace. This is to maintain a list of exposed modes while preparing user-mode’s list in drm_mode_getconnector ioctl. The purpose of this list_head only lies in the ioctl function, and is not expected to be used outside the function. Once used, the stale pointers are not reset, but left as it is, to avoid overhead of protecting it by mode_config.mutex.
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()
.
For printing you can use DRM_MODE_FMT
and DRM_MODE_ARG()
.
-
DRM_MODE_FMT
()¶ printf string for
struct drm_display_mode
Parameters
-
DRM_MODE_ARG
(m)¶ printf arguments for
struct drm_display_mode
Parameters
m
- display mode
-
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.
-
void
drm_bus_flags_from_videomode
(const struct videomode * vm, u32 * bus_flags)¶ extract information about pixelclk and DE polarity from videomode and store it in a separate variable
Parameters
const struct videomode * vm
- videomode structure to use
u32 * bus_flags
- information about pixelclk, sync and DE polarity will be stored here
Description
Sets DRM_BUS_FLAG_DE_(LOW|HIGH), DRM_BUS_FLAG_PIXDATA_(POS|NEG)EDGE and DISPLAY_FLAGS_SYNC_(POS|NEG)EDGE in bus_flags according to DISPLAY_FLAGS found in vm
-
int
of_get_drm_display_mode
(struct device_node * np, struct drm_display_mode * dmode, u32 * bus_flags, 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
u32 * bus_flags
- information about pixelclk, sync and DE polarity
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_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.
-
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_match
(const struct drm_display_mode * mode1, const struct drm_display_mode * mode2, unsigned int match_flags)¶ test modes for (partial) equality
Parameters
const struct drm_display_mode * mode1
- first mode
const struct drm_display_mode * mode2
- second mode
unsigned int match_flags
- which parts need to match (DRM_MODE_MATCH_*)
Description
Check to see if mode1 and mode2 are equivalent.
Return
True if the modes are (partially) equal, false otherwise.
-
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_driver
(struct drm_device * dev, const struct drm_display_mode * mode)¶ make sure the mode is somewhat sane
Parameters
struct drm_device * dev
- drm device
const struct drm_display_mode * mode
- mode to check
Description
First do basic validation on the mode, and then allow the driver
to check for device/driver specific limitations via the optional
drm_mode_config_helper_funcs.mode_valid
hook.
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
-
enum drm_mode_status
drm_mode_validate_ycbcr420
(const struct drm_display_mode * mode, struct drm_connector * connector)¶ add ‘ycbcr420-only’ modes only when allowed
Parameters
const struct drm_display_mode * mode
- mode to check
struct drm_connector * connector
- drm connector under action
Description
This function is a helper which can be used to filter out any YCBCR420 only mode, when the source doesn’t support it.
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_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.
-
bool
drm_mode_is_420_only
(const struct drm_display_info * display, const struct drm_display_mode * mode)¶ if a given videomode can be only supported in YCBCR420 output format
Parameters
const struct drm_display_info * display
- display under action
const struct drm_display_mode * mode
- video mode to be tested.
Return
true if the mode can be supported in YCBCR420 format false if not.
-
bool
drm_mode_is_420_also
(const struct drm_display_info * display, const struct drm_display_mode * mode)¶ if a given videomode can be supported in YCBCR420 output format also (along with RGB/YCBCR444/422)
Parameters
const struct drm_display_info * display
- display under action.
const struct drm_display_mode * mode
- video mode to be tested.
Return
true if the mode can be support YCBCR420 format false if not.
-
bool
drm_mode_is_420
(const struct drm_display_info * display, const struct drm_display_mode * mode)¶ if a given videomode can be supported in YCBCR420 output format
Parameters
const struct drm_display_info * display
- display under action.
const struct drm_display_mode * mode
- video mode to be tested.
Return
true if the mode can be supported in YCBCR420 format false if not.
Connector Abstraction¶
In DRM connectors are the general abstraction for display sinks, and include
als fixed panels or anything else that can display pixels in some form. As
opposed to all other KMS objects representing hardware (like CRTC, encoder or
plane abstractions) connectors can be hotplugged and unplugged at runtime.
Hence they are reference-counted using drm_connector_get()
and
drm_connector_put()
.
KMS driver must create, initialize, register and attach at a struct
drm_connector
for each such sink. The instance is created as other KMS
objects and initialized by setting the following fields. The connector is
initialized with a call to drm_connector_init()
with a pointer to the
struct drm_connector_funcs
and a connector type, and then exposed to
userspace with a call to drm_connector_register()
.
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_connector_attach_encoder()
. The
driver must also set the drm_connector.encoder
field to point to the
attached encoder.
For connectors which are not fixed (like built-in panels) the driver needs to
support hotplug notifications. The simplest way to do that is by using the
probe helpers, see drm_kms_helper_poll_init()
for connectors which don’t have
hardware support for hotplug interrupts. Connectors with hardware hotplug
support can instead use e.g. drm_helper_hpd_irq_event()
.
Connector Functions Reference¶
-
enum
drm_connector_status
¶ status for a
drm_connector
Constants
connector_status_connected
- The connector is definitely connected to a sink device, and can be enabled.
connector_status_disconnected
- The connector isn’t connected to a sink device which can be autodetect. For digital outputs like DP or HDMI (which can be realiable probed) this means there’s really nothing there. It is driver-dependent whether a connector with this status can be lit up or not.
connector_status_unknown
- The connector’s status could not be reliably detected. This happens when probing would either cause flicker (like load-detection when the connector is in use), or when a hardware resource isn’t available (like when load-detection needs a free CRTC). It should be possible to light up the connector with one of the listed fallback modes. For default configuration userspace should only try to light up connectors with unknown status when there’s not connector with connector_status_connected.
Description
This enum is used to track the connector status. There are no separate #defines for the uapi!
-
struct
drm_scrambling
¶
Definition
struct drm_scrambling {
bool supported;
bool low_rates;
};
Members
supported
- scrambling supported for rates > 340 Mhz.
low_rates
- scrambling supported for rates <= 340 Mhz.
-
struct
drm_hdmi_info
¶ runtime information about the connected HDMI sink
Definition
struct drm_hdmi_info {
struct drm_scdc scdc;
unsigned long y420_vdb_modes[BITS_TO_LONGS(128)];
unsigned long y420_cmdb_modes[BITS_TO_LONGS(128)];
u64 y420_cmdb_map;
u8 y420_dc_modes;
};
Members
scdc
- sink’s scdc support and capabilities
y420_vdb_modes
- bitmap of modes which can support ycbcr420 output only (not normal RGB/YCBCR444/422 outputs). There are total 107 VICs defined by CEA-861-F spec, so the size is 128 bits to map upto 128 VICs;
y420_cmdb_modes
- bitmap of modes which can support ycbcr420 output also, along with normal HDMI outputs. There are total 107 VICs defined by CEA-861-F spec, so the size is 128 bits to map upto 128 VICs;
y420_cmdb_map
- bitmap of SVD index, to extraxt vcb modes
y420_dc_modes
- bitmap of deep color support index
Description
Describes if a given display supports advanced HDMI 2.0 features. This information is available in CEA-861-F extension blocks (like HF-VSDB).
-
enum
drm_link_status
¶ connector’s link_status property value
Constants
DRM_LINK_STATUS_GOOD
- DP Link is Good as a result of successful link training
DRM_LINK_STATUS_BAD
- DP Link is BAD as a result of link training failure
Description
This enum is used as the connector’s link status property value. It is set to the values defined in uapi.
-
enum
drm_panel_orientation
¶ panel_orientation info for
drm_display_info
Constants
DRM_MODE_PANEL_ORIENTATION_UNKNOWN
- The drm driver has not provided any panel orientation information (normal for non panels) in this case the “panel orientation” connector prop will not be attached.
DRM_MODE_PANEL_ORIENTATION_NORMAL
- The top side of the panel matches the top side of the device’s casing.
DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP
- The top side of the panel matches the bottom side of the device’s casing, iow the panel is mounted upside-down.
DRM_MODE_PANEL_ORIENTATION_LEFT_UP
- The left side of the panel matches the top side of the device’s casing.
DRM_MODE_PANEL_ORIENTATION_RIGHT_UP
- The right side of the panel matches the top side of the device’s casing.
Description
This enum is used to track the (LCD) panel orientation. There are no separate #defines for the uapi!
-
struct
drm_display_info
¶ runtime data about the connected sink
Definition
struct drm_display_info {
char name[DRM_DISPLAY_INFO_LEN];
unsigned int width_mm;
unsigned int height_mm;
unsigned int pixel_clock;
unsigned int bpc;
enum subpixel_order subpixel_order;
#define DRM_COLOR_FORMAT_RGB444 (1<<0);
#define DRM_COLOR_FORMAT_YCRCB444 (1<<1);
#define DRM_COLOR_FORMAT_YCRCB422 (1<<2);
#define DRM_COLOR_FORMAT_YCRCB420 (1<<3);
int panel_orientation;
u32 color_formats;
const u32 *bus_formats;
unsigned int num_bus_formats;
#define DRM_BUS_FLAG_DE_LOW (1<<0);
#define DRM_BUS_FLAG_DE_HIGH (1<<1);
#define DRM_BUS_FLAG_PIXDATA_POSEDGE (1<<2);
#define DRM_BUS_FLAG_PIXDATA_NEGEDGE (1<<3);
#define DRM_BUS_FLAG_DATA_MSB_TO_LSB (1<<4);
#define DRM_BUS_FLAG_DATA_LSB_TO_MSB (1<<5);
#define DRM_BUS_FLAG_SYNC_POSEDGE (1<<6);
#define DRM_BUS_FLAG_SYNC_NEGEDGE (1<<7);
u32 bus_flags;
int max_tmds_clock;
bool dvi_dual;
bool has_hdmi_infoframe;
u8 edid_hdmi_dc_modes;
u8 cea_rev;
struct drm_hdmi_info hdmi;
bool non_desktop;
};
Members
name
- Name of the display.
width_mm
- Physical width in mm.
height_mm
- Physical height in mm.
pixel_clock
- Maximum pixel clock supported by the sink, in units of
100Hz. This mismatches the clock in
drm_display_mode
(which is in kHZ), because that’s what the EDID uses as base unit. bpc
- Maximum bits per color channel. Used by HDMI and DP outputs.
subpixel_order
- Subpixel order of LCD panels.
panel_orientation
- Read only connector property for built-in panels,
indicating the orientation of the panel vs the device’s casing.
drm_connector_init()
sets this to DRM_MODE_PANEL_ORIENTATION_UNKNOWN. When not UNKNOWN this gets used by the drm_fb_helpers to rotate the fb to compensate and gets exported as prop to userspace. color_formats
- HDMI Color formats, selects between RGB and YCrCb modes. Used DRM_COLOR_FORMAT_ defines, which are _not_ the same ones as used to describe the pixel format in framebuffers, and also don’t match the formats in bus_formats which are shared with v4l.
bus_formats
- Pixel data format on the wire, somewhat redundant with color_formats. Array of size num_bus_formats encoded using MEDIA_BUS_FMT_ defines shared with v4l and media drivers.
num_bus_formats
- Size of bus_formats array.
bus_flags
- Additional information (like pixel signal polarity) for the pixel data on the bus, using DRM_BUS_FLAGS_ defines.
max_tmds_clock
- Maximum TMDS clock rate supported by the sink in kHz. 0 means undefined.
dvi_dual
- Dual-link DVI sink?
has_hdmi_infoframe
- Does the sink support the HDMI infoframe?
edid_hdmi_dc_modes
- Mask of supported hdmi deep color modes. Even more stuff redundant with bus_formats.
cea_rev
- CEA revision of the HDMI sink.
hdmi
- advance features of a HDMI sink.
non_desktop
- Non desktop display (HMD).
Description
Describes a given display (e.g. CRT or flat panel) and its limitations. For
fixed display sinks like built-in panels there’s not much difference between
this and struct drm_connector
. But for sinks with a real cable this
structure is meant to describe all the things at the other end of the cable.
For sinks which provide an EDID this can be filled out by calling
drm_add_edid_modes()
.
-
struct
drm_tv_connector_state
¶ TV connector related states
Definition
struct drm_tv_connector_state {
enum drm_mode_subconnector subconnector;
struct {
unsigned int left;
unsigned int right;
unsigned int top;
unsigned int bottom;
} margins;
unsigned int mode;
unsigned int brightness;
unsigned int contrast;
unsigned int flicker_reduction;
unsigned int overscan;
unsigned int saturation;
unsigned int hue;
};
Members
subconnector
- selected subconnector
margins
- margins
margins.left
- left margin
margins.right
- right margin
margins.top
- top margin
margins.bottom
- bottom margin
mode
- TV mode
brightness
- brightness in percent
contrast
- contrast in percent
flicker_reduction
- flicker reduction in percent
overscan
- overscan in percent
saturation
- saturation in percent
hue
- hue in percent
-
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;
enum drm_link_status link_status;
struct drm_atomic_state *state;
struct drm_crtc_commit *commit;
struct drm_tv_connector_state tv;
enum hdmi_picture_aspect picture_aspect_ratio;
unsigned int content_type;
unsigned int scaling_mode;
unsigned int content_protection;
struct drm_writeback_job *writeback_job;
};
Members
connector
- backpointer to the connector
crtc
CRTC to connect connector to, NULL if disabled.
Do not change this directly, use
drm_atomic_set_crtc_for_connector()
instead.best_encoder
- Used by the atomic helpers to select the encoder, through the
drm_connector_helper_funcs.atomic_best_encoder
ordrm_connector_helper_funcs.best_encoder
callbacks. link_status
- Connector link_status to keep track of whether link is GOOD or BAD to notify userspace if retraining is necessary.
state
- backpointer to global drm_atomic_state
commit
Tracks the pending commit to prevent use-after-free conditions.
Is only set when crtc is NULL.
tv
- TV connector state
picture_aspect_ratio
Connector property to control the HDMI infoframe aspect ratio setting.
The
DRM_MODE_PICTURE_ASPECT_
* values much match the values forenum hdmi_picture_aspect
content_type
- Connector property to control the
HDMI infoframe content type setting.
The
DRM_MODE_CONTENT_TYPE_
* values much match the values. scaling_mode
- Connector property to control the upscaling, mostly used for built-in panels.
content_protection
- Connector property to request content protection. This is most commonly used for HDCP.
writeback_job
Writeback job for writeback connectors
Holds the framebuffer and out-fence for a writeback connector. As the writeback completion may be asynchronous to the normal commit cycle, the writeback job lifetime is managed separately from the normal atomic state by this object.
See also:
drm_writeback_queue_job()
anddrm_writeback_signal_completion()
-
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);
void (*atomic_print_state)(struct drm_printer *p, const struct drm_connector_state *state);
};
Members
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.
This hook is not used by atomic drivers, remapping of the legacy DPMS property is entirely handled in the DRM core.
RETURNS:
0 on success or a negative error code on failure.
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.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.
This callback is optional, if not implemented the connector will be considered as always being attached.
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.
Note that the helper library will already hold
drm_mode_config.connection_mutex
. Drivers which need to grab additional locks to avoid races with concurrent modeset changes need to usedrm_connector_helper_funcs.detect_ctx
instead.RETURNS:
drm_connector_status indicating the connector’s status.
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.
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
drm_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
drm_connector.modes
. Furthermore it must updatedrm_connector.status
anddrm_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()
to implement this function.RETURNS:
The number of modes detected and filled into
drm_connector.modes
.set_property
This is the legacy entry point to update a property attached to the connector.
This callback is optional if the driver does not support any legacy driver-private properties. For atomic drivers it is not used because property handling is done entirely in the DRM core.
RETURNS:
0 on success or a negative error code on failure.
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.This is called while holding
drm_connector.mutex
.Returns:
0 on success, or a negative error code on failure.
early_unregister
This optional hook should be used to unregister the additional userspace interfaces attached to the connector from
late_register()
. It is called fromdrm_connector_unregister()
, early in the driver unload sequence to disable userspace access before data structures are torndown.This is called while holding
drm_connector.mutex
.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). atomic_duplicate_state
Duplicate the current atomic state for this connector and return it. The core and helpers guarantee that any atomic state duplicated with this hook and still owned by the caller (i.e. not transferred to the driver by calling
drm_mode_config_funcs.atomic_commit
) will be cleaned up by calling the atomic_destroy_state hook in this structure.This callback is mandatory for atomic drivers.
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
drm_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.
atomic_destroy_state
Destroy a state duplicated with atomic_duplicate_state and release or unreference all resources it references
This callback is mandatory for atomic drivers.
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.
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).
atomic_print_state
If driver subclasses
struct drm_connector_state
, it should implement this optional hook for printing additional driver specific state.Do not call this directly, use
drm_atomic_connector_print_state()
instead.
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_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;
struct mutex mutex;
unsigned index;
int connector_type;
int connector_type_id;
bool interlace_allowed;
bool doublescan_allowed;
bool stereo_allowed;
bool ycbcr_420_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 *scaling_mode_property;
struct drm_property *content_protection_property;
struct drm_property_blob *path_blob_ptr;
#define DRM_CONNECTOR_POLL_HPD (1 << 0);
#define DRM_CONNECTOR_POLL_CONNECT (1 << 1);
#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2);
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;
#define DRM_CONNECTOR_MAX_ENCODER 3;
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
struct drm_encoder *encoder;
#define MAX_ELD_BYTES 128;
uint8_t eld[MAX_ELD_BYTES];
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;
struct drm_property_blob *tile_blob_ptr;
bool has_tile;
struct drm_tile_group *tile_group;
bool tile_is_single_monitor;
uint8_t num_h_tile, num_v_tile;
uint8_t tile_h_loc, tile_v_loc;
uint16_t tile_h_size, tile_v_size;
struct llist_node free_node;
};
Members
dev
- parent DRM device
kdev
- kernel device for sysfs attributes
attr
- sysfs attributes
head
- List of all connectors on a dev, linked from
drm_mode_config.connector_list
. Protected bydrm_mode_config.connector_list_lock
, but please only usedrm_connector_list_iter
to walk this list. base
- base KMS object
name
- human readable name, can be overwritten by the driver
mutex
- Lock for general connector state, but currently only protects
registered. Most of the connector state is still protected by
drm_mode_config.mutex
. index
- Compacted connector index, which matches the position inside the mode_config.list for drivers not supporting hot-add/removing. Can be used as an array index. It is invariant over the lifetime of the connector.
connector_type
- one of the DRM_MODE_CONNECTOR_<foo> types from drm_mode.h
connector_type_id
- index into connector type enum
interlace_allowed
- Can this connector handle interlaced modes? Only used by
drm_helper_probe_single_connector_modes()
for mode filtering. doublescan_allowed
- Can this connector handle doublescan? Only used by
drm_helper_probe_single_connector_modes()
for mode filtering. stereo_allowed
- Can this connector handle stereo modes? Only used by
drm_helper_probe_single_connector_modes()
for mode filtering. ycbcr_420_allowed
- This bool indicates if this connector is capable of handling YCBCR 420 output. While parsing the EDID blocks, its very helpful to know, if the source is capable of handling YCBCR 420 outputs.
registered
- Is this connector exposed (registered) with userspace? Protected by mutex.
modes
- Modes available on this connector (from
fill_modes()
+ user). Protected bydrm_mode_config.mutex
. status
- One of the drm_connector_status enums (connected, not, or unknown).
Protected by
drm_mode_config.mutex
. probed_modes
- These are modes added by probing with DDC or the BIOS, before
filtering is applied. Used by the probe helpers. Protected by
drm_mode_config.mutex
. 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
drm_display_info.width_mm
anddrm_display_info.height_mm
fields with the physical size of the display.Protected by
drm_mode_config.mutex
.funcs
- connector control functions
edid_blob_ptr
- DRM property containing EDID if present. Protected by
drm_mode_config.mutex
. This should be updated only by callingdrm_connector_update_edid_property()
. properties
- property tracking for this connector
scaling_mode_property
- Optional atomic property to control the
upscaling. See
drm_connector_attach_content_protection_property()
. content_protection_property
- DRM ENUM property for content
protection. See
drm_connector_attach_content_protection_property()
. path_blob_ptr
- DRM blob property data for the DP MST path property. This should only
be updated by calling
drm_connector_set_path_property()
. 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, without causing flickering even when the connector is in use. DACs should rarely do this without a lot of testing.
Set to 0 for connectors that don’t support connection status discovery.
dpms
- Current dpms state. For legacy drivers the
drm_connector_funcs.dpms
callback must update this. For atomic drivers, this is handled by the core atomic code, and drivers must only takedrm_crtc_state.active
into account. helper_private
- mid-layer private data
cmdline_mode
- mode line parsed from the kernel cmdline for this connector
force
- a DRM_FORCE_<foo> state for forced mode sets
override_edid
- has the EDID been overwritten through debugfs for testing?
encoder_ids
- Valid encoders for this connector. Please only use
drm_connector_for_each_possible_encoder()
to enumerate these. encoder
- Currently bound encoder driving this connector, if any.
Only really meaningful for non-atomic drivers. Atomic drivers should
instead look at
drm_connector_state.best_encoder
, and in case they need the CRTC driving this output,drm_connector_state.crtc
. eld
- EDID-like data, if present
latency_present
- AV delay info from ELD, if found
video_latency
- Video latency info from ELD, if found. [0]: progressive, [1]: interlaced
audio_latency
- audio latency info from ELD, if found [0]: progressive, [1]: interlaced
null_edid_counter
- track sinks that give us all zeros for the EDID. Needed to workaround some HW bugs where we get all 0s
bad_edid_counter
- track sinks that give us an EDID with invalid checksum
edid_corrupt
- Indicates whether the last read EDID was corrupt. Used in Displayport compliance testing - Displayport Link CTS Core 1.2 rev1.1 4.2.2.6
debugfs_entry
- debugfs directory for this connector
state
Current atomic state for this connector.
This is protected by
drm_mode_config.connection_mutex
. Note that nonblocking atomic commits access the current connector state without taking locks. Either by going through thestruct drm_atomic_state
pointers, seefor_each_oldnew_connector_in_state()
,for_each_old_connector_in_state()
andfor_each_new_connector_in_state()
. Or through careful ordering of atomic commit operations as implemented in the atomic helpers, seestruct drm_crtc_commit
.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.This should only be updated by calling
drm_connector_set_tile_property()
.has_tile
- is this connector connected to a tiled monitor
tile_group
- tile group for the connected monitor
tile_is_single_monitor
- whether the tile is one monitor housing
num_h_tile
- number of horizontal tiles in the tile group
num_v_tile
- number of vertical tiles in the tile group
tile_h_loc
- horizontal location of this tile
tile_v_loc
- vertical location of this tile
tile_h_size
- horizontal size of this tile.
tile_v_size
- vertical size of this tile.
free_node
- List used only by
drm_connector_list_iter
to be able to clean up a connector from any context, in conjunction withdrm_mode_config.connector_free_work
.
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_connector *
drm_connector_lookup
(struct drm_device * dev, struct drm_file * file_priv, uint32_t id)¶ lookup connector object
Parameters
struct drm_device * dev
- DRM device
struct drm_file * file_priv
- drm file to check for lease against.
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_connector_get
(struct drm_connector * connector)¶ acquire a connector reference
Parameters
struct drm_connector * connector
- DRM connector
Description
This function increments the connector’s refcount.
-
void
drm_connector_put
(struct drm_connector * connector)¶ release a connector reference
Parameters
struct drm_connector * connector
- DRM connector
Description
This function decrements the connector’s reference count and frees the object if the reference count drops to zero.
-
void
drm_connector_reference
(struct drm_connector * connector)¶ acquire a connector reference
Parameters
struct drm_connector * connector
- DRM connector
Description
This is a compatibility alias for drm_connector_get()
and should not be
used by new code.
-
void
drm_connector_unreference
(struct drm_connector * connector)¶ release a connector reference
Parameters
struct drm_connector * connector
- DRM connector
Description
This is a compatibility alias for drm_connector_put()
and should not be
used by new code.
-
struct
drm_tile_group
¶ Tile group metadata
Definition
struct drm_tile_group {
struct kref refcount;
struct drm_device *dev;
int id;
u8 group_data[8];
};
Members
refcount
- reference count
dev
- DRM device
id
- tile group id exposed to userspace
group_data
- Sink-private data identifying this group
Description
group_data corresponds to displayid vend/prod/serial for external screens with an EDID.
-
struct
drm_connector_list_iter
¶ connector_list iterator
Definition
struct drm_connector_list_iter {
};
Members
Description
This iterator tracks state needed to be able to walk the connector_list
within struct drm_mode_config. Only use together with
drm_connector_list_iter_begin()
, drm_connector_list_iter_end()
and
drm_connector_list_iter_next()
respectively the convenience macro
drm_for_each_connector_iter()
.
-
drm_for_each_connector_iter
(connector, iter)¶ connector_list iterator macro
Parameters
connector
struct drm_connector
pointer used as cursoriter
struct drm_connector_list_iter
Description
Note that connector is only valid within the list body, if you want to use
connector after calling drm_connector_list_iter_end()
then you need to grab
your own reference first using drm_connector_get()
.
-
drm_connector_for_each_possible_encoder
(connector, encoder, __i)¶ iterate connector’s possible encoders
Parameters
connector
struct drm_connector
pointerencoder
struct drm_encoder
pointer used as cursor__i
- int iteration cursor, for macro-internal use
-
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.
-
int
drm_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.
-
bool
drm_connector_has_possible_encoder
(struct drm_connector * connector, struct drm_encoder * encoder)¶ check if the connector and encoder are assosicated with each other
Parameters
struct drm_connector * connector
- the connector
struct drm_encoder * encoder
- the encoder
Return
True if encoder is one of the possible encoders for connector.
-
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
-
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.
-
void
drm_connector_list_iter_begin
(struct drm_device * dev, struct drm_connector_list_iter * iter)¶ initialize a connector_list iterator
Parameters
struct drm_device * dev
- DRM device
struct drm_connector_list_iter * iter
- connector_list iterator
Description
Sets iter up to walk the drm_mode_config.connector_list
of dev. iter
must always be cleaned up again by calling drm_connector_list_iter_end()
.
Iteration itself happens using drm_connector_list_iter_next()
or
drm_for_each_connector_iter()
.
-
struct drm_connector *
drm_connector_list_iter_next
(struct drm_connector_list_iter * iter)¶ return next connector
Parameters
struct drm_connector_list_iter * iter
- connector_list iterator
Description
Returns the next connector for iter, or NULL when the list walk has completed.
-
void
drm_connector_list_iter_end
(struct drm_connector_list_iter * iter)¶ tear down a connector_list iterator
Parameters
struct drm_connector_list_iter * iter
- connector_list iterator
Description
Tears down iter and releases any resources (like drm_connector
references)
acquired while walking the list. This must always be called, both when the
iteration completes fully or when it was aborted without walking the entire
list.
-
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.
-
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_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_connector_attach_content_type_property
(struct drm_connector * connector)¶ attach content-type property
Parameters
struct drm_connector * connector
- connector to attach content type property on.
Description
Called by a driver the first time a HDMI connector is made.
-
void
drm_hdmi_avi_infoframe_content_type
(struct hdmi_avi_infoframe * frame, const struct drm_connector_state * conn_state)¶ fill the HDMI AVI infoframe content type information, based on correspondent DRM property.
Parameters
struct hdmi_avi_infoframe * frame
- HDMI AVI infoframe
const struct drm_connector_state * conn_state
- DRM display connector state
-
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
- array of pointers to strings containing name of each format
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.
Atomic drivers should use drm_connector_attach_scaling_mode_property()
instead to correctly assign drm_connector_state.picture_aspect_ratio
in the atomic state.
-
int
drm_connector_attach_scaling_mode_property
(struct drm_connector * connector, u32 scaling_mode_mask)¶ attach atomic scaling mode property
Parameters
struct drm_connector * connector
- connector to attach scaling mode property on.
u32 scaling_mode_mask
- or’ed mask of BIT(
DRM_MODE_SCALE_
*).
Description
This is used to add support for scaling mode to atomic drivers.
The scaling mode will be set to drm_connector_state.picture_aspect_ratio
and can be used from drm_connector_helper_funcs->atomic_check
for validation.
This is the atomic version of drm_mode_create_scaling_mode_property()
.
Return
Zero on success, negative errno on failure.
-
int
drm_connector_attach_content_protection_property
(struct drm_connector * connector)¶ attach content protection property
Parameters
struct drm_connector * connector
- connector to attach CP property on.
Description
This is used to add support for content protection on select connectors. Content Protection is intentionally vague to allow for different underlying technologies, however it is most implemented by HDCP.
The content protection will be set to drm_connector_state.content_protection
Return
Zero on success, negative errno on failure.
-
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_content_type_property
(struct drm_device * dev)¶ create content type 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_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_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_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_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.
-
void
drm_connector_set_link_status_property
(struct drm_connector * connector, uint64_t link_status)¶ Set link status property of a connector
Parameters
struct drm_connector * connector
- drm connector
uint64_t link_status
- new value of link status property (0: Good, 1: Bad)
Description
In usual working scenario, this link status property will always be set to “GOOD”. If something fails during or after a mode set, the kernel driver may set this link status property to “BAD”. The caller then needs to send a hotplug uevent for userspace to re-check the valid modes through GET_CONNECTOR_IOCTL and retry modeset.
Note
Drivers cannot rely on userspace to support this property and issue a modeset. As such, they may choose to handle issues (like re-training a link) without userspace’s intervention.
The reason for adding this property is to handle link training failures, but it is not limited to DP or link training. For example, if we implement asynchronous setcrtc, this property can be used to report any failures in that.
-
int
drm_connector_init_panel_orientation_property
(struct drm_connector * connector, int width, int height)¶ initialize the connecters panel_orientation property
Parameters
struct drm_connector * connector
- connector for which to init the panel-orientation property.
int width
- width in pixels of the panel, used for panel quirk detection
int height
- height in pixels of the panel, used for panel quirk detection
Description
This function should only be called for built-in panels, after setting connector->display_info.panel_orientation first (if known).
This function will check for platform specific (e.g. DMI based) quirks overriding display_info.panel_orientation first, then if panel_orientation is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the “panel orientation” property to the connector.
Return
Zero on success, negative errno on failure.
-
void
drm_mode_put_tile_group
(struct drm_device * dev, struct drm_tile_group * tg)¶ drop a reference to a tile group.
Parameters
struct drm_device * dev
- DRM device
struct drm_tile_group * tg
- tile group to drop reference to.
Description
drop reference to tile group and free if 0.
-
struct drm_tile_group *
drm_mode_get_tile_group
(struct drm_device * dev, char topology)¶ get a reference to an existing tile group
Parameters
struct drm_device * dev
- DRM device
char topology
- 8-bytes unique per monitor.
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)¶ create a tile group from a displayid description
Parameters
struct drm_device * dev
- DRM device
char topology
- 8-bytes unique per monitor.
Description
Create a tile group for the unique monitor, and get a unique identifier for the tile group.
Return
new tile group or error.
Writeback Connectors¶
Writeback connectors are used to expose hardware which can write the output from a CRTC to a memory buffer. They are used and act similarly to other types of connectors, with some important differences:
- Writeback connectors don’t provide a way to output visually to the user.
- Writeback connectors are visible to userspace only when the client sets DRM_CLIENT_CAP_WRITEBACK_CONNECTORS.
- Writeback connectors don’t have EDID.
A framebuffer may only be attached to a writeback connector when the connector is attached to a CRTC. The WRITEBACK_FB_ID property which sets the framebuffer applies only to a single commit (see below). A framebuffer may not be attached while the CRTC is off.
Unlike with planes, when a writeback framebuffer is removed by userspace DRM makes no attempt to remove it from active use by the connector. This is because no method is provided to abort a writeback operation, and in any case making a new commit whilst a writeback is ongoing is undefined (see WRITEBACK_OUT_FENCE_PTR below). As soon as the current writeback is finished, the framebuffer will automatically no longer be in active use. As it will also have already been removed from the framebuffer list, there will be no way for any userspace application to retrieve a reference to it in the intervening period.
Writeback connectors have some additional properties, which userspace can use to query and control them:
- “WRITEBACK_FB_ID”:
- Write-only object property storing a DRM_MODE_OBJECT_FB: it stores the framebuffer to be written by the writeback connector. This property is similar to the FB_ID property on planes, but will always read as zero and is not preserved across commits. Userspace must set this property to an output buffer every time it wishes the buffer to get filled.
- “WRITEBACK_PIXEL_FORMATS”:
- Immutable blob property to store the supported pixel formats table. The data is an array of u32 DRM_FORMAT_* fourcc values. Userspace can use this blob to find out what pixel formats are supported by the connector’s writeback engine.
- “WRITEBACK_OUT_FENCE_PTR”:
- Userspace can use this property to provide a pointer for the kernel to fill with a sync_file file descriptor, which will signal once the writeback is finished. The value should be the address of a 32-bit signed integer, cast to a u64. Userspace should wait for this fence to signal before making another commit affecting any of the same CRTCs, Planes or Connectors. Failure to do so will result in undefined behaviour. For this reason it is strongly recommended that all userspace applications making use of writeback connectors always retrieve an out-fence for the commit and use it appropriately. From userspace, this property will always read as zero.
-
int
drm_writeback_connector_init
(struct drm_device * dev, struct drm_writeback_connector * wb_connector, const struct drm_connector_funcs * con_funcs, const struct drm_encoder_helper_funcs * enc_helper_funcs, const u32 * formats, int n_formats)¶ Initialize a writeback connector and its properties
Parameters
struct drm_device * dev
- DRM device
struct drm_writeback_connector * wb_connector
- Writeback connector to initialize
const struct drm_connector_funcs * con_funcs
- Connector funcs vtable
const struct drm_encoder_helper_funcs * enc_helper_funcs
- Encoder helper funcs vtable to be used by the internal encoder
const u32 * formats
- Array of supported pixel formats for the writeback engine
int n_formats
- Length of the formats array
Description
This function creates the writeback-connector-specific properties if they have not been already created, initializes the connector as type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property values. It will also create an internal encoder associated with the drm_writeback_connector and set it to use the enc_helper_funcs vtable for the encoder helper.
Drivers should always use this function instead of drm_connector_init()
to
set up writeback connectors.
Return
0 on success, or a negative error code
-
void
drm_writeback_queue_job
(struct drm_writeback_connector * wb_connector, struct drm_writeback_job * job)¶ Queue a writeback job for later signalling
Parameters
struct drm_writeback_connector * wb_connector
- The writeback connector to queue a job on
struct drm_writeback_job * job
- The job to queue
Description
This function adds a job to the job_queue for a writeback connector. It should be considered to take ownership of the writeback job, and so any other references to the job must be cleared after calling this function.
Drivers must ensure that for a given writeback connector, jobs are queued in exactly the same order as they will be completed by the hardware (and signaled via drm_writeback_signal_completion).
For every call to drm_writeback_queue_job()
there must be exactly one call to
drm_writeback_signal_completion()
See also: drm_writeback_signal_completion()
-
void
drm_writeback_signal_completion
(struct drm_writeback_connector * wb_connector, int status)¶ Signal the completion of a writeback job
Parameters
struct drm_writeback_connector * wb_connector
- The writeback connector whose job is complete
int status
- Status code to set in the writeback out_fence (0 for success)
Description
Drivers should call this to signal the completion of a previously queued writeback job. It should be called as soon as possible after the hardware has finished writing, and may be called from interrupt context. It is the driver’s responsibility to ensure that for a given connector, the hardware completes writeback jobs in the same order as they are queued.
Unless the driver is holding its own reference to the framebuffer, it must not be accessed after calling this function.
See also: drm_writeback_queue_job()
Encoder Abstraction¶
Encoders represent the connecting element between the CRTC (as the overall
pixel pipeline, represented by struct drm_crtc
) and the connectors (as the
generic sink entity, represented by struct drm_connector
). An encoder takes
pixel data from a CRTC and converts it to a format suitable for any attached
connector. Encoders are objects exposed to userspace, originally to allow
userspace to infer cloning and connector/CRTC restrictions. Unfortunately
almost all drivers get this wrong, making the uabi pretty much useless. On
top of that the exposed restrictions are too simple for today’s hardware, and
the recommended way to infer restrictions is by using the
DRM_MODE_ATOMIC_TEST_ONLY flag for the atomic IOCTL.
Otherwise encoders aren’t used in the uapi at all (any modeset request from
userspace directly connects a connector with a CRTC), drivers are therefore
free to use them however they wish. Modeset helper libraries make strong use
of encoders to facilitate code sharing. But for more complex settings it is
usually better to move shared code into a separate drm_bridge
. Compared to
encoders, bridges also have the benefit of being purely an internal
abstraction since they are not exposed to userspace at all.
Encoders are initialized with drm_encoder_init()
and cleaned up using
drm_encoder_cleanup()
.
Encoder Functions Reference¶
-
struct
drm_encoder_funcs
¶ encoder controls
Definition
struct drm_encoder_funcs {
void (*reset)(struct drm_encoder *encoder);
void (*destroy)(struct drm_encoder *encoder);
int (*late_register)(struct drm_encoder *encoder);
void (*early_unregister)(struct drm_encoder *encoder);
};
Members
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. 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. late_register
This optional hook can be used to register additional userspace interfaces attached to the encoder like debugfs interfaces. It is called late in the driver load sequence from
drm_dev_register()
. Everything added from this callback should be unregistered in the early_unregister callback.Returns:
0 on success, or a negative error code on failure.
early_unregister
- This optional hook should be used to unregister the additional
userspace interfaces attached to the encoder from
late_register. It is called from
drm_dev_unregister()
, early in the driver unload sequence to disable userspace access before data structures are torndown.
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;
unsigned index;
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
dev
- parent DRM device
head
- list management
base
- base KMS object
name
- human readable name, can be overwritten by the driver
encoder_type
One of the DRM_MODE_ENCODER_<foo> types in drm_mode.h. The following encoder types are defined thus far:
- 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, or in general any panel with a proprietary parallel connector.
- DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video, Component, SCART).
- DRM_MODE_ENCODER_VIRTUAL for virtual machine displays
- DRM_MODE_ENCODER_DSI for panels connected using the DSI serial bus.
- DRM_MODE_ENCODER_DPI for panels connected using the DPI parallel bus.
- DRM_MODE_ENCODER_DPMST for special fake encoders used to allow mutliple DP MST streams to share one physical encoder.
index
- Position inside the mode_config.list, can be used as an array index. It is invariant over the lifetime of the encoder.
possible_crtcs
Bitmask of potential CRTC bindings, using
drm_crtc_index()
as the index into the bitfield. The driver must set the bits for alldrm_crtc
objects this encoder can be connected to before callingdrm_encoder_init()
.In reality almost every driver gets this wrong.
Note that since CRTC objects can’t be hotplugged the assigned indices are stable and hence known before registering all objects.
possible_clones
Bitmask of potential sibling encoders for cloning, using
drm_encoder_index()
as the index into the bitfield. The driver must set the bits for alldrm_encoder
objects which can clone adrm_crtc
together with this encoder before callingdrm_encoder_init()
. Drivers should set the bit representing the encoder itself, too. Cloning bits should be set such that when two encoders can be used in a cloned configuration, they both should have each another bits set.In reality almost every driver gets this wrong.
Note that since encoder objects can’t be hotplugged the assigned indices are stable and hence known before registering all objects.
crtc
- Currently bound CRTC, only really meaningful for non-atomic
drivers. Atomic drivers should instead check
drm_connector_state.crtc
. bridge
- bridge associated to the encoder
funcs
- control functions
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.
-
unsigned int
drm_encoder_index
(const struct drm_encoder * encoder)¶ find the index of a registered encoder
Parameters
const 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.
-
u32
drm_encoder_mask
(const struct drm_encoder * encoder)¶ find the mask of a registered ENCODER
Parameters
const struct drm_encoder * encoder
- encoder to find mask for
Description
Given a registered encoder, return the mask bit of that encoder for an encoder’s possible_clones field.
-
bool
drm_encoder_crtc_ok
(struct drm_encoder * encoder, struct drm_crtc * crtc)¶ can a given crtc drive a given encoder?
Parameters
struct drm_encoder * encoder
- encoder to test
struct drm_crtc * crtc
- crtc to test
Description
Returns false if encoder can’t be driven by crtc, true otherwise.
-
struct drm_encoder *
drm_encoder_find
(struct drm_device * dev, struct drm_file * file_priv, uint32_t id)¶ find a
drm_encoder
Parameters
struct drm_device * dev
- DRM device
struct drm_file * file_priv
- drm file to check for lease against.
uint32_t id
- encoder id
Description
Returns the encoder with id, NULL if it doesn’t exist. Simple wrapper around
drm_mode_object_find()
.
-
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.
-
drm_for_each_encoder
(encoder, dev)¶ iterate over all encoders
Parameters
encoder
- the loop cursor
dev
- the DRM device
Description
Iterate over all encoders of dev.
-
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. At driver unload time drm_encoder_cleanup()
should be
called from the driver’s drm_encoder_funcs.destroy
hook.
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.
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.
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_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 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 struct drm_modeset_lock
and struct drm_modeset_acquire_ctx
.
For basic principles of ww_mutex
, see: Documentation/locking/ww-mutex-design.txt
The basic usage pattern is to:
drm_modeset_acquire_init(ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE)
retry:
foreach (lock in random_ordered_set_of_locks) {
ret = drm_modeset_lock(lock, ctx)
if (ret == -EDEADLK) {
ret = drm_modeset_backoff(ctx);
if (!ret)
goto retry;
}
if (ret)
goto out;
}
... do stuff ...
out:
drm_modeset_drop_locks(ctx);
drm_modeset_acquire_fini(ctx);
If all that is needed is a single modeset lock, then the struct
drm_modeset_acquire_ctx
is not needed and the locking can be simplified
by passing a NULL instead of ctx in the drm_modeset_lock()
call or
calling drm_modeset_lock_single_interruptible()
. To unlock afterwards
call drm_modeset_unlock()
.
On top of these per-object locks using ww_mutex
there’s also an overall
drm_mode_config.mutex
, 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;
bool interruptible;
};
Members
ww_ctx
- base acquire ctx
contended
- used internally for -EDEADLK handling
locked
- list of held locks
trylock_only
- trylock mode used in atomic contexts/panic notifiers
interruptible
- whether interruptible locking should be used.
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
mutex
- resource locking
head
- used to hold it’s place on
drm_atomi_state.locked
list when part of an atomic update
Description
Used for locking CRTCs and other modeset resources.
-
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 drm_device.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 drm_device.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_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
- 0 or
DRM_MODESET_ACQUIRE_INTERRUPTIBLE
Description
When passing DRM_MODESET_ACQUIRE_INTERRUPTIBLE
to flags,
all calls to drm_modeset_lock()
will perform an interruptible
wait.
-
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.
-
int
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.
This function returns 0 on success, or -ERESTARTSYS if this context
is initialized with DRM_MODESET_ACQUIRE_INTERRUPTIBLE
and the
wait has been interrupted.
-
void
drm_modeset_lock_init
(struct drm_modeset_lock * lock)¶ initialize lock
Parameters
struct drm_modeset_lock * lock
- lock to init
-
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()
.
If the ctx is not NULL and initialized with
DRM_MODESET_ACQUIRE_INTERRUPTIBLE
, this function will fail with
-ERESTARTSYS when interrupted.
If ctx is NULL then the function call behaves like a normal,
uninterruptible non-nesting mutex_lock()
call.
-
int
drm_modeset_lock_single_interruptible
(struct drm_modeset_lock * lock)¶ take a single modeset lock
Parameters
struct drm_modeset_lock * lock
- lock to take
Description
This function behaves as drm_modeset_lock()
with a NULL context,
but performs interruptible waits.
This function returns 0 on success, or -ERESTARTSYS when interrupted.
-
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 drm_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.
KMS Properties¶
Property Types and Blob Property Support¶
Properties as represented by drm_property
are used to extend the modeset
interface exposed to userspace. For the atomic modeset IOCTL properties are
even the only way to transport metadata about the desired new modeset
configuration from userspace to the kernel. Properties have a well-defined
value range, which is enforced by the drm core. See the documentation of the
flags member of struct drm_property
for an overview of the different
property types and ranges.
Properties don’t store the current value directly, but need to be
instatiated by attaching them to a drm_mode_object
with
drm_object_attach_property()
.
Property values are only 64bit. To support bigger piles of data (like gamma
tables, color correction matrices or large structures) a property can instead
point at a drm_property_blob
with that additional data.
Properties are defined by their symbolic name, userspace must keep a per-object mapping from those names to the property ID used in the atomic IOCTL and in the get/set property IOCTL.
-
struct
drm_property_enum
¶ symbolic values for enumerations
Definition
struct drm_property_enum {
uint64_t value;
struct list_head head;
char name[DRM_PROP_NAME_LEN];
};
Members
value
- numeric property value for this enum entry
head
- list of enum values, linked to
drm_property.enum_list
name
- symbolic name for the enum
Description
For enumeration and bitmask properties this structure stores the symbolic decoding for each value. This is used for example for the rotation property.
-
struct
drm_property
¶ modeset object property
Definition
struct drm_property {
struct list_head head;
struct drm_mode_object base;
uint32_t flags;
char name[DRM_PROP_NAME_LEN];
uint32_t num_values;
uint64_t *values;
struct drm_device *dev;
struct list_head enum_list;
};
Members
head
- per-device list of properties, for cleanup.
base
- base KMS object
flags
Property flags and type. A property needs to be one of the following types:
- DRM_MODE_PROP_RANGE
- Range properties report their minimum and maximum admissible unsigned values.
The KMS core verifies that values set by application fit in that
range. The range is unsigned. Range properties are created using
drm_property_create_range()
. - DRM_MODE_PROP_SIGNED_RANGE
- Range properties report their minimum and maximum admissible unsigned values.
The KMS core verifies that values set by application fit in that
range. The range is signed. Range properties are created using
drm_property_create_signed_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. Enum
properties are created using
drm_property_create_enum()
. - 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. Bitmask properties are created using
drm_property_create_bitmask()
. - DRM_MODE_PROB_OBJECT
Object properties are used to link modeset objects. This is used extensively in the atomic support to create the display pipeline, by linking
drm_framebuffer
todrm_plane
,drm_plane
todrm_crtc
anddrm_connector
todrm_crtc
. An object property can only link to a specific type ofdrm_mode_object
, this limit is enforced by the core. Object properties are created usingdrm_property_create_object()
.Object properties work like blob properties, but in a more general fashion. They are limited to atomic drivers and must have the DRM_MODE_PROP_ATOMIC flag set.
- 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 created by calling
drm_property_create()
with DRM_MODE_PROP_BLOB as the type.Actual blob objects to contain blob data are created using
drm_property_create_blob()
, or through the corresponding IOCTL.Besides the built-in limit to only accept blob objects blob properties work exactly like object properties. The only reasons blob properties exist is backwards compatibility with existing userspace.
In addition a property can have any combination of the below flags:
- DRM_MODE_PROP_ATOMIC
- Set for properties which encode atomic modeset state. Such properties are not exposed to legacy userspace.
- DRM_MODE_PROP_IMMUTABLE
- Set for properties whose values cannot be changed by userspace. The kernel is allowed to update the value of these properties. This is generally used to expose probe state to userspace, e.g. the EDID, or the connector path property on DP MST sinks.
name
- symbolic name of the properties
num_values
- size of the values array.
values
- Array with limits and values for the property. The interpretation of these limits is dependent upon the type per flags.
dev
- DRM device
enum_list
- List of
drm_prop_enum_list
structures with the symbolic names for enum and bitmask values.
Description
This structure represent a modeset object property. It combines both the name
of the property with the set of permissible values. This means that when a
driver wants to use a property with the same name on different objects, but
with different value ranges, then it must create property for each one. An
example would be rotation of drm_plane
, when e.g. the primary plane cannot
be rotated. But if both the name and the value range match, then the same
property structure can be instantiated multiple times for the same object.
Userspace must be able to cope with this and cannot assume that the same
symbolic property will have the same modeset object ID on all modeset
objects.
Properties are created by one of the special functions, as explained in detail in the flags structure member.
To actually expose a property it must be attached to each object using
drm_object_attach_property()
. Currently properties can only be attached to
drm_connector
, drm_crtc
and drm_plane
.
Properties are also used as the generic metadatatransport for the atomic IOCTL. Everything that was set directly in structures in the legacy modeset IOCTLs (like the plane source or destination windows, or e.g. the links to the CRTC) is exposed as a property with the DRM_MODE_PROP_ATOMIC flag set.
-
struct
drm_property_blob
¶ Blob data for
drm_property
Definition
struct drm_property_blob {
struct drm_mode_object base;
struct drm_device *dev;
struct list_head head_global;
struct list_head head_file;
size_t length;
void *data;
};
Members
base
- base KMS object
dev
- DRM device
head_global
- entry on the global blob list in
drm_mode_config.property_blob_list
. head_file
- entry on the per-file blob list in
drm_file.blobs
list. length
- size of the blob in bytes, invariant over the lifetime of the object
data
- actual data, embedded at the end of this structure
Description
Blobs are used to store bigger values than what fits directly into the 64
bits available for a drm_property
.
Blobs are reference counted using drm_property_blob_get()
and
drm_property_blob_put()
. They are created using drm_property_create_blob()
.
-
bool
drm_property_type_is
(struct drm_property * property, uint32_t type)¶ check the type of a property
Parameters
struct drm_property * property
- property to check
uint32_t type
- property type to compare with
Description
This is a helper function becauase the uapi encoding of property types is a bit special for historical reasons.
-
struct drm_property *
drm_property_find
(struct drm_device * dev, struct drm_file * file_priv, uint32_t id)¶ find property object
Parameters
struct drm_device * dev
- DRM device
struct drm_file * file_priv
- drm file to check for lease against.
uint32_t id
- property object id
Description
This function looks up the property object specified by id and returns it.
-
struct drm_property *
drm_property_create
(struct drm_device * dev, u32 flags, const char * name, int num_values)¶ create a new property type
Parameters
struct drm_device * dev
- drm device
u32 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()
, which is done automatically when
calling drm_mode_config_cleanup()
.
Return
A pointer to the newly created property on success, NULL on failure.
-
struct drm_property *
drm_property_create_enum
(struct drm_device * dev, u32 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
u32 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()
, which is done automatically when
calling drm_mode_config_cleanup()
.
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, u32 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
u32 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()
, which is done automatically when
calling drm_mode_config_cleanup()
.
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, u32 flags, const char * name, uint64_t min, uint64_t max)¶ create a new unsigned ranged property type
Parameters
struct drm_device * dev
- drm device
u32 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()
, which is done automatically when
calling drm_mode_config_cleanup()
.
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, u32 flags, const char * name, int64_t min, int64_t max)¶ create a new signed ranged property type
Parameters
struct drm_device * dev
- drm device
u32 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()
, which is done automatically when
calling drm_mode_config_cleanup()
.
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, u32 flags, const char * name, uint32_t type)¶ create a new object property type
Parameters
struct drm_device * dev
- drm device
u32 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()
, which is done automatically when
calling drm_mode_config_cleanup()
.
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, u32 flags, const char * name)¶ create a new boolean property type
Parameters
struct drm_device * dev
- drm device
u32 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()
, which is done automatically when
calling drm_mode_config_cleanup()
.
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, uint64_t value, const char * name)¶ add a possible value to an enumeration property
Parameters
struct drm_property * property
- enumeration property to change
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.
-
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. Note that blob properties are meant to be invariant, hence the data must be filled out before the blob is used as the value of any property.
Return
New blob property with a single reference on success, or an ERR_PTR value on failure.
-
void
drm_property_blob_put
(struct drm_property_blob * blob)¶ release a blob property reference
Parameters
struct drm_property_blob * blob
- DRM blob property
Description
Releases a reference to a blob property. May free the object.
-
struct drm_property_blob *
drm_property_blob_get
(struct drm_property_blob * blob)¶ acquire blob property reference
Parameters
struct drm_property_blob * blob
- DRM blob property
Description
Acquires a reference to an existing blob property. Returns blob, which allows this to be used as a shorthand in assignments.
-
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_blob_put()
.
Return
NULL on failure, pointer to the blob on success.
-
int
drm_property_replace_global_blob
(struct drm_device * dev, struct drm_property_blob ** replace, size_t length, const void * data, struct drm_mode_object * obj_holds_id, struct drm_property * prop_holds_id)¶ replace existing blob property
Parameters
struct drm_device * dev
- drm device
struct drm_property_blob ** replace
- location of blob property pointer to be replaced
size_t length
- length of data for new blob, or 0 for no data
const void * data
- content for new blob, or NULL for no data
struct drm_mode_object * obj_holds_id
- optional object for property holding blob ID
struct drm_property * prop_holds_id
- optional property holding blob ID return 0 on success or error on failure
Description
This function will replace a global property in the blob list, optionally updating a property which holds the ID of that property.
If length is 0 or data is NULL, no new blob will be created, and the holding property, if specified, will be set to 0.
Access to the replace pointer is assumed to be protected by the caller, e.g. by holding the relevant modesetting object lock for its parent.
For example, a drm_connector has a ‘PATH’ property, which contains the ID of a blob property with the value of the MST path information. Calling this function with replace pointing to the connector’s path_blob_ptr, length and data set for the new path information, obj_holds_id set to the connector’s base object, and prop_holds_id set to the path property name, will perform a completely atomic update. The access to path_blob_ptr is protected by the caller holding a lock on the connector.
-
bool
drm_property_replace_blob
(struct drm_property_blob ** blob, struct drm_property_blob * new_blob)¶ 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
Return
true if the blob was in fact replaced.
Standard Connector Properties¶
DRM connectors have a few standardized properties:
- EDID:
- Blob property which contains the current EDID read from the sink. This
is useful to parse sink identification information like vendor, model
and serial. Drivers should update this property by calling
drm_connector_update_edid_property()
, usually after having parsed the EDID usingdrm_add_edid_modes()
. Userspace cannot change this property. - DPMS:
Legacy property for setting the power state of the connector. For atomic drivers this is only provided for backwards compatibility with existing drivers, it remaps to controlling the “ACTIVE” property on the CRTC the connector is linked to. Drivers should never set this property directly, it is handled by the DRM core by calling the
drm_connector_funcs.dpms
callback. For atomic drivers the remapping to the “ACTIVE” property is implemented in the DRM core. This is the only standard connector property that userspace can change.Note that this property cannot be set through the MODE_ATOMIC ioctl, userspace must use “ACTIVE” on the CRTC instead.
WARNING:
For userspace also running on legacy drivers the “DPMS” semantics are a lot more complicated. First, userspace cannot rely on the “DPMS” value returned by the GETCONNECTOR actually reflecting reality, because many drivers fail to update it. For atomic drivers this is taken care of in
drm_atomic_helper_update_legacy_modeset_state()
.The second issue is that the DPMS state is only well-defined when the connector is connected to a CRTC. In atomic the DRM core enforces that “ACTIVE” is off in such a case, no such checks exists for “DPMS”.
Finally, when enabling an output using the legacy SETCONFIG ioctl then “DPMS” is forced to ON. But see above, that might not be reflected in the software value on legacy drivers.
Summarizing: Only set “DPMS” when the connector is known to be enabled, assume that a successful SETCONFIG call also sets “DPMS” to on, and never read back the value of “DPMS” because it can be incorrect.
- PATH:
- Connector path property to identify how this sink is physically
connected. Used by DP MST. This should be set by calling
drm_connector_set_path_property()
, in the case of DP MST with the path property the MST manager created. Userspace cannot change this property. - TILE:
- Connector tile group property to indicate how a set of DRM connector
compose together into one logical screen. This is used by both high-res
external screens (often only using a single cable, but exposing multiple
DP MST sinks), or high-res integrated panels (like dual-link DSI) which
are not gen-locked. Note that 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 both
drm_crtc
anddrm_plane
if needed. Drivers should update this value usingdrm_connector_set_tile_property()
. Userspace cannot change this property. - link-status:
- Connector link-status property to indicate the status of link. The
default value of link-status is “GOOD”. If something fails during or
after modeset, the kernel driver may set this to “BAD” and issue a
hotplug uevent. Drivers should update this value using
drm_connector_set_link_status_property()
. - non_desktop:
- Indicates the output should be ignored for purposes of displaying a standard desktop environment or console. This is most likely because the output device is not rectilinear.
- Content Protection:
This property is used by userspace to request the kernel protect future content communicated over the link. When requested, kernel will apply the appropriate means of protection (most often HDCP), and use the property to tell userspace the protection is active.
Drivers can set this up by calling
drm_connector_attach_content_protection_property()
on initialization.The value of this property can be one of the following:
- DRM_MODE_CONTENT_PROTECTION_UNDESIRED = 0
- The link is not protected, content is transmitted in the clear.
- DRM_MODE_CONTENT_PROTECTION_DESIRED = 1
- Userspace has requested content protection, but the link is not currently protected. When in this state, kernel should enable Content Protection as soon as possible.
- DRM_MODE_CONTENT_PROTECTION_ENABLED = 2
- Userspace has requested content protection, and the link is protected. Only the driver can set the property to this value. If userspace attempts to set to ENABLED, kernel will return -EINVAL.
A few guidelines:
- DESIRED state should be preserved until userspace de-asserts it by setting the property to UNDESIRED. This means ENABLED should only transition to UNDESIRED when the user explicitly requests it.
- If the state is DESIRED, kernel should attempt to re-authenticate the link whenever possible. This includes across disable/enable, dpms, hotplug, downstream device changes, link status failures, etc..
- Userspace is responsible for polling the property to determine when the value transitions from ENABLED to DESIRED. This signifies the link is no longer protected and userspace should take appropriate action (whatever that might be).
Connectors also have one standardized atomic property:
- CRTC_ID:
- Mode object ID of the
drm_crtc
this connector should be connected to.
Connectors for LCD panels may also have one standardized property:
- panel orientation:
- On some devices the LCD panel is mounted in the casing in such a way
that the up/top side of the panel does not match with the top side of
the device. Userspace can use this property to check for this.
Note that input coordinates from touchscreens (input devices with
INPUT_PROP_DIRECT) will still map 1:1 to the actual LCD panel
coordinates, so if userspace rotates the picture to adjust for
the orientation it must also apply the same transformation to the
touchscreen input coordinates. This property is initialized by calling
drm_connector_init_panel_orientation_property()
. - scaling mode:
This property defines how a non-native mode is upscaled to the native mode of an LCD panel:
- None:
- No upscaling happens, scaling is left to the panel. Not all drivers expose this mode.
- Full:
- The output is upscaled to the full resolution of the panel, ignoring the aspect ratio.
- Center:
- No upscaling happens, the output is centered within the native resolution the panel.
- Full aspect:
- The output is upscaled to maximize either the width or height while retaining the aspect ratio.
This property should be set up by calling
drm_connector_attach_scaling_mode_property()
. Note that drivers can also expose this property to external outputs, in which case they must support “None”, which should be the default (since external screens have a built-in scaler).
HDMI Specific Connector Properties¶
- content type (HDMI specific):
Indicates content type setting to be used in HDMI infoframes to indicate content type for the external device, so that it adjusts it’s display settings accordingly.
The value of this property can be one of the following:
- No Data:
- Content type is unknown
- Graphics:
- Content type is graphics
- Photo:
- Content type is photo
- Cinema:
- Content type is cinema
- Game:
- Content type is game
Drivers can set up this property by calling
drm_connector_attach_content_type_property()
. Decoding to infoframe values is done throughdrm_hdmi_avi_infoframe_content_type()
.
Plane Composition Properties¶
The basic plane composition model supported by standard plane properties only
has a source rectangle (in logical pixels within the drm_framebuffer
), with
sub-pixel accuracy, which is scaled up to a pixel-aligned destination
rectangle in the visible area of a drm_crtc
. The visible area of a CRTC is
defined by the horizontal and vertical visible pixels (stored in hdisplay
and vdisplay) of the requested mode (stored in drm_crtc_state.mode
). These
two rectangles are both stored in the drm_plane_state
.
For the atomic ioctl the following standard (atomic) properties on the plane object encode the basic plane composition model:
- SRC_X:
- X coordinate offset for the source rectangle within the
drm_framebuffer
, in 16.16 fixed point. Must be positive. - SRC_Y:
- Y coordinate offset for the source rectangle within the
drm_framebuffer
, in 16.16 fixed point. Must be positive. - SRC_W:
- Width for the source rectangle within the
drm_framebuffer
, in 16.16 fixed point. SRC_X plus SRC_W must be within the width of the source framebuffer. Must be positive. - SRC_H:
- Height for the source rectangle within the
drm_framebuffer
, in 16.16 fixed point. SRC_Y plus SRC_H must be within the height of the source framebuffer. Must be positive. - CRTC_X:
- X coordinate offset for the destination rectangle. Can be negative.
- CRTC_Y:
- Y coordinate offset for the destination rectangle. Can be negative.
- CRTC_W:
- Width for the destination rectangle. CRTC_X plus CRTC_W can extend past
the currently visible horizontal area of the
drm_crtc
. - CRTC_H:
- Height for the destination rectangle. CRTC_Y plus CRTC_H can extend past
the currently visible vertical area of the
drm_crtc
. - FB_ID:
- Mode object ID of the
drm_framebuffer
this plane should scan out. - CRTC_ID:
- Mode object ID of the
drm_crtc
this plane should be connected to.
Note that the source rectangle must fully lie within the bounds of the
drm_framebuffer
. The destination rectangle can lie outside of the visible
area of the current mode of the CRTC. It must be apprpriately clipped by the
driver, which can be done by calling drm_plane_helper_check_update()
. Drivers
are also allowed to round the subpixel sampling positions appropriately, but
only to the next full pixel. No pixel outside of the source rectangle may
ever be sampled, which is important when applying more sophisticated
filtering than just a bilinear one when scaling. The filtering mode when
scaling is unspecified.
On top of this basic transformation additional properties can be exposed by the driver:
- alpha:
- Alpha is setup with
drm_plane_create_alpha_property()
. It controls the plane-wide opacity, from transparent (0) to opaque (0xffff). It can be combined with pixel alpha. The pixel values in the framebuffers are expected to not be pre-multiplied by the global alpha associated to the plane. - rotation:
- Rotation is set up with
drm_plane_create_rotation_property()
. It adds a rotation and reflection step between the source and destination rectangles. Without this property the rectangle is only scaled, but not rotated or reflected. - zpos:
- Z position is set up with
drm_plane_create_zpos_immutable_property()
anddrm_plane_create_zpos_property()
. It controls the visibility of overlapping planes. Without this property the primary plane is always below the cursor plane, and ordering between all other planes is undefined.
Note that all the property extensions described here apply either to the plane or the CRTC (e.g. for the background color, which currently is not exposed and assumed to be black).
Parameters
struct drm_plane * plane
- drm plane
Description
This function creates a generic, mutable, alpha property and enables support for it in the DRM core. It is attached to plane.
The alpha property will be allowed to be within the bounds of 0 (transparent) to 0xffff (opaque).
Return
0 on success, negative error code on failure.
-
int
drm_plane_create_rotation_property
(struct drm_plane * plane, unsigned int rotation, unsigned int supported_rotations)¶ create a new rotation property
Parameters
struct drm_plane * plane
- drm plane
unsigned int rotation
- initial value of the rotation property
unsigned int supported_rotations
- bitmask of supported rotations and reflections
Description
This creates a new property with the selected support for transformations.
Since a rotation by 180° degress is the same as reflecting both along the x
and the y axis the rotation property is somewhat redundant. Drivers can use
drm_rotation_simplify()
to normalize values of this property.
The property exposed to userspace is a bitmask property (see
drm_property_create_bitmask()
) called “rotation” and has the following
bitmask enumaration values:
- DRM_MODE_ROTATE_0:
- “rotate-0”
- DRM_MODE_ROTATE_90:
- “rotate-90”
- DRM_MODE_ROTATE_180:
- “rotate-180”
- DRM_MODE_ROTATE_270:
- “rotate-270”
- DRM_MODE_REFLECT_X:
- “reflect-x”
- DRM_MODE_REFLECT_Y:
- “reflect-y”
Rotation is the specified amount in degrees in counter clockwise direction, the X and Y axis are within the source rectangle, i.e. the X/Y axis before rotation. After reflection, the rotation is applied to the image sampled from the source rectangle, before scaling it to fit the destination rectangle.
-
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_MODE_REFLECT_X one could call this function like this:
- drm_rotation_simplify(rotation, DRM_MODE_ROTATE_0 |
- DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_Y);
to eliminate the DRM_MODE_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.
-
int
drm_plane_create_zpos_property
(struct drm_plane * plane, unsigned int zpos, unsigned int min, unsigned int max)¶ create mutable zpos property
Parameters
struct drm_plane * plane
- drm plane
unsigned int zpos
- initial value of zpos property
unsigned int min
- minimal possible value of zpos property
unsigned int max
- maximal possible value of zpos property
Description
This function initializes generic mutable zpos property and enables support
for it in drm core. Drivers can then attach this property to planes to enable
support for configurable planes arrangement during blending operation.
Drivers that attach a mutable zpos property to any plane should call the
drm_atomic_normalize_zpos()
helper during their implementation of
drm_mode_config_funcs.atomic_check()
, which will update the normalized zpos
values and store them in drm_plane_state.normalized_zpos
. Usually min
should be set to 0 and max to maximal number of planes for given crtc - 1.
If zpos of some planes cannot be changed (like fixed background or
cursor/topmost planes), driver should adjust min/max values and assign those
planes immutable zpos property with lower or higher values (for more
information, see drm_plane_create_zpos_immutable_property()
function). In such
case driver should also assign proper initial zpos values for all planes in
its plane_reset()
callback, so the planes will be always sorted properly.
See also drm_atomic_normalize_zpos()
.
The property exposed to userspace is called “zpos”.
Return
Zero on success, negative errno on failure.
-
int
drm_plane_create_zpos_immutable_property
(struct drm_plane * plane, unsigned int zpos)¶ create immuttable zpos property
Parameters
struct drm_plane * plane
- drm plane
unsigned int zpos
- value of zpos property
Description
This function initializes generic immutable zpos property and enables
support for it in drm core. Using this property driver lets userspace
to get the arrangement of the planes for blending operation and notifies
it that the hardware (or driver) doesn’t support changing of the planes’
order. For mutable zpos see drm_plane_create_zpos_property()
.
The property exposed to userspace is called “zpos”.
Return
Zero on success, negative errno on failure.
-
int
drm_atomic_normalize_zpos
(struct drm_device * dev, struct drm_atomic_state * state)¶ calculate normalized zpos values for all crtcs
Parameters
struct drm_device * dev
- DRM device
struct drm_atomic_state * state
- atomic state of DRM device
Description
This function calculates normalized zpos value for all modified planes in the provided atomic state of DRM device.
For every CRTC this function checks new states of all planes assigned to
it and calculates normalized zpos value for these planes. Planes are compared
first by their zpos values, then by plane id (if zpos is equal). The plane
with lowest zpos value is at the bottom. The drm_plane_state.normalized_zpos
is then filled with unique values from 0 to number of active planes in crtc
minus one.
RETURNS Zero for success or -errno
Color Management Properties¶
Color management or color space adjustments is supported through a set of 5
properties on the drm_crtc
object. They are set up by calling
drm_crtc_enable_color_mgmt()
.
- “DEGAMMA_LUT”:
Blob property to set the degamma lookup table (LUT) mapping pixel data from the framebuffer before it is given to the transformation matrix. The data is interpreted as an array of
struct drm_color_lut
elements. Hardware might choose not to use the full precision of the LUT elements nor use all the elements of the LUT (for example the hardware might choose to interpolate between LUT[0] and LUT[4]).Setting this to NULL (blob property value set to 0) means a linear/pass-thru gamma table should be used. This is generally the driver boot-up state too. Drivers can access this blob through
drm_crtc_state.degamma_lut
.- “DEGAMMA_LUT_SIZE”:
- Unsinged range property to give the size of the lookup table to be set on the DEGAMMA_LUT property (the size depends on the underlying hardware). If drivers support multiple LUT sizes then they should publish the largest size, and sub-sample smaller sized LUTs (e.g. for split-gamma modes) appropriately.
- “CTM”:
Blob property to set the current transformation matrix (CTM) apply to pixel data after the lookup through the degamma LUT and before the lookup through the gamma LUT. The data is interpreted as a struct
drm_color_ctm
.Setting this to NULL (blob property value set to 0) means a unit/pass-thru matrix should be used. This is generally the driver boot-up state too. Drivers can access the blob for the color conversion matrix through
drm_crtc_state.ctm
.- “GAMMA_LUT”:
Blob property to set the gamma lookup table (LUT) mapping pixel data after the transformation matrix to data sent to the connector. The data is interpreted as an array of
struct drm_color_lut
elements. Hardware might choose not to use the full precision of the LUT elements nor use all the elements of the LUT (for example the hardware might choose to interpolate between LUT[0] and LUT[4]).Setting this to NULL (blob property value set to 0) means a linear/pass-thru gamma table should be used. This is generally the driver boot-up state too. Drivers can access this blob through
drm_crtc_state.gamma_lut
.- “GAMMA_LUT_SIZE”:
- Unsigned range property to give the size of the lookup table to be set on the GAMMA_LUT property (the size depends on the underlying hardware). If drivers support multiple LUT sizes then they should publish the largest size, and sub-sample smaller sized LUTs (e.g. for split-gamma modes) appropriately.
There is also support for a legacy gamma table, which is set up by calling
drm_mode_crtc_set_gamma_size()
. Drivers which support both should use
drm_atomic_helper_legacy_gamma_set()
to alias the legacy gamma ramp with the
“GAMMA_LUT” property above.
Support for different non RGB color encodings is controlled through
drm_plane
specific COLOR_ENCODING and COLOR_RANGE properties. They
are set up by calling drm_plane_create_color_properties()
.
- “COLOR_ENCODING”
- Optional plane enum property to support different non RGB color encodings. The driver can provide a subset of standard enum values supported by the DRM plane.
- “COLOR_RANGE”
- Optional plane enum property to support different non RGB color parameter ranges. The driver can provide a subset of standard enum values supported by the DRM plane.
-
uint32_t
drm_color_lut_extract
(uint32_t user_input, uint32_t bit_precision)¶ clamp and round LUT entries
Parameters
uint32_t user_input
- input value
uint32_t bit_precision
- number of bits the hw LUT supports
Description
Extract a degamma/gamma LUT value provided by user (in the form of
drm_color_lut
entries) and round it to the precision supported by the
hardware.
-
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.
Drivers should use drm_atomic_helper_legacy_gamma_set()
to implement the
legacy drm_crtc_funcs.gamma_set
callback.
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.
-
int
drm_plane_create_color_properties
(struct drm_plane * plane, u32 supported_encodings, u32 supported_ranges, enum drm_color_encoding default_encoding, enum drm_color_range default_range)¶ color encoding related plane properties
Parameters
struct drm_plane * plane
- plane object
u32 supported_encodings
- bitfield indicating supported color encodings
u32 supported_ranges
- bitfileld indicating supported color ranges
enum drm_color_encoding default_encoding
- default color encoding
enum drm_color_range default_range
- default color range
Description
Create and attach plane specific COLOR_ENCODING and COLOR_RANGE properties to plane. The supported encodings and ranges should be provided in supported_encodings and supported_ranges bitmasks. Each bit set in the bitmask indicates that its number as enum value is supported.
Tile Group Property¶
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. The property is called “TILE”. Drivers can manage tile
groups using drm_mode_create_tile_group()
, drm_mode_put_tile_group()
and
drm_mode_get_tile_group()
. But this is only needed for internal panels where
the tile group information is exposed through a non-standard way.
Explicit Fencing Properties¶
Explicit fencing allows userspace to control the buffer synchronization between devices. A Fence or a group of fences are transfered to/from userspace using Sync File fds and there are two DRM properties for that. IN_FENCE_FD on each DRM Plane to send fences to the kernel and OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
As a contrast, with implicit fencing the kernel keeps track of any
ongoing rendering, and automatically ensures that the atomic update waits
for any pending rendering to complete. For shared buffers represented with
a struct dma_buf
this is tracked in struct reservation_object
.
Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org),
whereas explicit fencing is what Android wants.
- “IN_FENCE_FD”:
Use this property to pass a fence that DRM should wait on before proceeding with the Atomic Commit request and show the framebuffer for the plane on the screen. The fence can be either a normal fence or a merged one, the sync_file framework will handle both cases and use a fence_array if a merged fence is received. Passing -1 here means no fences to wait on.
If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag it will only check if the Sync File is a valid one.
On the driver side the fence is stored on the fence parameter of
struct drm_plane_state
. Drivers which also support implicit fencing should set the implicit fence usingdrm_atomic_set_fence_for_plane()
, to make sure there’s consistent behaviour between drivers in precedence of implicit vs. explicit fencing.- “OUT_FENCE_PTR”:
Use this property to pass a file descriptor pointer to DRM. Once the Atomic Commit request call returns OUT_FENCE_PTR will be filled with the file descriptor number of a Sync File. This Sync File contains the CRTC fence that will be signaled when all framebuffers present on the Atomic Commit * request for that given CRTC are scanned out on the screen.
The Atomic Commit request fails if a invalid pointer is passed. If the Atomic Commit request fails for any other reason the out fence fd returned will be -1. On a Atomic Commit with the DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
Note that out-fences don’t have a special interface to drivers and are internally represented by a
struct drm_pending_vblank_event
in structdrm_crtc_state
, which is also used by the nonblocking atomic commit helpers and for the DRM event handling for existing userspace.
Existing KMS Properties¶
The following table gives description of drm properties exposed by various modules/drivers. Because this table is very unwieldy, do not add any new properties here. Instead document them in a section above.
Owner Module/Drivers | Group | Property Name | Type | Property Values | Object attached | Description/Restrictions |
---|---|---|---|---|---|---|
DVI-I | “subconnector” | ENUM | { “Unknown”, “DVI-D”, “DVI-A” } | Connector | TBD | |
“select subconnector” | ENUM | { “Automatic”, “DVI-D”, “DVI-A” } | Connector | TBD | ||
TV | “subconnector” | ENUM | { “Unknown”, “Composite”, “SVIDEO”, “Component”, “SCART” } | Connector | TBD | |
“select subconnector” | ENUM | { “Automatic”, “Composite”, “SVIDEO”, “Component”, “SCART” } | Connector | TBD | ||
“mode” | ENUM | { “NTSC_M”, “NTSC_J”, “NTSC_443”, “PAL_B” } etc. | Connector | TBD | ||
“left margin” | RANGE | Min=0, Max=100 | Connector | TBD | ||
“right margin” | RANGE | Min=0, Max=100 | Connector | TBD | ||
“top margin” | RANGE | Min=0, Max=100 | Connector | TBD | ||
“bottom margin” | RANGE | Min=0, Max=100 | Connector | TBD | ||
“brightness” | RANGE | Min=0, Max=100 | Connector | TBD | ||
“contrast” | RANGE | Min=0, Max=100 | Connector | TBD | ||
“flicker reduction” | RANGE | Min=0, Max=100 | Connector | TBD | ||
“overscan” | RANGE | Min=0, Max=100 | Connector | TBD | ||
“saturation” | RANGE | Min=0, Max=100 | Connector | TBD | ||
“hue” | RANGE | Min=0, Max=100 | Connector | TBD | ||
Virtual GPU | “suggested X” | RANGE | Min=0, Max=0xffffffff | Connector | property to suggest an X offset for a connector | |
“suggested Y” | RANGE | Min=0, Max=0xffffffff | Connector | property to suggest an Y offset for a connector | ||
Optional | “aspect ratio” | ENUM | { “None”, “4:3”, “16:9” } | Connector | TDB | |
Optional | “content type” | ENUM | { “No Data”, “Graphics”, “Photo”, “Cinema”, “Game” } | Connector | TBD | |
i915 | Generic | “Broadcast RGB” | ENUM | { “Automatic”, “Full”, “Limited 16:235” } | Connector | When this property is set to Limited 16:235 and CTM is set, the hardware will be programmed with the result of the multiplication of CTM by the limited range matrix to ensure the pixels normaly in the range 0..1.0 are remapped to the range 16/255..235/255. |
“audio” | ENUM | { “force-dvi”, “off”, “auto”, “on” } | Connector | TBD | ||
SDVO-TV | “mode” | ENUM | { “NTSC_M”, “NTSC_J”, “NTSC_443”, “PAL_B” } etc. | Connector | TBD | |
“left_margin” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“right_margin” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“top_margin” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“bottom_margin” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“hpos” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“vpos” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“contrast” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“saturation” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“hue” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“sharpness” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“flicker_filter” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“flicker_filter_adaptive” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“flicker_filter_2d” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“tv_chroma_filter” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“tv_luma_filter” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“dot_crawl” | RANGE | Min=0, Max=1 | Connector | TBD | ||
SDVO-TV/LVDS | “brightness” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | |
CDV gma-500 | Generic | “Broadcast RGB” | ENUM | { “Full”, “Limited 16:235” } | Connector | TBD |
“Broadcast RGB” | ENUM | { “off”, “auto”, “on” } | Connector | TBD | ||
Poulsbo | Generic | “backlight” | RANGE | Min=0, Max=100 | Connector | TBD |
SDVO-TV | “mode” | ENUM | { “NTSC_M”, “NTSC_J”, “NTSC_443”, “PAL_B” } etc. | Connector | TBD | |
“left_margin” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“right_margin” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“top_margin” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“bottom_margin” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“hpos” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“vpos” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“contrast” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“saturation” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“hue” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“sharpness” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“flicker_filter” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“flicker_filter_adaptive” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“flicker_filter_2d” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“tv_chroma_filter” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“tv_luma_filter” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | ||
“dot_crawl” | RANGE | Min=0, Max=1 | Connector | TBD | ||
SDVO-TV/LVDS | “brightness” | RANGE | Min=0, Max= SDVO dependent | Connector | TBD | |
armada | CRTC | “CSC_YUV” | ENUM | { “Auto” , “CCIR601”, “CCIR709” } | CRTC | TBD |
“CSC_RGB” | ENUM | { “Auto”, “Computer system”, “Studio” } | CRTC | TBD | ||
Overlay | “colorkey” | RANGE | Min=0, Max=0xffffff | Plane | TBD | |
“colorkey_min” | RANGE | Min=0, Max=0xffffff | Plane | TBD | ||
“colorkey_max” | RANGE | Min=0, Max=0xffffff | Plane | TBD | ||
“colorkey_val” | RANGE | Min=0, Max=0xffffff | Plane | TBD | ||
“colorkey_alpha” | RANGE | Min=0, Max=0xffffff | Plane | TBD | ||
“colorkey_mode” | ENUM | { “disabled”, “Y component”, “U component” , “V component”, “RGB”, “R component”, “G component”, “B component” } | Plane | TBD | ||
“brightness” | RANGE | Min=0, Max=256 + 255 | Plane | TBD | ||
“contrast” | RANGE | Min=0, Max=0x7fff | Plane | TBD | ||
“saturation” | RANGE | Min=0, Max=0x7fff | Plane | TBD | ||
exynos | CRTC | “mode” | ENUM | { “normal”, “blank” } | CRTC | TBD |
i2c/ch7006_drv | Generic | “scale” | RANGE | Min=0, Max=2 | Connector | TBD |
TV | “mode” | ENUM | { “PAL”, “PAL-M”,”PAL-N”}, ”PAL-Nc” , “PAL-60”, “NTSC-M”, “NTSC-J” } | Connector | TBD | |
nouveau | NV10 Overlay | “colorkey” | RANGE | Min=0, Max=0x01ffffff | Plane | TBD |
“contrast” | RANGE | Min=0, Max=8192-1 | Plane | TBD | ||
“brightness” | RANGE | Min=0, Max=1024 | Plane | TBD | ||
“hue” | RANGE | Min=0, Max=359 | Plane | TBD | ||
“saturation” | RANGE | Min=0, Max=8192-1 | Plane | TBD | ||
“iturbt_709” | RANGE | Min=0, Max=1 | Plane | TBD | ||
Nv04 Overlay | “colorkey” | RANGE | Min=0, Max=0x01ffffff | Plane | TBD | |
“brightness” | RANGE | Min=0, Max=1024 | Plane | TBD | ||
Display | “dithering mode” | ENUM | { “auto”, “off”, “on” } | Connector | TBD | |
“dithering depth” | ENUM | { “auto”, “off”, “on”, “static 2x2”, “dynamic 2x2”, “temporal” } | Connector | TBD | ||
“underscan” | ENUM | { “auto”, “6 bpc”, “8 bpc” } | Connector | TBD | ||
“underscan hborder” | RANGE | Min=0, Max=128 | Connector | TBD | ||
“underscan vborder” | RANGE | Min=0, Max=128 | Connector | TBD | ||
“vibrant hue” | RANGE | Min=0, Max=180 | Connector | TBD | ||
“color vibrance” | RANGE | Min=0, Max=200 | Connector | TBD | ||
omap | Generic | “zorder” | RANGE | Min=0, Max=3 | CRTC, Plane | TBD |
qxl | Generic | “hotplug_mode_update” | RANGE | Min=0, Max=1 | Connector | TBD |
radeon | DVI-I | “coherent” | RANGE | Min=0, Max=1 | Connector | TBD |
DAC enable load detect | “load detection” | RANGE | Min=0, Max=1 | Connector | TBD | |
TV Standard | “tv standard” | ENUM | { “ntsc”, “pal”, “pal-m”, “pal-60”, “ntsc-j” , “scart-pal”, “pal-cn”, “secam” } | Connector | TBD | |
legacy TMDS PLL detect | “tmds_pll” | ENUM | { “driver”, “bios” } | TBD | ||
Underscan | “underscan” | ENUM | { “off”, “on”, “auto” } | Connector | TBD | |
“underscan hborder” | RANGE | Min=0, Max=128 | Connector | TBD | ||
“underscan vborder” | RANGE | Min=0, Max=128 | Connector | TBD | ||
Audio | “audio” | ENUM | { “off”, “on”, “auto” } | Connector | TBD | |
FMT Dithering | “dither” | ENUM | { “off”, “on” } | Connector | TBD | |
“colorkey” | RANGE | Min=0, Max=0x01ffffff | Plane | TBD |
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 initialize the vertical blanking handling core with a call to
drm_vblank_init()
. Minimally, a driver needs to implement
drm_crtc_funcs.enable_vblank
and drm_crtc_funcs.disable_vblank
plus call
drm_crtc_handle_vblank()
in it’s vblank interrupt handler for working vblank
support.
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_crtc_vblank_get()
and release the vblank reference again with
drm_crtc_vblank_put()
. In between these two calls vblank interrupts are
guaranteed to be enabled.
On many hardware disabling the vblank interrupt cannot be done in a race-free
manner, see drm_driver.vblank_disable_immediate
and
drm_driver.max_vblank_count
. In that case the vblank core only disables the
vblanks after a timer has expired, which can be configured through the
vblankoffdelay
module parameter.
Vertical Blanking and Interrupt Handling Functions Reference¶
-
struct
drm_pending_vblank_event
¶ pending vblank event tracking
Definition
struct drm_pending_vblank_event {
struct drm_pending_event base;
unsigned int pipe;
u64 sequence;
union {
struct drm_event base;
struct drm_event_vblank vbl;
struct drm_event_crtc_sequence seq;
} event;
};
Members
base
- Base structure for tracking pending DRM events.
pipe
drm_crtc_index()
of thedrm_crtc
this event is for.sequence
- frame event should be triggered at
event
- Actual event which will be sent to userspace.
event.base
- DRM event base class.
event.vbl
- Event payload for vblank events, requested through
either the MODE_PAGE_FLIP or MODE_ATOMIC IOCTL. Also
generated by the legacy WAIT_VBLANK IOCTL, but new userspace
should use MODE_QUEUE_SEQUENCE and
event.seq
instead. event.seq
- Event payload for the MODE_QUEUEU_SEQUENCE IOCTL.
-
struct
drm_vblank_crtc
¶ vblank tracking for a CRTC
Definition
struct drm_vblank_crtc {
struct drm_device *dev;
wait_queue_head_t queue;
struct timer_list disable_timer;
seqlock_t seqlock;
u64 count;
ktime_t time;
atomic_t refcount;
u32 last;
unsigned int inmodeset;
unsigned int pipe;
int framedur_ns;
int linedur_ns;
struct drm_display_mode hwmode;
bool enabled;
};
Members
dev
- Pointer to the
drm_device
. queue
- Wait queue for vblank waiters.
disable_timer
- Disable timer for the delayed vblank disabling
hysteresis logic. Vblank disabling is controlled through the
drm_vblank_offdelay module option and the setting of the
drm_device.max_vblank_count
value. seqlock
- Protect vblank count and time.
count
- Current software vblank counter.
time
- Vblank timestamp corresponding to count.
refcount
- Number of users/waiters of the vblank interrupt. Only when this refcount reaches 0 can the hardware interrupt be disabled using disable_timer.
last
- Protected by
drm_device.vbl_lock
, used for wraparound handling. inmodeset
- Tracks whether the vblank is disabled due to a modeset.
For legacy driver bit 2 additionally tracks whether an additional
temporary vblank reference has been acquired to paper over the
hardware counter resetting/jumping. KMS drivers should instead just
call
drm_crtc_vblank_off()
anddrm_crtc_vblank_on()
, which explicitly save and restore the vblank count. pipe
drm_crtc_index()
of thedrm_crtc
corresponding to this structure.framedur_ns
- Frame/Field duration in ns, used by
drm_calc_vbltimestamp_from_scanoutpos()
and computed bydrm_calc_timestamping_constants()
. linedur_ns
- Line duration in ns, used by
drm_calc_vbltimestamp_from_scanoutpos()
and computed bydrm_calc_timestamping_constants()
. hwmode
- Cache of the current hardware display mode. Only valid when enabled
is set. This is used by helpers like
drm_calc_vbltimestamp_from_scanoutpos()
. We can’t just access the hardware mode by e.g. looking atdrm_crtc_state.adjusted_mode
, because that one is really hard to get from interrupt context. enabled
- Tracks the enabling state of the corresponding
drm_crtc
to avoid double-disabling and hence corrupting saved state. Needed by drivers not using atomic KMS, since those might go through their CRTC disabling functions multiple times.
Description
This structure tracks the vblank state for one CRTC.
Note that for historical reasons - the vblank handling code is still shared
with legacy/non-kms drivers - this is a free-standing structure not directly
connected to struct drm_crtc
. But all public interface functions are taking
a struct drm_crtc
to hide this implementation detail.
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 interrupts using the high precision
timestamping support.
This is mostly useful for hardware that can obtain the scanout position, but doesn’t have a hardware frame counter.
-
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.
Cleanup is handled by the DRM core, or through calling drm_dev_fini()
for
drivers with a drm_driver.release
callback.
Return
Zero on success or a negative error code on failure.
-
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()
and related
functions.
-
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.
-
bool
drm_calc_vbltimestamp_from_scanoutpos
(struct drm_device * dev, unsigned int pipe, int * max_error, ktime_t * vblank_time, bool in_vblank_irq)¶ 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
ktime_t * vblank_time
- Pointer to time which should receive the timestamp
bool in_vblank_irq
- True when called from
drm_crtc_handle_vblank()
. Some drivers need to apply some workarounds for gpu-specific vblank irq quirks if flag is set.
Description
Implements calculation of exact vblank timestamps from given drm_display_mode
timings and current video scanout position of a CRTC. This can be directly
used as the drm_driver.get_vblank_timestamp
implementation of a kms driver
if drm_driver.get_scanout_position
is implemented.
The current implementation only handles standard video modes. For double scan
and interlaced modes the driver is supposed to adjust the hardware mode
(taken from drm_crtc_state.adjusted
mode for atomic modeset drivers) to
match the scanout position reported.
Note that atomic drivers must call drm_calc_timestamping_constants()
before
enabling a CRTC. The atomic helpers already take care of that in
drm_atomic_helper_update_legacy_modeset_state()
.
Return
Returns true on success, and false on failure, i.e. when no accurate timestamp could be acquired.
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. Note that this timer isn’t correct against a racing
vblank interrupt (since it only reports the software vblank counter), see
drm_crtc_accurate_vblank_count()
for such use-cases.
Return
The software vblank counter.
-
u64
drm_crtc_vblank_count_and_time
(struct drm_crtc * crtc, ktime_t * 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
ktime_t * vblanktime
- Pointer to time 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.
-
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.
NOTE
Drivers using this to send out the drm_crtc_state.event
as part of an
atomic commit must ensure that the next vblank happens at exactly the same
time as the atomic commit is committed to the hardware. This function itself
does not protect against the next vblank interrupt racing with either this
function call or the atomic commit operation. A possible sequence could be:
- Driver commits new hardware state into vblank-synchronized registers.
- A vblank happens, committing the hardware state. Also the corresponding vblank interrupt is fired off and fully processed by the interrupt handler.
- The atomic commit operation proceeds to call
drm_crtc_arm_vblank_event()
. - The event is only send out for the next vblank, which is wrong.
An equivalent race can happen when the driver calls
drm_crtc_arm_vblank_event()
before writing out the new hardware state.
The only way to make this work safely is to prevent the vblank from firing
(and the hardware from committing anything else) until the entire atomic
commit sequence has run to completion. If the hardware does not have such a
feature (e.g. using a “go” bit), then it is unsafe to use this functions.
Instead drivers need to manually send out the event from their interrupt
handler by calling drm_crtc_send_vblank_event()
and make sure that there’s no
possible race with the hardware committing the atomic update.
Caller must 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 for the most recently processed vblank, and sends it to userspace. Caller must hold event lock.
See drm_crtc_arm_vblank_event()
for a helper which can be used in certain
situation, especially to send out events for atomic commit operations.
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.
This is the legacy version of drm_crtc_wait_one_vblank()
.
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.
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 or disabling the crtc in general.
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.
This is useful for recovering driver state e.g. on driver load, or on resume.
Parameters
struct drm_crtc * crtc
- CRTC in question
Description
This functions restores the vblank interrupt state captured with
drm_crtc_vblank_off()
again and is generally called when enabling crtc. Note
that calls to drm_crtc_vblank_on()
and drm_crtc_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.
-
void
drm_vblank_restore
(struct drm_device * dev, unsigned int pipe)¶ estimate missed vblanks and update vblank count.
Parameters
struct drm_device * dev
- DRM device
unsigned int pipe
- CRTC index
Description
Power manamement features can cause frame counter resets between vblank
disable and enable. Drivers can use this function in their
drm_crtc_funcs.enable_vblank
implementation to estimate missed vblanks since
the last drm_crtc_funcs.disable_vblank
using timestamps and update the
vblank counter.
This function is the legacy version of drm_crtc_vblank_restore()
.
-
void
drm_crtc_vblank_restore
(struct drm_crtc * crtc)¶ estimate missed vblanks and update vblank count.
Parameters
struct drm_crtc * crtc
- CRTC in question
Description
Power manamement features can cause frame counter resets between vblank
disable and enable. Drivers can use this function in their
drm_crtc_funcs.enable_vblank
implementation to estimate missed vblanks since
the last drm_crtc_funcs.disable_vblank
using timestamps and update the
vblank counter.
-
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.