summaryrefslogtreecommitdiffstats
path: root/include/drm/drm_crtc.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/drm/drm_crtc.h')
-rw-r--r--include/drm/drm_crtc.h1242
1 files changed, 1116 insertions, 126 deletions
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 3f0c6909dda1..c65a212db77e 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -85,7 +85,11 @@ static inline uint64_t I642U64(int64_t val)
return (uint64_t)*((uint64_t *)&val);
}
-/* rotation property bits */
+/*
+ * Rotation property bits. DRM_ROTATE_<degrees> rotates the image by the
+ * specified amount in degrees in counter clockwise direction. DRM_REFLECT_X and
+ * DRM_REFLECT_Y reflects the image along the specified axis prior to rotation
+ */
#define DRM_ROTATE_MASK 0x0f
#define DRM_ROTATE_0 0
#define DRM_ROTATE_90 1
@@ -158,23 +162,60 @@ struct drm_tile_group {
u8 group_data[8];
};
+/**
+ * struct drm_framebuffer_funcs - framebuffer hooks
+ */
struct drm_framebuffer_funcs {
- /* note: use drm_framebuffer_remove() */
+ /**
+ * @destroy:
+ *
+ * Clean up framebuffer resources, specifically also unreference the
+ * backing storage. The core guarantees to call this function for every
+ * framebuffer successfully created by ->fb_create() in
+ * &drm_mode_config_funcs. Drivers must also call
+ * drm_framebuffer_cleanup() to release DRM core resources for this
+ * framebuffer.
+ */
void (*destroy)(struct drm_framebuffer *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.
+ */
int (*create_handle)(struct drm_framebuffer *fb,
struct drm_file *file_priv,
unsigned int *handle);
- /*
- * Optional callback for the dirty fb ioctl.
+ /**
+ * @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.
*
- * Userspace can notify the driver via this callback
- * that a area of the framebuffer has changed and should
- * be flushed to the display hardware.
+ * RETURNS:
*
- * 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.
+ * 0 on success or a negative error code on failure.
*/
int (*dirty)(struct drm_framebuffer *framebuffer,
struct drm_file *file_priv, unsigned flags,
@@ -250,6 +291,11 @@ struct drm_plane;
struct drm_bridge;
struct drm_atomic_state;
+struct drm_crtc_helper_funcs;
+struct drm_encoder_helper_funcs;
+struct drm_connector_helper_funcs;
+struct drm_plane_helper_funcs;
+
/**
* struct drm_crtc_state - mutable CRTC state
* @crtc: backpointer to the CRTC
@@ -260,6 +306,7 @@ struct drm_atomic_state;
* @active_changed: crtc_state->active has been toggled.
* @connectors_changed: connectors to this crtc have been updated
* @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
+ * @connector_mask: bitmask of (1 << drm_connector_index(connector)) of attached connectors
* @last_vblank_count: for helpers and drivers to capture the vblank of the
* update to ensure framebuffer cleanup isn't done too early
* @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings
@@ -293,6 +340,8 @@ struct drm_crtc_state {
*/
u32 plane_mask;
+ u32 connector_mask;
+
/* last_vblank_count: for vblank waits before cleanup */
u32 last_vblank_count;
@@ -311,23 +360,6 @@ struct drm_crtc_state {
/**
* struct drm_crtc_funcs - control CRTCs for a given device
- * @save: save CRTC state
- * @restore: restore CRTC state
- * @reset: reset CRTC after state has been invalidated (e.g. resume)
- * @cursor_set: setup the cursor
- * @cursor_set2: setup the cursor with hotspot, superseeds @cursor_set if set
- * @cursor_move: move the cursor
- * @gamma_set: specify color ramp for CRTC
- * @destroy: deinit and free object
- * @set_property: called when a property is changed
- * @set_config: apply a new CRTC configuration
- * @page_flip: initiate a page flip
- * @atomic_duplicate_state: duplicate the atomic state for this CRTC
- * @atomic_destroy_state: destroy an atomic state for this CRTC
- * @atomic_set_property: set a property on an atomic state for this CRTC
- * (do not call directly, use drm_atomic_crtc_set_property())
- * @atomic_get_property: get a property on an atomic state for this CRTC
- * (do not call directly, use drm_atomic_crtc_get_property())
*
* 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
@@ -339,54 +371,317 @@ struct drm_crtc_state {
* bus accessors.
*/
struct drm_crtc_funcs {
- /* Save CRTC state */
- void (*save)(struct drm_crtc *crtc); /* suspend? */
- /* Restore CRTC state */
- void (*restore)(struct drm_crtc *crtc); /* resume? */
- /* Reset CRTC state */
+ /**
+ * @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.
+ */
void (*reset)(struct drm_crtc *crtc);
- /* cursor controls */
+ /**
+ * @cursor_set:
+ *
+ * Update the cursor image. The cursor position is relative to the CRTC
+ * and can be partially or fully outside of the visible area.
+ *
+ * Note that contrary to all other KMS functions the legacy cursor entry
+ * points don't take a framebuffer object, but instead take directly a
+ * raw buffer object id from the driver's buffer manager (which is
+ * either GEM or TTM for current drivers).
+ *
+ * This entry point is deprecated, drivers should instead implement
+ * universal plane support and register a proper cursor plane using
+ * drm_crtc_init_with_planes().
+ *
+ * This callback is optional
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
int (*cursor_set)(struct drm_crtc *crtc, struct drm_file *file_priv,
uint32_t handle, uint32_t width, uint32_t height);
+
+ /**
+ * @cursor_set2:
+ *
+ * Update the cursor image, including hotspot information. The hotspot
+ * must not affect the cursor position in CRTC coordinates, but is only
+ * meant as a hint for virtualized display hardware to coordinate the
+ * guests and hosts cursor position. The cursor hotspot is relative to
+ * the cursor image. Otherwise this works exactly like @cursor_set.
+ *
+ * This entry point is deprecated, drivers should instead implement
+ * universal plane support and register a proper cursor plane using
+ * drm_crtc_init_with_planes().
+ *
+ * This callback is optional.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
int (*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);
+
+ /**
+ * @cursor_move:
+ *
+ * Update the cursor position. The cursor does not need to be visible
+ * when this hook is called.
+ *
+ * This entry point is deprecated, drivers should instead implement
+ * universal plane support and register a proper cursor plane using
+ * drm_crtc_init_with_planes().
+ *
+ * This callback is optional.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
int (*cursor_move)(struct drm_crtc *crtc, int x, int y);
- /* Set gamma on the CRTC */
+ /**
+ * @gamma_set:
+ *
+ * Set gamma on the CRTC.
+ *
+ * This callback is optional.
+ *
+ * NOTE:
+ *
+ * Drivers that support gamma tables and also fbdev emulation through
+ * the provided helper library need to take care to fill out the gamma
+ * hooks for both. Currently there's a bit an unfortunate duplication
+ * going on, which should eventually be unified to just one set of
+ * hooks.
+ */
void (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
uint32_t start, uint32_t size);
- /* Object destroy routine */
+
+ /**
+ * @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.
+ */
void (*destroy)(struct drm_crtc *crtc);
+ /**
+ * @set_config:
+ *
+ * This is the main legacy entry point to change the modeset state on a
+ * CRTC. All the details of the desired configuration are passed in a
+ * struct &drm_mode_set - see there for details.
+ *
+ * Drivers implementing atomic modeset should use
+ * drm_atomic_helper_set_config() to implement this hook.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
int (*set_config)(struct drm_mode_set *set);
- /*
- * Flip to the given framebuffer. This implements the page
- * flip ioctl described in drm_mode.h, specifically, the
- * implementation must return immediately and block all
- * rendering to the current fb until the flip has completed.
- * If userspace set the event flag in the ioctl, the event
- * argument will point to an event to send back when the flip
- * completes, otherwise it will be NULL.
+ /**
+ * @page_flip:
+ *
+ * Legacy entry point to schedule a flip to the given framebuffer.
+ *
+ * Page flipping is a synchronization mechanism that replaces the frame
+ * buffer being scanned out by the CRTC with a new frame buffer during
+ * vertical blanking, avoiding tearing (except when requested otherwise
+ * through the DRM_MODE_PAGE_FLIP_ASYNC flag). When an application
+ * requests a page flip the DRM core verifies that the new frame buffer
+ * is large enough to be scanned out by the CRTC in the currently
+ * configured mode and then calls the CRTC ->page_flip() operation with a
+ * pointer to the new frame buffer.
+ *
+ * The driver must wait for any pending rendering to the new framebuffer
+ * to complete before executing the flip. It should also wait for any
+ * pending rendering from other drivers if the underlying buffer is a
+ * shared dma-buf.
+ *
+ * An application can request to be notified when the page flip has
+ * completed. The drm core will supply a struct &drm_event in the event
+ * parameter in this case. This can be handled by the
+ * drm_crtc_send_vblank_event() function, which the driver should call on
+ * the provided event upon completion of the flip. Note that if
+ * the driver supports vblank signalling and timestamping the vblank
+ * counters and timestamps must agree with the ones returned from page
+ * flip events. With the current vblank helper infrastructure this can
+ * be achieved by holding a vblank reference while the page flip is
+ * pending, acquired through drm_crtc_vblank_get() and released with
+ * drm_crtc_vblank_put(). Drivers are free to implement their own vblank
+ * counter and timestamp tracking though, e.g. if they have accurate
+ * timestamp registers in hardware.
+ *
+ * FIXME:
+ *
+ * Up to that point drivers need to manage events themselves and can use
+ * even->base.list freely for that. Specifically they need to ensure
+ * that they don't send out page flip (or vblank) events for which the
+ * corresponding drm file has been closed already. The drm core
+ * unfortunately does not (yet) take care of that. Therefore drivers
+ * currently must clean up and release pending events in their
+ * ->preclose driver function.
+ *
+ * This callback is optional.
+ *
+ * NOTE:
+ *
+ * Very early versions of the KMS ABI mandated that the driver must
+ * block (but not reject) any rendering to the old framebuffer until the
+ * flip operation has completed and the old framebuffer is no longer
+ * visible. This requirement has been lifted, and userspace is instead
+ * expected to request delivery of an event and wait with recycling old
+ * buffers until such has been received.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure. Note that if a
+ * ->page_flip() operation is already pending the callback should return
+ * -EBUSY. Pageflips on a disabled CRTC (either by setting a NULL mode
+ * or just runtime disabled through DPMS respectively the new atomic
+ * "ACTIVE" state) should result in an -EINVAL error code. Note that
+ * drm_atomic_helper_page_flip() checks this already for atomic drivers.
*/
int (*page_flip)(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t flags);
+ /**
+ * @set_property:
+ *
+ * This is the legacy entry point to update a property attached to the
+ * CRTC.
+ *
+ * Drivers implementing atomic modeset should use
+ * drm_atomic_helper_crtc_set_property() to implement this hook.
+ *
+ * This callback is optional if the driver does not support any legacy
+ * driver-private properties.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
int (*set_property)(struct drm_crtc *crtc,
struct drm_property *property, uint64_t val);
- /* atomic update handling */
+ /**
+ * @atomic_duplicate_state:
+ *
+ * Duplicate the current atomic state for this CRTC and return it.
+ * The core and helpers gurantee that any atomic state duplicated with
+ * this hook and still owned by the caller (i.e. not transferred to the
+ * driver by calling ->atomic_commit() from struct
+ * &drm_mode_config_funcs) will be cleaned up by calling the
+ * @atomic_destroy_state hook in this structure.
+ *
+ * Atomic drivers which don't subclass struct &drm_crtc should use
+ * drm_atomic_helper_crtc_duplicate_state(). Drivers that subclass the
+ * state structure to extend it with driver-private state should use
+ * __drm_atomic_helper_crtc_duplicate_state() to make sure shared state is
+ * duplicated in a consistent fashion across drivers.
+ *
+ * It is an error to call this hook before crtc->state has been
+ * initialized correctly.
+ *
+ * NOTE:
+ *
+ * If the duplicate state references refcounted resources this hook must
+ * acquire a reference for each of them. The driver must release these
+ * references again in @atomic_destroy_state.
+ *
+ * RETURNS:
+ *
+ * Duplicated atomic state or NULL when the allocation failed.
+ */
struct drm_crtc_state *(*atomic_duplicate_state)(struct drm_crtc *crtc);
+
+ /**
+ * @atomic_destroy_state:
+ *
+ * Destroy a state duplicated with @atomic_duplicate_state and release
+ * or unreference all resources it references
+ */
void (*atomic_destroy_state)(struct drm_crtc *crtc,
struct drm_crtc_state *state);
+
+ /**
+ * @atomic_set_property:
+ *
+ * Decode a driver-private property value and store the decoded value
+ * into the passed-in state structure. Since the atomic core decodes all
+ * standardized properties (even for extensions beyond the core set of
+ * properties which might not be implemented by all drivers) this
+ * requires drivers to subclass the state structure.
+ *
+ * Such driver-private properties should really only be implemented for
+ * truly hardware/vendor specific state. Instead it is preferred to
+ * standardize atomic extension and decode the properties used to expose
+ * such an extension in the core.
+ *
+ * Do not call this function directly, use
+ * drm_atomic_crtc_set_property() instead.
+ *
+ * This callback is optional if the driver does not support any
+ * driver-private atomic properties.
+ *
+ * NOTE:
+ *
+ * This function is called in the state assembly phase of atomic
+ * modesets, which can be aborted for any reason (including on
+ * userspace's request to just check whether a configuration would be
+ * possible). Drivers MUST NOT touch any persistent state (hardware or
+ * software) or data structures except the passed in @state parameter.
+ *
+ * Also since userspace controls in which order properties are set this
+ * function must not do any input validation (since the state update is
+ * incomplete and hence likely inconsistent). Instead any such input
+ * validation must be done in the various atomic_check callbacks.
+ *
+ * RETURNS:
+ *
+ * 0 if the property has been found, -EINVAL if the property isn't
+ * implemented by the driver (which should never happen, the core only
+ * asks for properties attached to this CRTC). No other validation is
+ * allowed by the driver. The core already checks that the property
+ * value is within the range (integer, valid enum value, ...) the driver
+ * set when registering the property.
+ */
int (*atomic_set_property)(struct drm_crtc *crtc,
struct drm_crtc_state *state,
struct drm_property *property,
uint64_t val);
+ /**
+ * @atomic_get_property:
+ *
+ * Reads out the decoded driver-private property. This is used to
+ * implement the GETCRTC IOCTL.
+ *
+ * Do not call this function directly, use
+ * drm_atomic_crtc_get_property() instead.
+ *
+ * This callback is optional if the driver does not support any
+ * driver-private atomic properties.
+ *
+ * RETURNS:
+ *
+ * 0 on success, -EINVAL if the property isn't implemented by the
+ * driver (which should never happen, the core only asks for
+ * properties attached to this CRTC).
+ */
int (*atomic_get_property)(struct drm_crtc *crtc,
const struct drm_crtc_state *state,
struct drm_property *property,
@@ -416,7 +711,7 @@ struct drm_crtc_funcs {
* @properties: property tracking for this CRTC
* @state: current atomic state for this CRTC
* @acquire_ctx: per-CRTC implicit acquire context used by atomic drivers for
- * legacy ioctls
+ * legacy IOCTLs
*
* Each CRTC may have one or more connectors associated with it. This structure
* allows the CRTC to be controlled.
@@ -426,6 +721,8 @@ struct drm_crtc {
struct device_node *port;
struct list_head head;
+ char *name;
+
/*
* crtc mutex
*
@@ -463,14 +760,14 @@ struct drm_crtc {
uint16_t *gamma_store;
/* if you are using the helper */
- const void *helper_private;
+ const struct drm_crtc_helper_funcs *helper_private;
struct drm_object_properties properties;
struct drm_crtc_state *state;
/*
- * For legacy crtc ioctls so that atomic drivers can get at the locking
+ * For legacy crtc IOCTLs so that atomic drivers can get at the locking
* acquire context.
*/
struct drm_modeset_acquire_ctx *acquire_ctx;
@@ -495,54 +792,239 @@ struct drm_connector_state {
/**
* struct drm_connector_funcs - control connectors on a given device
- * @dpms: set power state
- * @save: save connector state
- * @restore: restore connector state
- * @reset: reset connector after state has been invalidated (e.g. resume)
- * @detect: is this connector active?
- * @fill_modes: fill mode list for this connector
- * @set_property: property for this connector may need an update
- * @destroy: make object go away
- * @force: notify the driver that the connector is forced on
- * @atomic_duplicate_state: duplicate the atomic state for this connector
- * @atomic_destroy_state: destroy an atomic state for this connector
- * @atomic_set_property: set a property on an atomic state for this connector
- * (do not call directly, use drm_atomic_connector_set_property())
- * @atomic_get_property: get a property on an atomic state for this connector
- * (do not call directly, use drm_atomic_connector_get_property())
*
* 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_funcs {
+ /**
+ * @dpms:
+ *
+ * Legacy entry point to set the per-connector DPMS state. Legacy DPMS
+ * is exposed as a standard property on the connector, but diverted to
+ * this callback in the drm core. Note that atomic drivers don't
+ * implement the 4 level DPMS support on the connector any more, but
+ * instead only have an on/off "ACTIVE" property on the CRTC object.
+ *
+ * Drivers implementing atomic modeset should use
+ * drm_atomic_helper_connector_dpms() to implement this hook.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
int (*dpms)(struct drm_connector *connector, int mode);
- void (*save)(struct drm_connector *connector);
- void (*restore)(struct drm_connector *connector);
+
+ /**
+ * @reset:
+ *
+ * Reset connector hardware and software state to off. This function isn't
+ * called by the core directly, only through drm_mode_config_reset().
+ * It's not a helper hook only for historical reasons.
+ *
+ * Atomic drivers can use drm_atomic_helper_connector_reset() to reset
+ * atomic state using this hook.
+ */
void (*reset)(struct drm_connector *connector);
- /* Check to see if anything is attached to the connector.
- * @force is set to false whilst polling, true when checking the
- * connector due to user request. @force can be used by the driver
- * to avoid expensive, destructive operations during automated
- * probing.
+ /**
+ * @detect:
+ *
+ * Check to see if anything is attached to the connector. The parameter
+ * force is set to false whilst polling, true when checking the
+ * connector due to a user request. force can be used by the driver to
+ * avoid expensive, destructive operations during automated probing.
+ *
+ * FIXME:
+ *
+ * Note that this hook is only called by the probe helper. It's not in
+ * the helper library vtable purely for historical reasons. The only DRM
+ * core entry point to probe connector state is @fill_modes.
+ *
+ * RETURNS:
+ *
+ * drm_connector_status indicating the connector's status.
*/
enum drm_connector_status (*detect)(struct drm_connector *connector,
bool force);
+
+ /**
+ * @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.
+ */
+ void (*force)(struct drm_connector *connector);
+
+ /**
+ * @fill_modes:
+ *
+ * Entry point for output detection and basic mode validation. The
+ * driver should reprobe the output if needed (e.g. when hotplug
+ * handling is unreliable), add all detected modes to connector->modes
+ * and filter out any the device can't support in any configuration. It
+ * also needs to filter out any modes wider or higher than the
+ * parameters max_width and max_height indicate.
+ *
+ * The drivers must also prune any modes no longer valid from
+ * connector->modes. Furthermore it must update connector->status and
+ * connector->edid. If no EDID has been received for this output
+ * connector->edid must be NULL.
+ *
+ * Drivers using the probe helpers should use
+ * drm_helper_probe_single_connector_modes() or
+ * drm_helper_probe_single_connector_modes_nomerge() to implement this
+ * function.
+ *
+ * RETURNS:
+ *
+ * The number of modes detected and filled into connector->modes.
+ */
int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
+
+ /**
+ * @set_property:
+ *
+ * This is the legacy entry point to update a property attached to the
+ * connector.
+ *
+ * Drivers implementing atomic modeset should use
+ * drm_atomic_helper_connector_set_property() to implement this hook.
+ *
+ * This callback is optional if the driver does not support any legacy
+ * driver-private properties.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
int (*set_property)(struct drm_connector *connector, struct drm_property *property,
uint64_t val);
+
+ /**
+ * @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).
+ */
void (*destroy)(struct drm_connector *connector);
- void (*force)(struct drm_connector *connector);
- /* atomic update handling */
+ /**
+ * @atomic_duplicate_state:
+ *
+ * Duplicate the current atomic state for this connector and return it.
+ * The core and helpers gurantee that any atomic state duplicated with
+ * this hook and still owned by the caller (i.e. not transferred to the
+ * driver by calling ->atomic_commit() from struct
+ * &drm_mode_config_funcs) will be cleaned up by calling the
+ * @atomic_destroy_state hook in this structure.
+ *
+ * Atomic drivers which don't subclass struct &drm_connector_state should use
+ * drm_atomic_helper_connector_duplicate_state(). Drivers that subclass the
+ * state structure to extend it with driver-private state should use
+ * __drm_atomic_helper_connector_duplicate_state() to make sure shared state is
+ * duplicated in a consistent fashion across drivers.
+ *
+ * It is an error to call this hook before connector->state has been
+ * initialized correctly.
+ *
+ * NOTE:
+ *
+ * If the duplicate state references refcounted resources this hook must
+ * acquire a reference for each of them. The driver must release these
+ * references again in @atomic_destroy_state.
+ *
+ * RETURNS:
+ *
+ * Duplicated atomic state or NULL when the allocation failed.
+ */
struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector);
+
+ /**
+ * @atomic_destroy_state:
+ *
+ * Destroy a state duplicated with @atomic_duplicate_state and release
+ * or unreference all resources it references
+ */
void (*atomic_destroy_state)(struct drm_connector *connector,
struct drm_connector_state *state);
+
+ /**
+ * @atomic_set_property:
+ *
+ * Decode a driver-private property value and store the decoded value
+ * into the passed-in state structure. Since the atomic core decodes all
+ * standardized properties (even for extensions beyond the core set of
+ * properties which might not be implemented by all drivers) this
+ * requires drivers to subclass the state structure.
+ *
+ * Such driver-private properties should really only be implemented for
+ * truly hardware/vendor specific state. Instead it is preferred to
+ * standardize atomic extension and decode the properties used to expose
+ * such an extension in the core.
+ *
+ * Do not call this function directly, use
+ * drm_atomic_connector_set_property() instead.
+ *
+ * This callback is optional if the driver does not support any
+ * driver-private atomic properties.
+ *
+ * NOTE:
+ *
+ * This function is called in the state assembly phase of atomic
+ * modesets, which can be aborted for any reason (including on
+ * userspace's request to just check whether a configuration would be
+ * possible). Drivers MUST NOT touch any persistent state (hardware or
+ * software) or data structures except the passed in @state parameter.
+ *
+ * Also since userspace controls in which order properties are set this
+ * function must not do any input validation (since the state update is
+ * incomplete and hence likely inconsistent). Instead any such input
+ * validation must be done in the various atomic_check callbacks.
+ *
+ * RETURNS:
+ *
+ * 0 if the property has been found, -EINVAL if the property isn't
+ * implemented by the driver (which shouldn't ever happen, the core only
+ * asks for properties attached to this connector). No other validation
+ * is allowed by the driver. The core already checks that the property
+ * value is within the range (integer, valid enum value, ...) the driver
+ * set when registering the property.
+ */
int (*atomic_set_property)(struct drm_connector *connector,
struct drm_connector_state *state,
struct drm_property *property,
uint64_t val);
+
+ /**
+ * @atomic_get_property:
+ *
+ * Reads out the decoded driver-private property. This is used to
+ * implement the GETCONNECTOR IOCTL.
+ *
+ * Do not call this function directly, use
+ * drm_atomic_connector_get_property() instead.
+ *
+ * This callback is optional if the driver does not support any
+ * driver-private atomic properties.
+ *
+ * RETURNS:
+ *
+ * 0 on success, -EINVAL if the property isn't implemented by the
+ * driver (which shouldn't ever happen, the core only asks for
+ * properties attached to this connector).
+ */
int (*atomic_get_property)(struct drm_connector *connector,
const struct drm_connector_state *state,
struct drm_property *property,
@@ -551,13 +1033,26 @@ struct drm_connector_funcs {
/**
* struct drm_encoder_funcs - encoder controls
- * @reset: reset state (e.g. at init or resume time)
- * @destroy: cleanup and free associated data
*
* Encoders sit between CRTCs and connectors.
*/
struct drm_encoder_funcs {
+ /**
+ * @reset:
+ *
+ * Reset encoder hardware and software state to off. This function isn't
+ * called by the core directly, only through drm_mode_config_reset().
+ * It's not a helper hook only for historical reasons.
+ */
void (*reset)(struct drm_encoder *encoder);
+
+ /**
+ * @destroy:
+ *
+ * Clean up encoder resources. This is only called at driver unload time
+ * through drm_mode_config_cleanup() since an encoder cannot be
+ * hotplugged in DRM.
+ */
void (*destroy)(struct drm_encoder *encoder);
};
@@ -593,7 +1088,7 @@ struct drm_encoder {
struct drm_crtc *crtc;
struct drm_bridge *bridge;
const struct drm_encoder_funcs *funcs;
- const void *helper_private;
+ const struct drm_encoder_helper_funcs *helper_private;
};
/* should we poll this connector for connects and disconnects */
@@ -698,7 +1193,7 @@ struct drm_connector {
/* requested DPMS state */
int dpms;
- const void *helper_private;
+ const struct drm_connector_helper_funcs *helper_private;
/* forced on connector */
struct drm_cmdline_mode cmdline_mode;
@@ -778,40 +1273,203 @@ struct drm_plane_state {
/**
* struct drm_plane_funcs - driver plane control functions
- * @update_plane: update the plane configuration
- * @disable_plane: shut down the plane
- * @destroy: clean up plane resources
- * @reset: reset plane after state has been invalidated (e.g. resume)
- * @set_property: called when a property is changed
- * @atomic_duplicate_state: duplicate the atomic state for this plane
- * @atomic_destroy_state: destroy an atomic state for this plane
- * @atomic_set_property: set a property on an atomic state for this plane
- * (do not call directly, use drm_atomic_plane_set_property())
- * @atomic_get_property: get a property on an atomic state for this plane
- * (do not call directly, use drm_atomic_plane_get_property())
*/
struct drm_plane_funcs {
+ /**
+ * @update_plane:
+ *
+ * This is the legacy entry point to enable and configure the plane for
+ * the given CRTC and framebuffer. It is never called to disable the
+ * plane, i.e. the passed-in crtc and fb paramters are never NULL.
+ *
+ * The source rectangle in frame buffer memory coordinates is given by
+ * the src_x, src_y, src_w and src_h parameters (as 16.16 fixed point
+ * values). Devices that don't support subpixel plane coordinates can
+ * ignore the fractional part.
+ *
+ * The destination rectangle in CRTC coordinates is given by the
+ * crtc_x, crtc_y, crtc_w and crtc_h parameters (as integer values).
+ * Devices scale the source rectangle to the destination rectangle. If
+ * scaling is not supported, and the source rectangle size doesn't match
+ * the destination rectangle size, the driver must return a
+ * -<errorname>EINVAL</errorname> error.
+ *
+ * Drivers implementing atomic modeset should use
+ * drm_atomic_helper_update_plane() to implement this hook.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
int (*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);
+
+ /**
+ * @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.
+ */
int (*disable_plane)(struct drm_plane *plane);
+
+ /**
+ * @destroy:
+ *
+ * Clean up plane resources. This is only called at driver unload time
+ * through drm_mode_config_cleanup() since a plane cannot be hotplugged
+ * in DRM.
+ */
void (*destroy)(struct drm_plane *plane);
+
+ /**
+ * @reset:
+ *
+ * Reset plane hardware and software state to off. This function isn't
+ * called by the core directly, only through drm_mode_config_reset().
+ * It's not a helper hook only for historical reasons.
+ *
+ * Atomic drivers can use drm_atomic_helper_plane_reset() to reset
+ * atomic state using this hook.
+ */
void (*reset)(struct drm_plane *plane);
+ /**
+ * @set_property:
+ *
+ * This is the legacy entry point to update a property attached to the
+ * plane.
+ *
+ * Drivers implementing atomic modeset should use
+ * drm_atomic_helper_plane_set_property() to implement this hook.
+ *
+ * This callback is optional if the driver does not support any legacy
+ * driver-private properties.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
int (*set_property)(struct drm_plane *plane,
struct drm_property *property, uint64_t val);
- /* atomic update handling */
+ /**
+ * @atomic_duplicate_state:
+ *
+ * Duplicate the current atomic state for this plane and return it.
+ * The core and helpers gurantee that any atomic state duplicated with
+ * this hook and still owned by the caller (i.e. not transferred to the
+ * driver by calling ->atomic_commit() from struct
+ * &drm_mode_config_funcs) will be cleaned up by calling the
+ * @atomic_destroy_state hook in this structure.
+ *
+ * Atomic drivers which don't subclass struct &drm_plane_state should use
+ * drm_atomic_helper_plane_duplicate_state(). Drivers that subclass the
+ * state structure to extend it with driver-private state should use
+ * __drm_atomic_helper_plane_duplicate_state() to make sure shared state is
+ * duplicated in a consistent fashion across drivers.
+ *
+ * It is an error to call this hook before plane->state has been
+ * initialized correctly.
+ *
+ * NOTE:
+ *
+ * If the duplicate state references refcounted resources this hook must
+ * acquire a reference for each of them. The driver must release these
+ * references again in @atomic_destroy_state.
+ *
+ * RETURNS:
+ *
+ * Duplicated atomic state or NULL when the allocation failed.
+ */
struct drm_plane_state *(*atomic_duplicate_state)(struct drm_plane *plane);
+
+ /**
+ * @atomic_destroy_state:
+ *
+ * Destroy a state duplicated with @atomic_duplicate_state and release
+ * or unreference all resources it references
+ */
void (*atomic_destroy_state)(struct drm_plane *plane,
struct drm_plane_state *state);
+
+ /**
+ * @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
+ *