aboutsummaryrefslogtreecommitdiffstats
path: root/include/drm
diff options
context:
space:
mode:
Diffstat (limited to 'include/drm')
-rw-r--r--include/drm/drmP.h15
-rw-r--r--include/drm/drm_atomic.h10
-rw-r--r--include/drm/drm_atomic_helper.h14
-rw-r--r--include/drm/drm_crtc.h1242
-rw-r--r--include/drm/drm_crtc_helper.h167
-rw-r--r--include/drm/drm_dp_helper.h36
-rw-r--r--include/drm/drm_dp_mst_helper.h11
-rw-r--r--include/drm/drm_encoder_slave.h2
-rw-r--r--include/drm/drm_fb_cma_helper.h2
-rw-r--r--include/drm/drm_fb_helper.h101
-rw-r--r--include/drm/drm_gem.h106
-rw-r--r--include/drm/drm_mipi_dsi.h27
-rw-r--r--include/drm/drm_mm.h26
-rw-r--r--include/drm/drm_modes.h347
-rw-r--r--include/drm/drm_modeset_helper_vtables.h928
-rw-r--r--include/drm/drm_modeset_lock.h4
-rw-r--r--include/drm/drm_plane_helper.h38
-rw-r--r--include/drm/drm_rect.h3
-rw-r--r--include/drm/i915_component.h83
-rw-r--r--include/drm/i915_pciids.h49
-rw-r--r--include/drm/ttm/ttm_bo_api.h10
-rw-r--r--include/drm/ttm/ttm_bo_driver.h4
22 files changed, 2763 insertions, 462 deletions
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 0a271ca1f7c7..d7162cf1c3e1 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -349,6 +349,8 @@ struct drm_file {
struct list_head event_list;
int event_space;
+ struct mutex event_read_lock;
+
struct drm_prime_file_private prime;
};
@@ -585,6 +587,13 @@ struct drm_driver {
int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
+ /**
+ * Hook for allocating the GEM object struct, for use by core
+ * helpers.
+ */
+ struct drm_gem_object *(*gem_create_object)(struct drm_device *dev,
+ size_t size);
+
/* prime: */
/* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */
int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv,
@@ -1059,7 +1068,7 @@ void drm_dev_ref(struct drm_device *dev);
void drm_dev_unref(struct drm_device *dev);
int drm_dev_register(struct drm_device *dev, unsigned long flags);
void drm_dev_unregister(struct drm_device *dev);
-int drm_dev_set_unique(struct drm_device *dev, const char *fmt, ...);
+int drm_dev_set_unique(struct drm_device *dev, const char *name);
struct drm_minor *drm_minor_acquire(unsigned int minor_id);
void drm_minor_release(struct drm_minor *minor);
@@ -1108,6 +1117,7 @@ static inline int drm_pci_set_busid(struct drm_device *dev,
#define DRM_PCIE_SPEED_80 4
extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
+extern int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw);
/* platform section */
extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device);
@@ -1121,4 +1131,7 @@ static __inline__ bool drm_can_sleep(void)
return true;
}
+/* helper for handling conditionals in various for_each macros */
+#define for_each_if(condition) if (!(condition)) {} else
+
#endif
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 4b74c97d297a..d3eaa5df187a 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -130,10 +130,6 @@ int __must_check
drm_atomic_add_affected_planes(struct drm_atomic_state *state,
struct drm_crtc *crtc);
-int
-drm_atomic_connectors_for_crtc(struct drm_atomic_state *state,
- struct drm_crtc *crtc);
-
void drm_atomic_legacy_backoff(struct drm_atomic_state *state);
void
@@ -149,7 +145,7 @@ int __must_check drm_atomic_async_commit(struct drm_atomic_state *state);
((connector) = (state)->connectors[__i], \
(connector_state) = (state)->connector_states[__i], 1); \
(__i)++) \
- if (connector)
+ for_each_if (connector)
#define for_each_crtc_in_state(state, crtc, crtc_state, __i) \
for ((__i) = 0; \
@@ -157,7 +153,7 @@ int __must_check drm_atomic_async_commit(struct drm_atomic_state *state);
((crtc) = (state)->crtcs[__i], \
(crtc_state) = (state)->crtc_states[__i], 1); \
(__i)++) \
- if (crtc_state)
+ for_each_if (crtc_state)
#define for_each_plane_in_state(state, plane, plane_state, __i) \
for ((__i) = 0; \
@@ -165,7 +161,7 @@ int __must_check drm_atomic_async_commit(struct drm_atomic_state *state);
((plane) = (state)->planes[__i], \
(plane_state) = (state)->plane_states[__i], 1); \
(__i)++) \
- if (plane_state)
+ for_each_if (plane_state)
static inline bool
drm_atomic_crtc_needs_modeset(struct drm_crtc_state *state)
{
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 8cba54a2a0a0..fe5efada9d68 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -42,6 +42,10 @@ int drm_atomic_helper_commit(struct drm_device *dev,
struct drm_atomic_state *state,
bool async);
+bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev,
+ struct drm_atomic_state *old_state,
+ struct drm_crtc *crtc);
+
void drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
struct drm_atomic_state *old_state);
@@ -62,6 +66,8 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
struct drm_atomic_state *old_state);
void drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state);
+void drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc *crtc,
+ bool atomic);
void drm_atomic_helper_swap_state(struct drm_device *dev,
struct drm_atomic_state *state);
@@ -81,6 +87,12 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set);
int __drm_atomic_helper_set_config(struct drm_mode_set *set,
struct drm_atomic_state *state);
+int drm_atomic_helper_disable_all(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx);
+struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev);
+int drm_atomic_helper_resume(struct drm_device *dev,
+ struct drm_atomic_state *state);
+
int drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc,
struct drm_property *property,
uint64_t val);
@@ -118,6 +130,8 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state);
+void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
+ struct drm_connector_state *conn_state);
void drm_atomic_helper_connector_reset(struct drm_connector *connector);
void
__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
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
+ * possible). Drivers MUST NOT touch any persistent state (hardware or
+ * software) or data structures except the passed in @state parameter.
+ *
+ * Also since userspace controls in which order properties are set this
+ * function must not do any input validation (since the state update is
+ * incomplete and hence likely inconsistent). Instead any such input
+ * validation must be done in the various atomic_check callbacks.
+ *
+ * RETURNS:
+ *
+ * 0 if the property has been found, -EINVAL if the property isn't
+ * implemented by the driver (which shouldn't ever happen, the core only
+ * asks for properties attached to this plane). No other validation is
+ * allowed by the driver. The core already checks that the property
+ * value is within the range (integer, valid enum value, ...) the driver
+ * set when registering the property.
+ */
int (*atomic_set_property)(struct drm_plane *plane,
struct drm_plane_state *state,
struct drm_property *property,
uint64_t val);
+
+ /**
+ * @atomic_get_property:
+ *
+ * Reads out the decoded driver-private property. This is used to
+ * implement the GETPLANE IOCTL.
+ *
+ * Do not call this function directly, use
+ * drm_atomic_plane_get_property() instead.
+ *
+ * This callback is optional if the driver does not support any
+ * driver-private atomic properties.
+ *
+ * RETURNS:
+ *
+ * 0 on success, -EINVAL if the property isn't implemented by the
+ * driver (which should never happen, the core only asks for
+ * properties attached to this plane).
+ */
int (*atomic_get_property)(struct drm_plane *plane,
const struct drm_plane_state *state,
struct drm_property *property,
@@ -824,6 +1482,7 @@ enum drm_plane_type {
DRM_PLANE_TYPE_CURSOR,
};
+
/**
* struct drm_plane - central DRM plane control structure
* @dev: DRM device this plane belongs to
@@ -846,6 +1505,8 @@ struct drm_plane {
struct drm_device *dev;
struct list_head head;
+ char *name;
+
struct drm_modeset_lock mutex;
struct drm_mode_object base;
@@ -866,7 +1527,7 @@ struct drm_plane {
enum drm_plane_type type;
- const void *helper_private;
+ const struct drm_plane_helper_funcs *helper_private;
struct drm_plane_state *state;
};
@@ -874,24 +1535,114 @@ struct drm_plane {
/**
* struct drm_bridge_funcs - drm_bridge control functions
* @attach: Called during drm_bridge_attach
- * @mode_fixup: Try to fixup (or reject entirely) proposed mode for this bridge
- * @disable: Called right before encoder prepare, disables the bridge
- * @post_disable: Called right after encoder prepare, for lockstepped disable
- * @mode_set: Set this mode to the bridge
- * @pre_enable: Called right before encoder commit, for lockstepped commit
- * @enable: Called right after encoder commit, enables the bridge
*/
struct drm_bridge_funcs {
int (*attach)(struct drm_bridge *bridge);
+
+ /**
+ * @mode_fixup:
+ *
+ * This callback is used to validate and adjust a mode. The paramater
+ * mode is the display mode that should be fed to the next element in
+ * the display chain, either the final &drm_connector or the next
+ * &drm_bridge. The parameter adjusted_mode is the input mode the bridge
+ * requires. It can be modified by this callback and does not need to
+ * match mode.
+ *
+ * This is the only hook that allows a bridge to reject a modeset. If
+ * this function passes all other callbacks must succeed for this
+ * configuration.
+ *
+ * NOTE:
+ *
+ * This function is called in the check phase of atomic modesets, which
+ * can be aborted for any reason (including on userspace's request to
+ * just check whether a configuration would be possible). Drivers MUST
+ * NOT touch any persistent state (hardware or software) or data
+ * structures except the passed in @state parameter.
+ *
+ * RETURNS:
+ *
+ * True if an acceptable configuration is possible, false if the modeset
+ * operation should be rejected.
+ */
bool (*mode_fixup)(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
+ /**
+ * @disable:
+ *
+ * This callback should disable the bridge. It is called right before
+ * the preceding element in the display pipe is disabled. If the
+ * preceding element is a bridge this means it's called before that
+ * bridge's ->disable() function. If the preceding element is a
+ * &drm_encoder it's called right before the encoder's ->disable(),
+ * ->prepare() or ->dpms() hook from struct &drm_encoder_helper_funcs.
+ *
+ * The bridge can assume that the display pipe (i.e. clocks and timing
+ * signals) feeding it is still running when this callback is called.
+ */
void (*disable)(struct drm_bridge *bridge);
+
+ /**
+ * @post_disable:
+ *
+ * This callback should disable the bridge. It is called right after
+ * the preceding element in the display pipe is disabled. If the
+ * preceding element is a bridge this means it's called after that
+ * bridge's ->post_disable() function. If the preceding element is a
+ * &drm_encoder it's called right after the encoder's ->disable(),
+ * ->prepare() or ->dpms() hook from struct &drm_encoder_helper_funcs.
+ *
+ * The bridge must assume that the display pipe (i.e. clocks and timing
+ * singals) feeding it is no longer running when this callback is
+ * called.
+ */
void (*post_disable)(struct drm_bridge *bridge);
+
+ /**
+ * @mode_set:
+ *
+ * This callback should set the given mode on the bridge. It is called
+ * after the ->mode_set() callback for the preceding element in the
+ * display pipeline has been called already. The display pipe (i.e.
+ * clocks and timing signals) is off when this function is called.
+ */
void (*mode_set)(struct drm_bridge *bridge,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
+ /**
+ * @pre_enable:
+ *
+ * This callback should enable the bridge. It is called right before
+ * the preceding element in the display pipe is enabled. If the
+ * preceding element is a bridge this means it's called before that
+ * bridge's ->pre_enable() function. If the preceding element is a
+ * &drm_encoder it's called right before the encoder's ->enable(),
+ * ->commit() or ->dpms() hook from struct &drm_encoder_helper_funcs.
+ *
+ * The display pipe (i.e. clocks and timing signals) feeding this bridge
+ * will not yet be running when this callback is called. The bridge must
+ * not enable the display link feeding the next bridge in the chain (if
+ * there is one) when this callback is called.
+ */
void (*pre_enable)(struct drm_bridge *bridge);
+
+ /**
+ * @enable:
+ *
+ * This callback should enable the bridge. It is called right after
+ * the preceding element in the display pipe is enabled. If the
+ * preceding element is a bridge this means it's called after that
+ * bridge's ->enable() function. If the preceding element is a
+ * &drm_encoder it's called right after the encoder's ->enable(),
+ * ->commit() or ->dpms() hook from struct &drm_encoder_helper_funcs.
+ *
+ * The bridge can assume that the display pipe (i.e. clocks and timing
+ * signals) feeding it is running when this callback is called. This
+ * callback must enable the display link feeding the next bridge in the
+ * chain if there is one.
+ */
void (*enable)(struct drm_bridge *bridge);
};
@@ -922,7 +1673,7 @@ struct drm_bridge {
* struct drm_atomic_state - the global state object for atomic updates
* @dev: parent DRM device
* @allow_modeset: allow full modeset
- * @legacy_cursor_update: hint to enforce legacy cursor ioctl semantics
+ * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics
* @planes: pointer to array of plane pointers
* @plane_states: pointer to array of plane states pointers
* @crtcs: pointer to array of CRTC pointers
@@ -977,31 +1728,265 @@ struct drm_mode_set {
/**
* struct drm_mode_config_funcs - basic driver provided mode setting functions
- * @fb_create: create a new framebuffer object
- * @output_poll_changed: function to handle output configuration changes
- * @atomic_check: check whether a given atomic state update is possible
- * @atomic_commit: commit an atomic state update previously verified with
- * atomic_check()
- * @atomic_state_alloc: allocate a new atomic state
- * @atomic_state_clear: clear the atomic state
- * @atomic_state_free: free the atomic state
*
* Some global (i.e. not per-CRTC, connector, etc) mode setting functions that
* involve drivers.
*/
struct drm_mode_config_funcs {
+ /**
+ * @fb_create:
+ *
+ * Create a new framebuffer object. The core does basic checks on the
+ * requested metadata, but most of that is left to the driver. See
+ * struct &drm_mode_fb_cmd2 for details.
+ *
+ * If the parameters are deemed valid and the backing storage objects in
+ * the underlying memory manager all exist, then the driver allocates
+ * a new &drm_framebuffer structure, subclassed to contain
+ * driver-specific information (like the internal native buffer object
+ * references). It also needs to fill out all relevant metadata, which
+ * should be done by calling drm_helper_mode_fill_fb_struct().
+ *
+ * The initialization is finalized by calling drm_framebuffer_init(),
+ * which registers the framebuffer and makes it accessible to other
+ * threads.
+ *
+ * RETURNS:
+ *
+ * A new framebuffer with an initial reference count of 1 or a negative
+ * error code encoded with ERR_PTR().
+ */
struct drm_framebuffer *(*fb_create)(struct drm_device *dev,
struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd);
+ const struct drm_mode_fb_cmd2 *mode_cmd);
+
+ /**
+ * @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.
+ */
void (*output_poll_changed)(struct drm_device *dev);
+ /**
+ * @atomic_check:
+ *
+ * This is the only hook to validate an atomic modeset update. This
+ * function must reject any modeset and state changes which the hardware
+ * or driver doesn't support. This includes but is of course not limited
+ * to:
+ *
+ * - Checking that the modes, framebuffers, scaling and placement
+ * requirements and so on are within the limits of the hardware.
+ *
+ * - Checking that any hidden shared resources are not oversubscribed.
+ * This can be shared PLLs, shared lanes, overall memory bandwidth,
+ * display fifo space (where shared between planes or maybe even
+ * CRTCs).
+ *
+ * - Checking that virtualized resources exported to userspace are not
+ * oversubscribed. For various reasons it can make sense to expose
+ * more planes, crtcs or encoders than which are physically there. One
+ * example is dual-pipe operations (which generally should be hidden
+ * from userspace if when lockstepped in hardware, exposed otherwise),
+ * where a plane might need 1 hardware plane (if it's just on one
+ * pipe), 2 hardware planes (when it spans both pipes) or maybe even
+ * shared a hardware plane with a 2nd plane (if there's a compatible
+ * plane requested on the area handled by the other pipe).
+ *
+ * - Check that any transitional state is possible and that if
+ * requested, the update can indeed be done in the vblank period
+ * without temporarily disabling some functions.
+ *
+ * - Check any other constraints the driver or hardware might have.
+ *
+ * - This callback also needs to correctly fill out the &drm_crtc_state
+ * in this update to make sure that drm_atomic_crtc_needs_modeset()
+ * reflects the nature of the possible update and returns true if and
+ * only if the update cannot be applied without tearing within one
+ * vblank on that CRTC. The core uses that information to reject
+ * updates which require a full modeset (i.e. blanking the screen, or
+ * at least pausing updates for a substantial amount of time) if
+ * userspace has disallowed that in its request.
+ *
+ * - The driver also does not need to repeat basic input validation
+ * like done for the corresponding legacy entry points. The core does
+ * that before calling this hook.
+ *
+ * See the documentation of @atomic_commit for an exhaustive list of
+ * error conditions which don't have to be checked at the
+ * ->atomic_check() stage?
+ *
+ * See the documentation for struct &drm_atomic_state for how exactly
+ * an atomic modeset update is described.
+ *
+ * Drivers using the atomic helpers can implement this hook using
+ * drm_atomic_helper_check(), or one of the exported sub-functions of
+ * it.
+ *
+ * RETURNS:
+ *
+ * 0 on success or one of the below negative error codes:
+ *
+ * - -EINVAL, if any of the above constraints are violated.
+ *
+ * - -EDEADLK, when returned from an attempt to acquire an additional
+ * &drm_modeset_lock through drm_modeset_lock().
+ *
+ * - -ENOMEM, if allocating additional state sub-structures failed due
+ * to lack of memory.
+ *
+ * - -EINTR, -EAGAIN or -ERESTARTSYS, if the IOCTL should be restarted.
+ * This can either be due to a pending signal, or because the driver
+ * needs to completely bail out to recover from an exceptional
+ * situation like a GPU hang. From a userspace point all errors are
+ * treated equally.
+ */
int (*atomic_check)(struct drm_device *dev,
- struct drm_atomic_state *a);
+ struct drm_atomic_state *state);
+
+ /**
+ * @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.
+ *
+ * Asynchronous commits (as indicated with the async 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. Asynchronous commits must not wait for
+ * rendering in the context of this callback.
+ *
+ * An application can request to be notified when the atomic commit has
+ * completed. These events are per-CRTC and can be distinguished by the
+ * CRTC index supplied in &drm_event to userspace.
+ *
+ * The drm core will supply a struct &drm_event in the event
+ * member of each CRTC's &drm_crtc_state structure. This can be handled by the
+ * drm_crtc_send_vblank_event() function, which the driver should call on
+ * the provided event upon completion of the atomic commit. Note that if
+ * the driver supports vblank signalling and timestamping the vblank
+ * counters and timestamps must agree with the ones returned from page
+ * flip events. With the current vblank helper infrastructure this can
+ * be achieved by holding a vblank reference while the page flip is
+ * pending, acquired through drm_crtc_vblank_get() and released with
+ * drm_crtc_vblank_put(). Drivers are free to implement their own vblank
+ * counter and timestamp tracking though, e.g. if they have accurate
+ * timestamp registers in hardware.
+ *
+ * NOTE:
+ *
+ * Drivers are not allowed to shut down any display pipe successfully
+ * enabled through an atomic commit on their own. Doing so can result in
+ * compositors crashing if a page flip is suddenly rejected because the
+ * pipe is off.
+ *
+ * RETURNS:
+ *
+ * 0 on success or one of the below negative error codes:
+ *
+ * - -EBUSY, if an asynchronous 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).
+ */
int (*atomic_commit)(struct drm_device *dev,
- struct drm_atomic_state *a,
+ struct drm_atomic_state *state,
bool async);
+
+ /**
+ * @atomic_state_alloc:
+ *
+ * This optional hook can be used by drivers that want to subclass struct
+ * &drm_atomic_state to be able to track their own driver-private global
+ * state easily. If this hook is implemented, drivers must also
+ * implement @atomic_state_clear and @atomic_state_free.
+ *
+ * RETURNS:
+ *
+ * A new &drm_atomic_state on success or NULL on failure.
+ */
struct drm_atomic_state *(*atomic_state_alloc)(struct drm_device *dev);
+
+ /**
+ * @atomic_state_clear:
+ *
+ * This hook must clear any driver private state duplicated into the
+ * passed-in &drm_atomic_state. This hook is called when the caller
+ * encountered a &drm_modeset_lock deadlock and needs to drop all
+ * already acquired locks as part of the deadlock avoidance dance
+ * implemented in drm_modeset_lock_backoff().
+ *
+ * Any duplicated state must be invalidated since a concurrent atomic
+ * update might change it, and the drm atomic interfaces always apply
+ * updates as relative changes to the current state.
+ *
+ * Drivers that implement this must call drm_atomic_state_default_clear()
+ * to clear common state.
+ */
void (*atomic_state_clear)(struct drm_atomic_state *state);
+
+ /**
+ * @atomic_state_free:
+ *
+ * This hook needs driver private resources and the &drm_atomic_state
+ * itself. Note that the core first calls drm_atomic_state_clear() to
+ * avoid code duplicate between the clear and free hooks.
+ *
+ * Drivers that implement this must call drm_atomic_state_default_free()
+ * to release common resources.
+ */
void (*atomic_state_free)(struct drm_atomic_state *state);
};
@@ -1010,7 +1995,7 @@ struct drm_mode_config_funcs {
* @mutex: mutex protecting KMS related lists and structures
* @connection_mutex: ww mutex protecting connector state and routing
* @acquire_ctx: global implicit acquire context used by atomic drivers for
- * legacy ioctls
+ * legacy IOCTLs
* @idr_mutex: mutex for KMS ID allocation and management
* @crtc_idr: main KMS ID tracking object
* @fb_lock: mutex to protect fb state and lists
@@ -1166,7 +2151,7 @@ struct drm_mode_config {
*/
#define drm_for_each_plane_mask(plane, dev, plane_mask) \
list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \
- if ((plane_mask) & (1 << drm_plane_index(plane)))
+ for_each_if ((plane_mask) & (1 << drm_plane_index(plane)))
#define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
@@ -1183,11 +2168,13 @@ struct drm_prop_enum_list {
char *name;
};
-extern 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);
+extern __printf(6, 7)
+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, ...);
extern void drm_crtc_cleanup(struct drm_crtc *crtc);
extern unsigned int drm_crtc_index(struct drm_crtc *crtc);
@@ -1233,10 +2220,11 @@ void drm_bridge_mode_set(struct drm_bridge *bridge,
void drm_bridge_pre_enable(struct drm_bridge *bridge);
void drm_bridge_enable(struct drm_bridge *bridge);
-extern int drm_encoder_init(struct drm_device *dev,
- struct drm_encoder *encoder,
- const struct drm_encoder_funcs *funcs,
- int encoder_type);
+extern __printf(5, 6)
+int drm_encoder_init(struct drm_device *dev,
+ struct drm_encoder *encoder,
+ const struct drm_encoder_funcs *funcs,
+ int encoder_type, const char *name, ...);
/**
* drm_encoder_crtc_ok - can a given crtc drive a given encoder?
@@ -1251,13 +2239,15 @@ static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
return !!(encoder->possible_crtcs & drm_crtc_mask(crtc));
}
-extern int drm_universal_plane_init(struct drm_device *dev,
- struct drm_plane *plane,
- unsigned long possible_crtcs,
- const struct drm_plane_funcs *funcs,
- const uint32_t *formats,
- unsigned int format_count,
- enum drm_plane_type type);
+extern __printf(8, 9)
+int drm_universal_plane_init(struct drm_device *dev,
+ struct drm_plane *plane,
+ unsigned long possible_crtcs,
+ const struct drm_plane_funcs *funcs,
+ const uint32_t *formats,
+ unsigned int format_count,
+ enum drm_plane_type type,
+ const char *name, ...);
extern int drm_plane_init(struct drm_device *dev,
struct drm_plane *plane,
unsigned long possible_crtcs,
@@ -1543,7 +2533,7 @@ static inline struct drm_property *drm_property_find(struct drm_device *dev,
/* Plane list iterator for legacy (overlay only) planes. */
#define drm_for_each_legacy_plane(plane, dev) \
list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \
- if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+ for_each_if (plane->type == DRM_PLANE_TYPE_OVERLAY)
#define drm_for_each_plane(plane, dev) \
list_for_each_entry(plane, &(dev)->mode_config.plane_list, head)
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 3febb4b9fce9..4b37afa2b73b 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -40,148 +40,7 @@
#include <linux/fb.h>
#include <drm/drm_crtc.h>
-
-enum mode_set_atomic {
- LEAVE_ATOMIC_MODE_SET,
- ENTER_ATOMIC_MODE_SET,
-};
-
-/**
- * struct drm_crtc_helper_funcs - helper operations for CRTCs
- * @dpms: set power state
- * @prepare: prepare the CRTC, called before @mode_set
- * @commit: commit changes to CRTC, called after @mode_set
- * @mode_fixup: try to fixup proposed mode for this CRTC
- * @mode_set: set this mode
- * @mode_set_nofb: set mode only (no scanout buffer attached)
- * @mode_set_base: update the scanout buffer
- * @mode_set_base_atomic: non-blocking mode set (used for kgdb support)
- * @load_lut: load color palette
- * @disable: disable CRTC when no longer in use
- * @enable: enable CRTC
- * @atomic_check: check for validity of an atomic state
- * @atomic_begin: begin atomic update
- * @atomic_flush: flush atomic update
- *
- * The helper operations are called by the mid-layer CRTC helper.
- *
- * Note that with atomic helpers @dpms, @prepare and @commit hooks are
- * deprecated. Used @enable and @disable instead exclusively.
- *
- * With legacy crtc helpers there's a big semantic difference between @disable
- * and the other hooks: @disable also needs to release any resources acquired in
- * @mode_set (like shared PLLs).
- */
-struct drm_crtc_helper_funcs {
- /*
- * Control power levels on the CRTC. If the mode passed in is
- * unsupported, the provider must use the next lowest power level.
- */
- void (*dpms)(struct drm_crtc *crtc, int mode);
- void (*prepare)(struct drm_crtc *crtc);
- void (*commit)(struct drm_crtc *crtc);
-
- /* Provider can fixup or change mode timings before modeset occurs */
- bool (*mode_fixup)(struct drm_crtc *crtc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
- /* Actually set the mode */
- int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode, int x, int y,
- struct drm_framebuffer *old_fb);
- /* Actually set the mode for atomic helpers, optional */
- void (*mode_set_nofb)(struct drm_crtc *crtc);
-
- /* Move the crtc on the current fb to the given position *optional* */
- int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
- struct drm_framebuffer *old_fb);
- int (*mode_set_base_atomic)(struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int x, int y,
- enum mode_set_atomic);
-
- /* reload the current crtc LUT */
- void (*load_lut)(struct drm_crtc *crtc);
-
- void (*disable)(struct drm_crtc *crtc);
- void (*enable)(struct drm_crtc *crtc);
-
- /* atomic helpers */
- int (*atomic_check)(struct drm_crtc *crtc,
- struct drm_crtc_state *state);
- void (*atomic_begin)(struct drm_crtc *crtc,
- struct drm_crtc_state *old_crtc_state);
- void (*atomic_flush)(struct drm_crtc *crtc,
- struct drm_crtc_state *old_crtc_state);
-};
-
-/**
- * struct drm_encoder_helper_funcs - helper operations for encoders
- * @dpms: set power state
- * @save: save connector state
- * @restore: restore connector state
- * @mode_fixup: try to fixup proposed mode for this connector
- * @prepare: part of the disable sequence, called before the CRTC modeset
- * @commit: called after the CRTC modeset
- * @mode_set: set this mode, optional for atomic helpers
- * @get_crtc: return CRTC that the encoder is currently attached to
- * @detect: connection status detection
- * @disable: disable encoder when not in use (overrides DPMS off)
- * @enable: enable encoder
- * @atomic_check: check for validity of an atomic update
- *
- * The helper operations are called by the mid-layer CRTC helper.
- *
- * Note that with atomic helpers @dpms, @prepare and @commit hooks are
- * deprecated. Used @enable and @disable instead exclusively.
- *
- * With legacy crtc helpers there's a big semantic difference between @disable
- * and the other hooks: @disable also needs to release any resources acquired in
- * @mode_set (like shared PLLs).
- */
-struct drm_encoder_helper_funcs {
- void (*dpms)(struct drm_encoder *encoder, int mode);
- void (*save)(struct drm_encoder *encoder);
- void (*restore)(struct drm_encoder *encoder);
-
- bool (*mode_fixup)(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
- void (*prepare)(struct drm_encoder *encoder);
- void (*commit)(struct drm_encoder *encoder);
- void (*mode_set)(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
- struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder);
- /* detect for DAC style encoders */
- enum drm_connector_status (*detect)(struct drm_encoder *encoder,
- struct drm_connector *connector);
- void (*disable)(struct drm_encoder *encoder);
-
- void (*enable)(struct drm_encoder *encoder);
-
- /* atomic helpers */
- int (*atomic_check)(struct drm_encoder *encoder,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state);
-};
-
-/**
- * struct drm_connector_helper_funcs - helper operations for connectors
- * @get_modes: get mode list for this connector
- * @mode_valid: is this mode valid on the given connector? (optional)
- * @best_encoder: return the preferred encoder for this connector
- * @atomic_best_encoder: atomic version of @best_encoder
- *
- * The helper operations are called by the mid-layer CRTC helper.
- */
-struct drm_connector_helper_funcs {
- int (*get_modes)(struct drm_connector *connector);
- enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
- struct drm_display_mode *mode);
- struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
- struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector,
- struct drm_connector_state *connector_state);
-};
+#include <drm/drm_modeset_helper_vtables.h>
extern void drm_helper_disable_unused_functions(struct drm_device *dev);
extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
@@ -197,25 +56,7 @@ extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
extern void drm_helper_move_panel_connectors_to_head(struct drm_device *);
extern void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
- struct drm_mode_fb_cmd2 *mode_cmd);
-
-static inline void drm_crtc_helper_add(struct drm_crtc *crtc,
- const struct drm_crtc_helper_funcs *funcs)
-{
- crtc->helper_private = funcs;
-}
-
-static inline void drm_encoder_helper_add(struct drm_encoder *encoder,
- const struct drm_encoder_helper_funcs *funcs)
-{
- encoder->helper_private = funcs;
-}
-
-static inline void drm_connector_helper_add(struct drm_connector *connector,
- const struct drm_connector_helper_funcs *funcs)
-{
- connector->helper_private = funcs;
-}
+ const struct drm_mode_fb_cmd2 *mode_cmd);
extern void drm_helper_resume_force_mode(struct drm_device *dev);
@@ -229,10 +70,6 @@ int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
extern int drm_helper_probe_single_connector_modes(struct drm_connector
*connector, uint32_t maxX,
uint32_t maxY);
-extern int drm_helper_probe_single_connector_modes_nomerge(struct drm_connector
- *connector,
- uint32_t maxX,
- uint32_t maxY);
extern void drm_kms_helper_poll_init(struct drm_device *dev);
extern void drm_kms_helper_poll_fini(struct drm_device *dev);
extern bool drm_helper_hpd_irq_event(struct drm_device *dev);
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index bb9d0deca07c..1252108da0ef 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -455,16 +455,52 @@
# define DP_EDP_14 0x03
#define DP_EDP_GENERAL_CAP_1 0x701
+# define DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP (1 << 0)
+# define DP_EDP_BACKLIGHT_PIN_ENABLE_CAP (1 << 1)
+# define DP_EDP_BACKLIGHT_AUX_ENABLE_CAP (1 << 2)
+# define DP_EDP_PANEL_SELF_TEST_PIN_ENABLE_CAP (1 << 3)
+# define DP_EDP_PANEL_SELF_TEST_AUX_ENABLE_CAP (1 << 4)
+# define DP_EDP_FRC_ENABLE_CAP (1 << 5)
+# define DP_EDP_COLOR_ENGINE_CAP (1 << 6)
+# define DP_EDP_SET_POWER_CAP (1 << 7)
#define DP_EDP_BACKLIGHT_ADJUSTMENT_CAP 0x702
+# define DP_EDP_BACKLIGHT_BRIGHTNESS_PWM_PIN_CAP (1 << 0)
+# define DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP (1 << 1)
+# define DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT (1 << 2)
+# define DP_EDP_BACKLIGHT_AUX_PWM_PRODUCT_CAP (1 << 3)
+# define DP_EDP_BACKLIGHT_FREQ_PWM_PIN_PASSTHRU_CAP (1 << 4)
+# define DP_EDP_BACKLIGHT_FREQ_AUX_SET_CAP (1 << 5)
+# define DP_EDP_DYNAMIC_BACKLIGHT_CAP (1 << 6)
+# define DP_EDP_VBLANK_BACKLIGHT_UPDATE_CAP (1 << 7)
#define DP_EDP_GENERAL_CAP_2 0x703
+# define DP_EDP_OVERDRIVE_ENGINE_ENABLED (1 << 0)
#define DP_EDP_GENERAL_CAP_3 0x704 /* eDP 1.4 */
+# define DP_EDP_X_REGION_CAP_MASK (0xf << 0)
+# define DP_EDP_X_REGION_CAP_SHIFT 0
+# define DP_EDP_Y_REGION_CAP_MASK (0xf << 4)
+# define DP_EDP_Y_REGION_CAP_SHIFT 4
#define DP_EDP_DISPLAY_CONTROL_REGISTER 0x720
+# define DP_EDP_BACKLIGHT_ENABLE (1 << 0)
+# define DP_EDP_BLACK_VIDEO_ENABLE (1 << 1)
+# define DP_EDP_FRC_ENABLE (1 << 2)
+# define DP_EDP_COLOR_ENGINE_ENABLE (1 << 3)
+# define DP_EDP_VBLANK_BACKLIGHT_UPDATE_ENABLE (1 << 7)
#define DP_EDP_BACKLIGHT_MODE_SET_REGISTER 0x721
+# define DP_EDP_BACKLIGHT_CONTROL_MODE_MASK (3 << 0)
+# define DP_EDP_BACKLIGHT_CONTROL_MODE_PWM (0 << 0)
+# define DP_EDP_BACKLIGHT_CONTROL_MODE_PRESET (1 << 0)
+# define DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD (2 << 0)
+# define DP_EDP_BACKLIGHT_CONTROL_MODE_PRODUCT (3 << 0)
+# define DP_EDP_BACKLIGHT_FREQ_PWM_PIN_PASSTHRU_ENABLE (1 << 2)
+# define DP_EDP_BACKLIGHT_FREQ_AUX_SET_ENABLE (1 << 3)
+# define DP_EDP_DYNAMIC_BACKLIGHT_ENABLE (1 << 4)
+# define DP_EDP_REGIONAL_BACKLIGHT_ENABLE (1 << 5)
+# define DP_EDP_UPDATE_REGION_BRIGHTNESS (1 << 6) /* eDP 1.4 */
#define DP_EDP_BACKLIGHT_BRIGHTNESS_MSB 0x722
#define DP_EDP_BACKLIGHT_BRIGHTNESS_LSB 0x723
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 5340099741ae..24ab1787b771 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -94,6 +94,7 @@ struct drm_dp_mst_port {
struct drm_dp_mst_topology_mgr *mgr;
struct edid *cached_edid; /* for DP logical ports - make tiling work */
+ bool has_audio;
};
/**
@@ -215,13 +216,13 @@ struct drm_dp_sideband_msg_rx {
struct drm_dp_sideband_msg_hdr initial_hdr;
};
-
+#define DRM_DP_MAX_SDP_STREAMS 16
struct drm_dp_allocate_payload {
u8 port_number;
u8 number_sdp_streams;
u8 vcpi;
u16 pbn;
- u8 sdp_stream_sink[8];
+ u8 sdp_stream_sink[DRM_DP_MAX_SDP_STREAMS];
};
struct drm_dp_allocate_payload_ack_reply {
@@ -420,7 +421,7 @@ struct drm_dp_payload {
struct drm_dp_mst_topology_mgr {
struct device *dev;
- struct drm_dp_mst_topology_cbs *cbs;
+ const struct drm_dp_mst_topology_cbs *cbs;
int max_dpcd_transaction_bytes;
struct drm_dp_aux *aux; /* auxch for this topology mgr to use */
int max_payloads;
@@ -450,9 +451,7 @@ struct drm_dp_mst_topology_mgr {
the mstb tx_slots and txmsg->state once they are queued */
struct mutex qlock;
struct list_head tx_msg_downq;
- struct list_head tx_msg_upq;
bool tx_down_in_progress;
- bool tx_up_in_progress;
/* payload info + lock for it */
struct mutex payload_lock;
@@ -484,6 +483,8 @@ int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handl
enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
+bool drm_dp_mst_port_has_audio(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port);
struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h
index 8b9cc3671858..82cdf611393d 100644
--- a/include/drm/drm_encoder_slave.h
+++ b/include/drm/drm_encoder_slave.h
@@ -95,7 +95,7 @@ struct drm_encoder_slave_funcs {
struct drm_encoder_slave {
struct drm_encoder base;
- struct drm_encoder_slave_funcs *slave_funcs;
+ const struct drm_encoder_slave_funcs *slave_funcs;
void *slave_priv;
void *bus_priv;
};
diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h
index c54cf3d4a03f..be62bd321e75 100644
--- a/include/drm/drm_fb_cma_helper.h
+++ b/include/drm/drm_fb_cma_helper.h
@@ -18,7 +18,7 @@ void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma);
void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma);
struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev,
- struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd);
+ struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd);
struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
unsigned int plane);
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 87b090c4b730..d8a40dff0d1d 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -34,6 +34,11 @@ struct drm_fb_helper;
#include <linux/kgdb.h>
+enum mode_set_atomic {
+ LEAVE_ATOMIC_MODE_SET,
+ ENTER_ATOMIC_MODE_SET,
+};
+
struct drm_fb_offset {
int x, y;
};
@@ -74,25 +79,76 @@ struct drm_fb_helper_surface_size {
/**
* struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library
- * @gamma_set: Set the given gamma lut register on the given crtc.
- * @gamma_get: Read the given gamma lut register on the given crtc, used to
- * save the current lut when force-restoring the fbdev for e.g.
- * kdbg.
- * @fb_probe: Driver callback to allocate and initialize the fbdev info
- * structure. Furthermore it also needs to allocate the drm
- * framebuffer used to back the fbdev.
- * @initial_config: Setup an initial fbdev display configuration
*
* Driver callbacks used by the fbdev emulation helper library.
*/
struct drm_fb_helper_funcs {
+ /**
+ * @gamma_set:
+ *
+ * Set the given gamma LUT register on the given CRTC.
+ *
+ * This callback is optional.
+ *
+ * FIXME:
+ *
+ * This callback is functionally redundant with the core gamma table
+ * support and simply exists because the fbdev hasn't yet been
+ * refactored to use the core gamma table interfaces.
+ */
void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno);
+ /**
+ * @gamma_get:
+ *
+ * Read the given gamma LUT register on the given CRTC, used to save the
+ * current LUT when force-restoring the fbdev for e.g. kdbg.
+ *
+ * This callback is optional.
+ *
+ * FIXME:
+ *
+ * This callback is functionally redundant with the core gamma table
+ * support and simply exists because the fbdev hasn't yet been
+ * refactored to use the core gamma table interfaces.
+ */
void (*gamma_get)(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, int regno);
+ /**
+ * @fb_probe:
+ *
+ * Driver callback to allocate and initialize the fbdev info structure.
+ * Furthermore it also needs to allocate the DRM framebuffer used to
+ * back the fbdev.
+ *
+ * This callback is mandatory.
+ *
+ * RETURNS:
+ *
+ * The driver should return 0 on success and a negative error code on
+ * failure.
+ */
int (*fb_probe)(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes);
+
+ /**
+ * @initial_config:
+ *
+ * Driver callback to setup an initial fbdev display configuration.
+ * Drivers can use this callback to tell the fbdev emulation what the
+ * preferred initial configuration is. This is useful to implement
+ * smooth booting where the fbdev (and subsequently all userspace) never
+ * changes the mode, but always inherits the existing configuration.
+ *
+ * This callback is optional.
+ *
+ * RETURNS:
+ *
+ * The driver should return true if a suitable initial configuration has
+ * been filled out and false when the fbdev helper should fall back to
+ * the default probing logic.
+ */
bool (*initial_config)(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_crtc **crtcs,
struct drm_display_mode **modes,
@@ -105,18 +161,22 @@ struct drm_fb_helper_connector {
};
/**
- * struct drm_fb_helper - helper to emulate fbdev on top of kms
- * @fb: Scanout framebuffer object
- * @dev: DRM device
+ * struct drm_fb_helper - main structure to emulate fbdev on top of KMS
+ * @fb: Scanout framebuffer object
+ * @dev: DRM device
* @crtc_count: number of possible CRTCs
* @crtc_info: per-CRTC helper state (mode, x/y offset, etc)
* @connector_count: number of connected connectors
* @connector_info_alloc_count: size of connector_info
+ * @connector_info: array of per-connector information
* @funcs: driver callbacks for fb helper
* @fbdev: emulated fbdev device info struct
* @pseudo_palette: fake palette of 16 colors
- * @kernel_fb_list: list_head in kernel_fb_helper_list
- * @delayed_hotplug: was there a hotplug while kms master active?
+ *
+ * This is the main structure used by the fbdev helpers. Drivers supporting
+ * fbdev emulation should embedded this into their overall driver structure.
+ * Drivers must also fill out a struct &drm_fb_helper_funcs with a few
+ * operations.
*/
struct drm_fb_helper {
struct drm_framebuffer *fb;
@@ -129,10 +189,21 @@ struct drm_fb_helper {
const struct drm_fb_helper_funcs *funcs;
struct fb_info *fbdev;
u32 pseudo_palette[17];
+
+ /**
+ * @kernel_fb_list:
+ *
+ * Entry on the global kernel_fb_helper_list, used for kgdb entry/exit.
+ */
struct list_head kernel_fb_list;
- /* we got a hotplug but fbdev wasn't running the console
- delay until next set_par */
+ /**
+ * @delayed_hotplug:
+ *
+ * A hotplug was received while fbdev wasn't in control of the DRM
+ * device, i.e. another KMS master was active. The output configuration
+ * needs to be reprobe when fbdev is in control again.
+ */
bool delayed_hotplug;
/**
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index 15e7f007380f..0b3e11ab8757 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -35,76 +35,129 @@
*/
/**
- * This structure defines the drm_mm memory object, which will be used by the
- * DRM for its buffer objects.
+ * struct drm_gem_object - GEM buffer object
+ *
+ * This structure defines the generic parts for GEM buffer objects, which are
+ * mostly around handling mmap and userspace handles.
+ *
+ * Buffer objects are often abbreviated to BO.
*/
struct drm_gem_object {
- /** Reference count of this object */
+ /**
+ * @refcount:
+ *
+ * Reference count of this object
+ *
+ * Please use drm_gem_object_reference() to acquire and
+ * drm_gem_object_unreference() or drm_gem_object_unreference_unlocked()
+ * to release a reference to a GEM buffer object.
+ */
struct kref refcount;
/**
- * handle_count - gem file_priv handle count of this object
+ * @handle_count:
+ *
+ * This is the GEM file_priv handle count of this object.
*
* Each handle also holds a reference. Note that when the handle_count
* drops to 0 any global names (e.g. the id in the flink namespace) will
* be cleared.
*
* Protected by dev->object_name_lock.
- * */
+ */
unsigned handle_count;
- /** Related drm device */
+ /**
+ * @dev: DRM dev this object belongs to.
+ */
struct drm_device *dev;
- /** File representing the shmem storage */
+ /**
+ * @filp:
+ *
+ * SHMEM file node used as backing storage for swappable buffer objects.
+ * GEM also supports driver private objects with driver-specific backing
+ * storage (contiguous CMA memory, special reserved blocks). In this
+ * case @filp is NULL.
+ */
struct file *filp;
- /* Mapping info for this object */
+ /**
+ * @vma_node:
+ *
+ * Mapping info for this object to support mmap. Drivers are supposed to
+ * allocate the mmap offset using drm_gem_create_mmap_offset(). The
+ * offset itself can be retrieved using drm_vma_node_offset_addr().
+ *
+ * Memory mapping itself is handled by drm_gem_mmap(), which also checks
+ * that userspace is allowed to access the object.
+ */
struct drm_vma_offset_node vma_node;
/**
+ * @size:
+ *
* Size of the object, in bytes. Immutable over the object's
* lifetime.
*/
size_t size;
/**
+ * @name:
+ *
* Global name for this object, starts at 1. 0 means unnamed.
- * Access is covered by the object_name_lock in the related drm_device
+ * Access is covered by dev->object_name_lock. This is used by the GEM_FLINK
+ * and GEM_OPEN ioctls.
*/
int name;
/**
- * Memory domains. These monitor which caches contain read/write data
+ * @read_domains:
+ *
+ * Read memory domains. These monitor which caches contain read/write data
* related to the object. When transitioning from one set of domains
* to another, the driver is called to ensure that caches are suitably
- * flushed and invalidated
+ * flushed and invalidated.
*/
uint32_t read_domains;
+
+ /**
+ * @write_domain: Corresponding unique write memory domain.
+ */
uint32_t write_domain;
/**
+ * @pending_read_domains:
+ *
* While validating an exec operation, the
* new read/write domain values are computed here.
* They will be transferred to the above values
* at the point that any cache flushing occurs
*/
uint32_t pending_read_domains;
+
+ /**
+ * @pending_write_domain: Write domain similar to @pending_read_domains.
+ */
uint32_t pending_write_domain;
/**
- * dma_buf - dma buf associated with this GEM object
+ * @dma_buf:
+ *
+ * dma-buf associated with this GEM object.
*
* Pointer to the dma-buf associated with this gem object (either
* through importing or exporting). We break the resulting reference
* loop when the last gem handle for this object is released.
*
- * Protected by obj->object_name_lock
+ * Protected by obj->object_name_lock.
*/
struct dma_buf *dma_buf;
/**
- * import_attach - dma buf attachment backing this object
+ * @import_attach:
+ *
+ * dma-buf attachment backing this object.
*
* Any foreign dma_buf imported as a gem object has this set to the
* attachment point for the device. This is invariant over the lifetime
@@ -133,12 +186,30 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
struct vm_area_struct *vma);
int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
+/**
+ * drm_gem_object_reference - acquire a GEM BO reference
+ * @obj: GEM buffer object
+ *
+ * This acquires additional reference to @obj. It is illegal to call this
+ * without already holding a reference. No locks required.
+ */
static inline void
drm_gem_object_reference(struct drm_gem_object *obj)
{
kref_get(&obj->refcount);
}
+/**
+ * drm_gem_object_unreference - release a GEM BO reference
+ * @obj: GEM buffer object
+ *
+ * This releases a reference to @obj. Callers must hold the dev->struct_mutex
+ * lock when calling this function, even when the driver doesn't use
+ * dev->struct_mutex for anything.
+ *
+ * For drivers not encumbered with legacy locking use
+ * drm_gem_object_unreference_unlocked() instead.
+ */
static inline void
drm_gem_object_unreference(struct drm_gem_object *obj)
{
@@ -149,6 +220,13 @@ drm_gem_object_unreference(struct drm_gem_object *obj)
}
}
+/**
+ * drm_gem_object_unreference_unlocked - release a GEM BO reference
+ * @obj: GEM buffer object
+ *
+ * This releases a reference to @obj. Callers must not hold the
+ * dev->struct_mutex lock when calling this function.
+ */
static inline void
drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
{
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index f1d8d0dbb4f1..1b3b1f8c8cdf 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -163,9 +163,36 @@ static inline struct mipi_dsi_device *to_mipi_dsi_device(struct device *dev)
return container_of(dev, struct mipi_dsi_device, dev);
}
+/**
+ * mipi_dsi_pixel_format_to_bpp - obtain the number of bits per pixel for any
+ * given pixel format defined by the MIPI DSI
+ * specification
+ * @fmt: MIPI DSI pixel format
+ *
+ * Returns: The number of bits per pixel of the given pixel format.
+ */
+static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)
+{
+ switch (fmt) {
+ case MIPI_DSI_FMT_RGB888:
+ case MIPI_DSI_FMT_RGB666:
+ return 24;
+
+ case MIPI_DSI_FMT_RGB666_PACKED:
+ return 18;
+
+ case MIPI_DSI_FMT_RGB565:
+ return 16;
+ }
+
+ return -EINVAL;
+}
+
struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np);
int mipi_dsi_attach(struct mipi_dsi_device *dsi);
int mipi_dsi_detach(struct mipi_dsi_device *dsi);
+int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi);
+int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi);
int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
u16 value);
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
index 0de6290df4da..fc65118e5077 100644
--- a/include/drm/drm_mm.h
+++ b/include/drm/drm_mm.h
@@ -148,8 +148,7 @@ static inline u64 drm_mm_hole_node_start(struct drm_mm_node *hole_node)
static inline u64 __drm_mm_hole_node_end(struct drm_mm_node *hole_node)
{
- return list_entry(hole_node->node_list.next,
- struct drm_mm_node, node_list)->start;
+ return list_next_entry(hole_node, node_list)->start;
}
/**
@@ -180,6 +179,14 @@ static inline u64 drm_mm_hole_node_end(struct drm_mm_node *hole_node)
&(mm)->head_node.node_list, \
node_list)
+#define __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, backwards) \
+ for (entry = list_entry((backwards) ? (mm)->hole_stack.prev : (mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
+ &entry->hole_stack != &(mm)->hole_stack ? \
+ hole_start = drm_mm_hole_node_start(entry), \
+ hole_end = drm_mm_hole_node_end(entry), \
+ 1 : 0; \
+ entry = list_entry((backwards) ? entry->hole_stack.prev : entry->hole_stack.next, struct drm_mm_node, hole_stack))
+
/**
* drm_mm_for_each_hole - iterator to walk over all holes
* @entry: drm_mm_node used internally to track progress
@@ -200,20 +207,7 @@ static inline u64 drm_mm_hole_node_end(struct drm_mm_node *hole_node)
* going backwards.
*/
#define drm_mm_for_each_hole(entry, mm, hole_start, hole_end) \
- for (entry = list_entry((mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
- &entry->hole_stack != &(mm)->hole_stack ? \
- hole_start = drm_mm_hole_node_start(entry), \
- hole_end = drm_mm_hole_node_end(entry), \
- 1 : 0; \
- entry = list_entry(entry->hole_stack.next, struct drm_mm_node, hole_stack))
-
-#define __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, backwards) \
- for (entry = list_entry((backwards) ? (mm)->hole_stack.prev : (mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
- &entry->hole_stack != &(mm)->hole_stack ? \
- hole_start = drm_mm_hole_node_start(entry), \
- hole_end = drm_mm_hole_node_end(entry), \
- 1 : 0; \
- entry = list_entry((backwards) ? entry->hole_stack.prev : entry->hole_stack.next, struct drm_mm_node, hole_stack))
+ __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, 0)
/*
* Basic range manager support (drm_mm.c)
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index 08a8cac9e555..625966a906f2 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -35,46 +35,91 @@
* structures).
*/
+/**
+ * enum drm_mode_status - hardware support status of a mode
+ * @MODE_OK: Mode OK
+ * @MODE_HSYNC: hsync out of range
+ * @MODE_VSYNC: vsync out of range
+ * @MODE_H_ILLEGAL: mode has illegal horizontal timings
+ * @MODE_V_ILLEGAL: mode has illegal horizontal timings
+ * @MODE_BAD_WIDTH: requires an unsupported linepitch
+ * @MODE_NOMODE: no mode with a matching name
+ * @MODE_NO_INTERLACE: interlaced mode not supported
+ * @MODE_NO_DBLESCAN: doublescan mode not supported
+ * @MODE_NO_VSCAN: multiscan mode not supported
+ * @MODE_MEM: insufficient video memory
+ * @MODE_VIRTUAL_X: mode width too large for specified virtual size
+ * @MODE_VIRTUAL_Y: mode height too large for specified virtual size
+ * @MODE_MEM_VIRT: insufficient video memory given virtual size
+ * @MODE_NOCLOCK: no fixed clock available
+ * @MODE_CLOCK_HIGH: clock required is too high
+ * @MODE_CLOCK_LOW: clock required is too low
+ * @MODE_CLOCK_RANGE: clock/mode isn't in a ClockRange
+ * @MODE_BAD_HVALUE: horizontal timing was out of range
+ * @MODE_BAD_VVALUE: vertical timing was out of range
+ * @MODE_BAD_VSCAN: VScan value out of range
+ * @MODE_HSYNC_NARROW: horizontal sync too narrow
+ * @MODE_HSYNC_WIDE: horizontal sync too wide
+ * @MODE_HBLANK_NARROW: horizontal blanking too narrow
+ * @MODE_HBLANK_WIDE: horizontal blanking too wide
+ * @MODE_VSYNC_NARROW: vertical sync too narrow
+ * @MODE_VSYNC_WIDE: vertical sync too wide
+ * @MODE_VBLANK_NARROW: vertical blanking too narrow
+ * @MODE_VBLANK_WIDE: vertical blanking too wide
+ * @MODE_PANEL: exceeds panel dimensions
+ * @MODE_INTERLACE_WIDTH: width too large for interlaced mode
+ * @MODE_ONE_WIDTH: only one width is supported
+ * @MODE_ONE_HEIGHT: only one height is supported
+ * @MODE_ONE_SIZE: only one resolution is supported
+ * @MODE_NO_REDUCED: monitor doesn't accept reduced blanking
+ * @MODE_NO_STEREO: stereo modes not supported
+ * @MODE_STALE: mode has become stale
+ * @MODE_BAD: unspecified reason
+ * @MODE_ERROR: error condition
+ *
+ * This enum is used to filter out modes not supported by the driver/hardware
+ * combination.
+ */
enum drm_mode_status {
- MODE_OK = 0, /* 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_UNVERIFIED = -3, /* mode needs to reverified */
- MODE_BAD = -2, /* unspecified reason */
- MODE_ERROR = -1 /* error condition */
+ MODE_OK = 0,
+ MODE_HSYNC,
+ MODE_VSYNC,
+ MODE_H_ILLEGAL,
+ MODE_V_ILLEGAL,
+ MODE_BAD_WIDTH,
+ MODE_NOMODE,
+ MODE_NO_INTERLACE,
+ MODE_NO_DBLESCAN,
+ MODE_NO_VSCAN,
+ MODE_MEM,
+ MODE_VIRTUAL_X,
+ MODE_VIRTUAL_Y,
+ MODE_MEM_VIRT,
+ MODE_NOCLOCK,
+ MODE_CLOCK_HIGH,
+ MODE_CLOCK_LOW,
+ MODE_CLOCK_RANGE,
+ MODE_BAD_HVALUE,
+ MODE_BAD_VVALUE,
+ MODE_BAD_VSCAN,
+ MODE_HSYNC_NARROW,
+ MODE_HSYNC_WIDE,
+ MODE_HBLANK_NARROW,
+ MODE_HBLANK_WIDE,
+ MODE_VSYNC_NARROW,
+ MODE_VSYNC_WIDE,
+ MODE_VBLANK_NARROW,
+ MODE_VBLANK_WIDE,
+ MODE_PANEL,
+ MODE_INTERLACE_WIDTH,
+ MODE_ONE_WIDTH,
+ MODE_ONE_HEIGHT,
+ MODE_ONE_SIZE,
+ MODE_NO_REDUCED,
+ MODE_NO_STEREO,
+ MODE_STALE = -3,
+ MODE_BAD = -2,
+ MODE_ERROR = -1
};
#define DRM_MODE_TYPE_CLOCK_CRTC_C (DRM_MODE_TYPE_CLOCK_C | \
@@ -96,17 +141,125 @@ enum drm_mode_status {
#define DRM_MODE_FLAG_3D_MAX DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF
+/**
+ * struct drm_display_mode - DRM kernel-internal display mode structure
+ * @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?!
+ * @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
+ *
+ * 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().
+ */
struct drm_display_mode {
- /* Header */
+ /**
+ * @head:
+ *
+ * struct list_head for mode lists.
+ */
struct list_head head;
+
+ /**
+ * @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.
+ */
struct drm_mode_object base;
+ /**
+ * @name:
+ *
+ * Human-readable name of the mode, filled out with drm_mode_set_name().
+ */
char name[DRM_DISPLAY_MODE_LEN];
+ /**
+ * @status:
+ *
+ * Status of the mode, used to filter out modes not supported by the
+ * hardware. See enum &drm_mode_status.
+ */
enum drm_mode_status status;
+
+ /**
+ * @type:
+ *
+ * A bitmask of flags, mostly about the source of a mode. Possible flags
+ * are:
+ *
+ * - DRM_MODE_TYPE_BUILTIN: Meant for hard-coded modes, effectively
+ * unused.
+ * - DRM_MODE_TYPE_PREFERRED: Preferred mode, usually the native
+ * resolution of an LCD panel. There should only be one preferred
+ * mode per connector at any given time.
+ * - DRM_MODE_TYPE_DRIVER: Mode created by the driver, which is all of
+ * them really. Drivers must set this bit for all modes they create
+ * and expose to userspace.
+ *
+ * Plus a big list of flags which shouldn't be used at all, but are
+ * still around since these flags are also used in the userspace ABI:
+ *
+ * - DRM_MODE_TYPE_DEFAULT: Again a leftover, use
+ * DRM_MODE_TYPE_PREFERRED instead.
+ * - DRM_MODE_TYPE_CLOCK_C and DRM_MODE_TYPE_CRTC_C: Define leftovers
+ * which are stuck around for hysterical raisins only. No one has an
+ * idea what they were meant for. Don't use.
+ * - DRM_MODE_TYPE_USERDEF: Mode defined by userspace, again a vestige
+ * from older kms designs where userspace had to first add a custom
+ * mode to the kernel's mode list before it could use it. Don't use.
+ */
unsigned int type;
- /* Proposed mode values */
+ /**
+ * @clock:
+ *
+ * Pixel clock in kHz.
+ */
int clock; /* in kHz */
int hdisplay;
int hsync_start;
@@ -118,14 +271,74 @@ struct drm_display_mode {
int vsync_end;
int vtotal;
int vscan;
+ /**
+ * @flags:
+ *
+ * Sync and timing flags:
+ *
+ * - DRM_MODE_FLAG_PHSYNC: horizontal sync is active high.
+ * - DRM_MODE_FLAG_NHSYNC: horizontal sync is active low.
+ * - DRM_MODE_FLAG_PVSYNC: vertical sync is active high.
+ * - DRM_MODE_FLAG_NVSYNC: vertical sync is active low.
+ * - DRM_MODE_FLAG_INTERLACE: mode is interlaced.
+ * - DRM_MODE_FLAG_DBLSCAN: mode uses doublescan.
+ * - DRM_MODE_FLAG_CSYNC: mode uses composite sync.
+ * - DRM_MODE_FLAG_PCSYNC: composite sync is active high.
+ * - DRM_MODE_FLAG_NCSYNC: composite sync is active low.
+ * - DRM_MODE_FLAG_HSKEW: hskew provided (not used?).
+ * - DRM_MODE_FLAG_BCAST: not used?
+ * - DRM_MODE_FLAG_PIXMUX: not used?
+ * - DRM_MODE_FLAG_DBLCLK: double-clocked mode.
+ * - DRM_MODE_FLAG_CLKDIV2: half-clocked mode.
+ *
+ * Additionally there's flags to specify how 3D modes are packed:
+ *
+ * - DRM_MODE_FLAG_3D_NONE: normal, non-3D mode.
+ * - DRM_MODE_FLAG_3D_FRAME_PACKING: 2 full frames for left and right.
+ * - DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE: interleaved like fields.
+ * - DRM_MODE_FLAG_3D_LINE_ALTERNATIVE: interleaved lines.
+ * - DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL: side-by-side full frames.
+ * - DRM_MODE_FLAG_3D_L_DEPTH: ?
+ * - DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH: ?
+ * - DRM_MODE_FLAG_3D_TOP_AND_BOTTOM: frame split into top and bottom
+ * parts.
+ * - DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF: frame split into left and
+ * right parts.
+ */
unsigned int flags;
- /* Addressable image size (may be 0 for projectors, etc.) */
+ /**
+ * @width_mm:
+ *
+ * Addressable size of the output in mm, projectors should set this to
+ * 0.
+ */
int width_mm;
+
+ /**
+ * @height_mm:
+ *
+ * Addressable size of the output in mm, projectors should set this to
+ * 0.
+ */
int height_mm;
- /* Actual mode we give to hw */
- int crtc_clock; /* in KHz */
+ /**
+ * @crtc_clock:
+ *
+ * Actual pixel or dot clock in the hardware. This differs from the
+ * logical @clock when e.g. using interlacing, double-clocking, stereo
+ * modes or other fancy stuff that changes the timings and signals
+ * actually sent over the wire.
+ *
+ * This is again in kHz.
+ *
+ * Note that with digital outputs like HDMI or DP there's usually a
+ * massive confusion between the dot clock and the signal clock at the
+ * bit encoding level. Especially when a 8b/10b encoding is used and the
+ * difference is exactly a factor of 10.
+ */
+ int crtc_clock;
int crtc_hdisplay;
int crtc_hblank_start;
int crtc_hblank_end;
@@ -140,12 +353,48 @@ struct drm_display_mode {
int crtc_vsync_end;
int crtc_vtotal;
- /* Driver private mode info */
+ /**
+ * @private:
+ *
+ * Pointer for driver private data. This can only be used for mode
+ * objects passed to drivers in modeset operations. It shouldn't be used
+ * by atomic drivers since they can store any additional data by
+ * subclassing state structures.
+ */
int *private;
+
+ /**
+ * @private_flags:
+ *
+ * Similar to @private, but just an integer.
+ */
int private_flags;
- int vrefresh; /* in Hz */
- int hsync; /* in kHz */
+ /**
+ * @vrefresh:
+ *
+ * Vertical refresh rate, for debug output in human readable form. Not
+ * used in a functional way.
+ *
+ * This value is in Hz.
+ */
+ int vrefresh;
+
+ /**
+ * @hsync:
+ *
+ * Horizontal refresh rate, for debug output in human readable form. Not
+ * used in a functional way.
+ *
+ * This value is in kHz.
+ */
+ int hsync;
+
+ /**
+ * @picture_aspect_ratio:
+ *
+ * Field for setting the HDMI picture aspect ratio of a mode.
+ */
enum hdmi_picture_aspect picture_aspect_ratio;
};
@@ -222,6 +471,8 @@ struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
const struct drm_display_mode *mode);
bool drm_mode_equal(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2);
+bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1,
+ const struct drm_display_mode *mode2);
bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2);
@@ -232,7 +483,7 @@ enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode,
void drm_mode_prune_invalid(struct drm_device *dev,
struct list_head *mode_list, bool verbose);
void drm_mode_sort(struct list_head *mode_list);
-void drm_mode_connector_list_update(struct drm_connector *connector, bool merge_type_bits);
+void drm_mode_connector_list_update(struct drm_connector *connector);
/* parsing cmdline modes */
bool
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
new file mode 100644
index 000000000000..a126a0d7aed4
--- /dev/null
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -0,0 +1,928 @@
+/*
+ * Copyright © 2006 Keith Packard
+ * Copyright © 2007-2008 Dave Airlie
+ * Copyright © 2007-2008 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ * Copyright © 2011-2013 Intel Corporation
+ * Copyright © 2015 Intel Corporation
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __DRM_MODESET_HELPER_VTABLES_H__
+#define __DRM_MODESET_HELPER_VTABLES_H__
+
+#include <drm/drm_crtc.h>
+
+/**
+ * DOC: overview
+ *
+ * The DRM mode setting helper functions are common code for drivers to use if
+ * they wish. Drivers are not forced to use this code in their
+ * implementations but it would be useful if the code they do use at least
+ * provides a consistent interface and operation to userspace. Therefore it is
+ * highly recommended to use the provided helpers as much as possible.
+ *
+ * Because there is only one pointer per modeset object to hold a vfunc table
+ * for helper libraries they are by necessity shared among the different
+ * helpers.
+ *
+ * To make this clear all the helper vtables are pulled together in this location here.
+ */
+
+enum mode_set_atomic;
+
+/**
+ * struct drm_crtc_helper_funcs - helper operations for CRTCs
+ *
+ * These hooks are used by the legacy CRTC helpers, the transitional plane
+ * helpers and the new atomic modesetting helpers.
+ */
+struct drm_crtc_helper_funcs {
+ /**
+ * @dpms:
+ *
+ * Callback to control power levels on the CRTC. If the mode passed in
+ * is unsupported, the provider must use the next lowest power level.
+ * This is used by the legacy CRTC helpers to implement DPMS
+ * functionality in drm_helper_connector_dpms().
+ *
+ * This callback is also used to disable a CRTC by calling it with
+ * DRM_MODE_DPMS_OFF if the @disable hook isn't used.
+ *
+ * This callback is used by the legacy CRTC helpers. Atomic helpers
+ * also support using this hook for enabling and disabling a CRTC to
+ * facilitate transitions to atomic, but it is deprecated. Instead
+ * @enable and @disable should be used.
+ */
+ void (*dpms)(struct drm_crtc *crtc, int mode);
+
+ /**
+ * @prepare:
+ *
+ * This callback should prepare the CRTC for a subsequent modeset, which
+ * in practice means the driver should disable the CRTC if it is
+ * running. Most drivers ended up implementing this by calling their
+ * @dpms hook with DRM_MODE_DPMS_OFF.
+ *
+ * This callback is used by the legacy CRTC helpers. Atomic helpers
+ * also support using this hook for disabling a CRTC to facilitate
+ * transitions to atomic, but it is deprecated. Instead @disable should
+ * be used.
+ */
+ void (*prepare)(struct drm_crtc *crtc);
+
+ /**
+ * @commit:
+ *
+ * This callback should commit the new mode on the CRTC after a modeset,
+ * which in practice means the driver should enable the CRTC. Most
+ * drivers ended up implementing this by calling their @dpms hook with
+ * DRM_MODE_DPMS_ON.
+ *
+ * This callback is used by the legacy CRTC helpers. Atomic helpers
+ * also support using this hook for enabling a CRTC to facilitate
+ * transitions to atomic, but it is deprecated. Instead @enable should
+ * be used.
+ */
+ void (*commit)(struct drm_crtc *crtc);
+
+ /**
+ * @mode_fixup:
+ *
+ * This callback is used to validate a mode. The parameter mode is the
+ * display mode that userspace requested, adjusted_mode is the mode the
+ * encoders need to be fed with. Note that this is the inverse semantics
+ * of the meaning for the &drm_encoder and &drm_bridge
+ * ->mode_fixup() functions. If the CRTC cannot support the requested
+ * conversion from mode to adjusted_mode it should reject the modeset.
+ *
+ * This function is used by both legacy CRTC helpers and atomic helpers.
+ * With atomic helpers it is optional.
+ *
+ * NOTE:
+ *
+ * This function is called in the check phase of atomic modesets, which
+ * can be aborted for any reason (including on userspace's request to
+ * just check whether a configuration would be possible). Atomic drivers
+ * MUST NOT touch any persistent state (hardware or software) or data
+ * structures except the passed in adjusted_mode parameter.
+ *
+ * This is in contrast to the legacy CRTC helpers where this was
+ * allowed.
+ *
+ * Atomic drivers which need to inspect and adjust more state should
+ * instead use the @atomic_check callback.
+ *
+ * Also beware that neither core nor helpers filter modes before
+ * passing them to the driver: While the list of modes that is
+ * advertised to userspace is filtered using the connector's
+ * ->mode_valid() callback, neither the core nor the helpers do any
+ * filtering on modes passed in from userspace when setting a mode. It
+ * is therefore possible for userspace to pass in a mode that was
+ * previously filtered out using ->mode_valid() or add a custom mode
+ * that wasn't probed from EDID or similar to begin with. Even though
+ * this is an advanced feature and rarely used nowadays, some users rely
+ * on being able to specify modes manually so drivers must be prepared
+ * to deal with it. Specifically this means that all drivers need not
+ * only validate modes in ->mode_valid() but also in ->mode_fixup() to
+ * make sure invalid modes passed in from userspace are rejected.
+ *
+ * RETURNS:
+ *
+ * True if an acceptable configuration is possible, false if the modeset
+ * operation should be rejected.
+ */
+ bool (*mode_fixup)(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+
+ /**
+ * @mode_set:
+ *
+ * This callback is used by the legacy CRTC helpers to set a new mode,
+ * position and framebuffer. Since it ties the primary plane to every
+ * mode change it is incompatible with universal plane support. And
+ * since it can't update other planes it's incompatible with atomic
+ * modeset support.
+ *
+ * This callback is only used by CRTC helpers and deprecated.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
+ int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode, int x, int y,
+ struct drm_framebuffer *old_fb);
+
+ /**
+ * @mode_set_nofb:
+ *
+ * This callback is used to update the display mode of a CRTC without
+ * changing anything of the primary plane configuration. This fits the
+ * requirement of atomic and hence is used by the atomic helpers. It is
+ * also used by the transitional plane helpers to implement a
+ * @mode_set hook in drm_helper_crtc_mode_set().
+ *
+ * Note that the display pipe is completely off when this function is
+ * called. Atomic drivers which need hardware to be running before they
+ * program the new display mode (e.g. because they implement runtime PM)
+ * should not use this hook. This is because the helper library calls
+ * this hook only once per mode change and not every time the display
+ * pipeline is suspended using either DPMS or the new "ACTIVE" property.
+ * Which means register values set in this callback might get reset when
+ * the CRTC is suspended, but not restored. Such drivers should instead
+ * move all their CRTC setup into the @enable callback.
+ *
+ * This callback is optional.
+ */
+ void (*mode_set_nofb)(struct drm_crtc *crtc);
+
+ /**
+ * @mode_set_base:
+ *
+ * This callback is used by the legacy CRTC helpers to set a new
+ * framebuffer and scanout position. It is optional and used as an
+ * optimized fast-path instead of a full mode set operation with all the
+ * resulting flickering. If it is not present
+ * drm_crtc_helper_set_config() will fall back to a full modeset, using
+ * the ->mode_set() callback. Since it can't update other planes it's
+ * incompatible with atomic modeset support.
+ *
+ * This callback is only used by the CRTC helpers and deprecated.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
+ int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb);
+
+ /**
+ * @mode_set_base_atomic:
+ *
+ * This callback is used by the fbdev helpers to set a new framebuffer
+ * and scanout without sleeping, i.e. from an atomic calling context. It
+ * is only used to implement kgdb support.
+ *
+ * This callback is optional and only needed for kgdb support in the fbdev
+ * helpers.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
+ int (*mode_set_base_atomic)(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb, int x, int y,
+ enum mode_set_atomic);
+
+ /**
+ * @load_lut:
+ *
+ * Load a LUT prepared with the @gamma_set functions from
+ * &drm_fb_helper_funcs.
+ *
+ * This callback is optional and is only used by the fbdev emulation
+ * helpers.
+ *
+ * FIXME:
+ *
+ * This callback is functionally redundant with the core gamma table
+ * support and simply exists because the fbdev hasn't yet been
+ * refactored to use the core gamma table interfaces.
+ */
+ void (*load_lut)(struct drm_crtc *crtc);
+
+ /**
+ * @disable:
+ *
+ * This callback should be used to disable the CRTC. With the atomic
+ * drivers it is called after all encoders connected to this CRTC have
+ * been shut off already using their own ->disable hook. If that
+ * sequence is too simple drivers can just add their own hooks and call
+ * it from this CRTC callback here by looping over all encoders
+ * connected to it using for_each_encoder_on_crtc().
+ *
+ * This hook is used both by legacy CRTC helpers and atomic helpers.
+ * Atomic drivers don't need to implement it if there's no need to
+ * disable anything at the CRTC level. To ensure that runtime PM
+ * handling (using either DPMS or the new "ACTIVE" property) works
+ * @disable must be the inverse of @enable for atomic drivers.
+ *
+ * NOTE:
+ *
+ * With legacy CRTC helpers there's a big semantic difference between
+ * @disable and other hooks (like @prepare or @dpms) used to shut down a
+ * CRTC: @disable is only called when also logically disabling the
+ * display pipeline and needs to release any resources acquired in
+ * @mode_set (like shared PLLs, or again release pinned framebuffers).
+ *
+ * Therefore @disable must be the inverse of @mode_set plus @commit for
+ * drivers still using legacy CRTC helpers, which is different from the
+ * rules under atomic.
+ */
+ void (*disable)(struct drm_crtc *crtc);
+
+ /**
+ * @enable:
+ *
+ * This callback should be used to enable the CRTC. With the atomic
+ * drivers it is called before all encoders connected to this CRTC are
+ * enabled through the encoder's own ->enable hook. If that sequence is
+ * too simple drivers can just add their own hooks and call it from this
+ * CRTC callback here by looping over all encoders connected to it using
+ * for_each_encoder_on_crtc().
+ *
+ * This hook is used only by atomic helpers, for symmetry with @disable.
+ * Atomic drivers don't need to implement it if there's no need to
+ * enable anything at the CRTC level. To ensure that runtime PM handling
+ * (using either DPMS or the new "ACTIVE" property) works
+ * @enable must be the inverse of @disable for atomic drivers.
+ */
+ void (*enable)(struct drm_crtc *crtc);
+
+ /**
+ * @atomic_check:
+ *
+ * Drivers should check plane-update related CRTC constraints in this
+ * hook. They can also check mode related limitations but need to be
+ * aware of the calling order, since this hook is used by
+ * drm_atomic_helper_check_planes() whereas the preparations needed to
+ * check output routing and the display mode is done in
+ * drm_atomic_helper_check_modeset(). Therefore drivers that want to
+ * check output routing and display mode constraints in this callback
+ * must ensure that drm_atomic_helper_check_modeset() has been called
+ * beforehand. This is calling order used by the default helper
+ * implementation in drm_atomic_helper_check().
+ *
+ * When using drm_atomic_helper_check_planes() CRTCs' ->atomic_check()
+ * hooks are called after the ones for planes, which allows drivers to
+ * assign shared resources requested by planes in the CRTC callback
+ * here. For more complicated dependencies the driver can call the provided
+ * check helpers multiple times until the computed state has a final
+ * configuration and everything has been checked.
+ *
+ * This function is also allowed to inspect any other object's state and
+ * can add more state objects to the atomic commit if needed. Care must
+ * be taken though to ensure that state check&compute functions for
+ * these added states are all called, and derived state in other objects
+ * all updated. Again the recommendation is to just call check helpers
+ * until a maximal configuration is reached.
+ *
+ * This callback is used by the atomic modeset helpers and by the
+ * transitional plane helpers, but it is optional.
+ *
+ * NOTE:
+ *
+ * This function is called in the check phase of an atomic update. The
+ * driver is not allowed to change anything outside of the free-standing
+ * state objects passed-in or assembled in the overall &drm_atomic_state
+ * update tracking structure.
+ *
+ * RETURNS:
+ *
+ * 0 on success, -EINVAL if the state or the transition can't be
+ * supported, -ENOMEM on memory allocation failure and -EDEADLK if an
+ * attempt to obtain another state object ran into a &drm_modeset_lock
+ * deadlock.
+ */
+ int (*atomic_check)(struct drm_crtc *crtc,
+ struct drm_crtc_state *state);
+
+ /**
+ * @atomic_begin:
+ *
+ * Drivers should prepare for an atomic update of multiple planes on
+ * a CRTC in this hook. Depending upon hardware this might be vblank
+ * evasion, blocking updates by setting bits or doing preparatory work
+ * for e.g. manual update display.
+ *
+ * This hook is called before any plane commit functions are called.
+ *
+ * Note that the power state of the display pipe when this function is
+ * called depends upon the exact helpers and calling sequence the driver
+ * has picked. See drm_atomic_commit_planes() for a discussion of the
+ * tradeoffs and variants of plane commit helpers.
+ *
+ * This callback is used by the atomic modeset helpers and by the
+ * transitional plane helpers, but it is optional.
+ */
+ void (*atomic_begin)(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_crtc_state);
+ /**
+ * @atomic_flush:
+ *
+ * Drivers should finalize an atomic update of multiple planes on
+ * a CRTC in this hook. Depending upon hardware this might include
+ * checking that vblank evasion was successful, unblocking updates by
+ * setting bits or setting the GO bit to flush out all updates.
+ *
+ * Simple hardware or hardware with special requirements can commit and
+ * flush out all updates for all planes from this hook and forgo all the
+ * other commit hooks for plane updates.
+ *
+ * This hook is called after any plane commit functions are called.
+ *
+ * Note that the power state of the display pipe when this function is
+ * called depends upon the exact helpers and calling sequence the driver
+ * has picked. See drm_atomic_commit_planes() for a discussion of the
+ * tradeoffs and variants of plane commit helpers.
+ *
+ * This callback is used by the atomic modeset helpers and by the
+ * transitional plane helpers, but it is optional.
+ */
+ void (*atomic_flush)(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_crtc_state);
+};
+
+/**
+ * drm_crtc_helper_add - sets the helper vtable for a crtc
+ * @crtc: DRM CRTC
+ * @funcs: helper vtable to set for @crtc
+ */
+static inline void drm_crtc_helper_add(struct drm_crtc *crtc,
+ const struct drm_crtc_helper_funcs *funcs)
+{
+ crtc->helper_private = funcs;
+}
+
+/**
+ * struct drm_encoder_helper_funcs - helper operations for encoders
+ *
+ * These hooks are used by the legacy CRTC helpers, the transitional plane
+ * helpers and the new atomic modesetting helpers.
+ */
+struct drm_encoder_helper_funcs {
+ /**
+ * @dpms:
+ *
+ * Callback to control power levels on the encoder. If the mode passed in
+ * is unsupported, the provider must use the next lowest power level.
+ * This is used by the legacy encoder helpers to implement DPMS
+ * functionality in drm_helper_connector_dpms().
+ *
+ * This callback is also used to disable an encoder by calling it with
+ * DRM_MODE_DPMS_OFF if the @disable hook isn't used.
+ *
+ * This callback is used by the legacy CRTC helpers. Atomic helpers
+ * also support using this hook for enabling and disabling an encoder to
+ * facilitate transitions to atomic, but it is deprecated. Instead
+ * @enable and @disable should be used.
+ */
+ void (*dpms)(struct drm_encoder *encoder, int mode);
+
+ /**
+ * @mode_fixup:
+ *
+ * This callback is used to validate and adjust a mode. The parameter
+ * mode is the display mode that should be fed to the next element in
+ * the display chain, either the final &drm_connector or a &drm_bridge.
+ * The parameter adjusted_mode is the input mode the encoder requires. It
+ * can be modified by this callback and does not need to match mode.
+ *
+ * This function is used by both legacy CRTC helpers and atomic helpers.
+ * With atomic helpers it is optional.
+ *
+ * NOTE:
+ *
+ * This function is called in the check phase of atomic modesets, which
+ * can be aborted for any reason (including on userspace's request to
+ * just check whether a configuration would be possible). Atomic drivers
+ * MUST NOT touch any persistent state (hardware or software) or data
+ * structures except the passed in adjusted_mode parameter.
+ *
+ * This is in contrast to the legacy CRTC helpers where this was
+ * allowed.
+ *
+ * Atomic drivers which need to inspect and adjust more state should
+ * instead use the @atomic_check callback.
+ *
+ * Also beware that neither core nor helpers filter modes before
+ * passing them to the driver: While the list of modes that is
+ * advertised to userspace is filtered using the connector's
+ * ->mode_valid() callback, neither the core nor the helpers do any
+ * filtering on modes passed in from userspace when setting a mode. It
+ * is therefore possible for userspace to pass in a mode that was
+ * previously filtered out using ->mode_valid() or add a custom mode
+ * that wasn't probed from EDID or similar to begin with. Even though
+ * this is an advanced feature and rarely used nowadays, some users rely
+ * on being able to specify modes manually so drivers must be prepared
+ * to deal with it. Specifically this means that all drivers need not
+ * only validate modes in ->mode_valid() but also in ->mode_fixup() to
+ * make sure invalid modes passed in from userspace are rejected.
+ *
+ * RETURNS:
+ *
+ * True if an acceptable configuration is possible, false if the modeset
+ * operation should be rejected.
+ */
+ bool (*mode_fixup)(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+
+ /**
+ * @prepare:
+ *
+ * This callback should prepare the encoder for a subsequent modeset,
+ * which in practice means the driver should disable the encoder if it
+ * is running. Most drivers ended up implementing this by calling their
+ * @dpms hook with DRM_MODE_DPMS_OFF.
+ *
+ * This callback is used by the legacy CRTC helpers. Atomic helpers
+ * also support using this hook for disabling an encoder to facilitate
+ * transitions to atomic, but it is deprecated. Instead @disable should
+ * be used.
+ */
+ void (*prepare)(struct drm_encoder *encoder);
+
+ /**
+ * @commit:
+ *
+ * This callback should commit the new mode on the encoder after a modeset,
+ * which in practice means the driver should enable the encoder. Most
+ * drivers ended up implementing this by calling their @dpms hook with
+ * DRM_MODE_DPMS_ON.
+ *
+ * This callback is used by the legacy CRTC helpers. Atomic helpers
+ * also support using this hook for enabling an encoder to facilitate
+ * transitions to atomic, but it is deprecated. Instead @enable should
+ * be used.
+ */
+ void (*commit)(struct drm_encoder *encoder);
+
+ /**
+ * @mode_set:
+ *
+ * This callback is used to update the display mode of an encoder.
+ *
+ * Note that the display pipe is completely off when this function is
+ * called. Drivers which need hardware to be running before they program
+ * the new display mode (because they implement runtime PM) should not
+ * use this hook, because the helper library calls it only once and not
+ * every time the display pipeline is suspend using either DPMS or the
+ * new "ACTIVE" property. Such drivers should instead move all their
+ * encoder setup into the ->enable() callback.
+ *
+ * This callback is used both by the legacy CRTC helpers and the atomic
+ * modeset helpers. It is optional in the atomic helpers.
+ */
+ void (*mode_set)(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+
+ /**
+ * @get_crtc:
+ *
+ * This callback is used by the legacy CRTC helpers to work around
+ * deficiencies in its own book-keeping.
+ *
+ * Do not use, use atomic helpers instead, which get the book keeping
+ * right.
+ *
+ * FIXME:
+ *
+ * Currently only nouveau is using this, and as soon as nouveau is
+ * atomic we can ditch this hook.
+ */
+ struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder);
+
+ /**
+ * @detect:
+ *
+ * This callback can be used by drivers who want to do detection on the
+ * encoder object instead of in connector functions.
+ *
+ * It is not used by any helper and therefore has purely driver-specific
+ * semantics. New drivers shouldn't use this and instead just implement
+ * their own private callbacks.
+ *
+ * FIXME:
+ *
+ * This should just be converted into a pile of driver vfuncs.
+ * Currently radeon, amdgpu and nouveau are using it.
+ */
+ enum drm_connector_status (*detect)(struct drm_encoder *encoder,
+ struct drm_connector *connector);
+
+ /**
+ * @disable:
+ *
+ * This callback should be used to disable the encoder. With the atomic
+ * drivers it is called before this encoder's CRTC has been shut off
+ * using the CRTC's own ->disable hook. If that sequence is too simple
+ * drivers can just add their own driver private encoder hooks and call
+ * them from CRTC's callback by looping over all encoders connected to
+ * it using for_each_encoder_on_crtc().
+ *
+ * This hook is used both by legacy CRTC helpers and atomic helpers.
+ * Atomic drivers don't need to implement it if there's no need to
+ * disable anything at the encoder level. To ensure that runtime PM
+ * handling (using either DPMS or the new "ACTIVE" property) works
+ * @disable must be the inverse of @enable for atomic drivers.
+ *
+ * NOTE:
+ *
+ * With legacy CRTC helpers there's a big semantic difference between
+ * @disable and other hooks (like @prepare or @dpms) used to shut down a
+ * encoder: @disable is only called when also logically disabling the
+ * display pipeline and needs to release any resources acquired in
+ * @mode_set (like shared PLLs, or again release pinned framebuffers).
+ *
+ * Therefore @disable must be the inverse of @mode_set plus @commit for
+ * drivers still using legacy CRTC helpers, which is different from the
+ * rules under atomic.
+ */
+ void (*disable)(struct drm_encoder *encoder);
+
+ /**
+ * @enable:
+ *
+ * This callback should be used to enable the encoder. With the atomic
+ * drivers it is called after this encoder's CRTC has been enabled using
+ * the CRTC's own ->enable hook. If that sequence is too simple drivers
+ * can just add their own driver private encoder hooks and call them
+ * from CRTC's callback by looping over all encoders connected to it
+ * using for_each_encoder_on_crtc().
+ *
+ * This hook is used only by atomic helpers, for symmetry with @disable.
+ * Atomic drivers don't need to implement it if there's no need to
+ * enable anything at the encoder level. To ensure that runtime PM handling
+ * (using either DPMS or the new "ACTIVE" property) works
+ * @enable must be the inverse of @disable for atomic drivers.
+ */
+ void (*enable)(struct drm_encoder *encoder);
+
+ /**
+ * @atomic_check:
+ *
+ * This callback is used to validate encoder state for atomic drivers.
+ * Since the encoder is the object connecting the CRTC and connector it
+ * gets passed both states, to be able to validate interactions and
+ * update the CRTC to match what the encoder needs for the requested
+ * connector.
+ *
+ * This function is used by the atomic helpers, but it is optional.
+ *
+ * NOTE:
+ *
+ * This function is called in the check phase of an atomic update. The
+ * driver is not allowed to change anything outside of the free-standing
+ * state objects passed-in or assembled in the overall &drm_atomic_state
+ * update tracking structure.
+ *
+ * RETURNS:
+ *
+ * 0 on success, -EINVAL if the state or the transition can't be
+ * supported, -ENOMEM on memory allocation failure and -EDEADLK if an
+ * attempt to obtain another state object ran into a &drm_modeset_lock
+ * deadlock.
+ */
+ int (*atomic_check)(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state);
+};
+
+/**
+ * drm_encoder_helper_add - sets the helper vtable for an encoder
+ * @encoder: DRM encoder
+ * @funcs: helper vtable to set for @encoder
+ */
+static inline void drm_encoder_helper_add(struct drm_encoder *encoder,
+ const struct drm_encoder_helper_funcs *funcs)
+{
+ encoder->helper_private = funcs;
+}
+
+/**
+ * struct drm_connector_helper_funcs - helper operations for connectors
+ *
+ * These functions are used by the atomic and legacy modeset helpers and by the
+ * probe helpers.
+ */
+struct drm_connector_helper_funcs {
+ /**
+ * @get_modes:
+ *
+ * This function should fill in all modes currently valid for the sink
+ * into the connector->probed_modes list. It should also update the
+ * EDID property by calling drm_mode_connector_update_edid_property().
+ *
+ * The usual way to implement this is to cache the EDID retrieved in the
+ * probe callback somewhere in the driver-private connector structure.
+ * In this function drivers then parse the modes in the EDID and add
+ * them by calling drm_add_edid_modes(). But connectors that driver a
+ * fixed panel can also manually add specific modes using
+ * drm_mode_probed_add(). Drivers which manually add modes should also
+ * make sure that the @display_info, @width_mm and @height_mm fields of the
+ * struct #drm_connector are filled in.
+ *
+ * Virtual drivers that just want some standard VESA mode with a given
+ * resolution can call drm_add_modes_noedid(), and mark the preferred
+ * one using drm_set_preferred_mode().
+ *
+ * Finally drivers that support audio probably want to update the ELD
+ * data, too, using drm_edid_to_eld().
+ *
+ * This function is only called after the ->detect() hook has indicated
+ * that a sink is connected and when the EDID isn't overridden through
+ * sysfs or the kernel commandline.
+ *
+ * This callback is used by the probe helpers in e.g.
+ * drm_helper_probe_single_connector_modes().
+ *
+ * RETURNS:
+ *
+ * The number of modes added by calling drm_mode_probed_add().
+ */
+ int (*get_modes)(struct drm_connector *connector);
+
+ /**
+ * @mode_valid:
+ *
+ * Callback to validate a mode for a connector, irrespective of the
+ * specific display configuration.
+ *
+ * This callback is used by the probe helpers to filter the mode list
+ * (which is usually derived from the EDID data block from the sink).
+ * See e.g. drm_helper_probe_single_connector_modes().
+ *
+ * NOTE:
+ *
+ * This only filters the mode list supplied to userspace in the
+ * GETCONNECOTR IOCTL. Userspace is free to create modes of its own and
+ * ask the kernel to use them. It this case the atomic helpers or legacy
+ * CRTC helpers will not call this function. Drivers therefore must
+ * still fully validate any mode passed in in a modeset request.
+ *
+ * RETURNS:
+ *
+ * Either MODE_OK or one of the failure reasons in enum
+ * &drm_mode_status.
+ */
+ enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
+ struct drm_display_mode *mode);
+ /**
+ * @best_encoder:
+ *
+ * This function should select the best encoder for the given connector.
+ *
+ * This function is used by both the atomic helpers (in the
+ * drm_atomic_helper_check_modeset() function) and in the legacy CRTC
+ * helpers.
+ *
+ * NOTE:
+ *
+ * In atomic drivers this function is called in the check phase of an
+ * atomic update. The driver is not allowed to change or inspect
+ * anything outside of arguments passed-in. Atomic drivers which need to
+ * inspect dynamic configuration state should instead use
+ * @atomic_best_encoder.
+ *
+ * RETURNS:
+ *
+ * Encoder that should be used for the given connector and connector
+ * state, or NULL if no suitable encoder exists. Note that the helpers
+ * will ensure that encoders aren't used twice, drivers should not check
+ * for this.
+ */
+ struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
+
+ /**
+ * @atomic_best_encoder:
+ *
+ * This is the atomic version of @best_encoder for atomic drivers which
+ * need to select the best encoder depending upon the desired
+ * configuration and can't select it statically.
+ *
+ * This function is used by drm_atomic_helper_check_modeset() and either
+ * this or @best_encoder is required.
+ *
+ * NOTE:
+ *
+ * This function is called in the check phase of an atomic update. The
+ * driver is not allowed to change anything outside of the free-standing
+ * state objects passed-in or assembled in the overall &drm_atomic_state
+ * update tracking structure.
+ *
+ * RETURNS:
+ *
+ * Encoder that should be used for the given connector and connector
+ * state, or NULL if no suitable encoder exists. Note that the helpers
+ * will ensure that encoders aren't used twice, drivers should not check
+ * for this.
+ */
+ struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector,
+ struct drm_connector_state *connector_state);
+};
+
+/**
+ * drm_connector_helper_add - sets the helper vtable for a connector
+ * @connector: DRM connector
+ * @funcs: helper vtable to set for @connector
+ */
+static inline void drm_connector_helper_add(struct drm_connector *connector,
+ const struct drm_connector_helper_funcs *funcs)
+{
+ connector->helper_private = funcs;
+}
+
+/**
+ * struct drm_plane_helper_funcs - helper operations for planes
+ *
+ * These functions are used by the atomic helpers and by the transitional plane
+ * helpers.
+ */
+struct drm_plane_helper_funcs {
+ /**
+ * @prepare_fb:
+ *
+ * This hook is to prepare a framebuffer for scanout by e.g. pinning
+ * it's backing storage or relocating it into a contiguous block of
+ * VRAM. Other possible preparatory work includes flushing caches.
+ *
+ * This function must not block for outstanding rendering, since it is
+ * called in the context of the atomic IOCTL even for async commits to
+ * be able to return any errors to userspace. Instead the recommended
+ * way is to fill out the fence member of the passed-in
+ * &drm_plane_state. If the driver doesn't support native fences then
+ * equivalent functionality should be implemented through private
+ * members in the plane structure.
+ *
+ * The helpers will call @cleanup_fb with matching arguments for every
+ * successful call to this hook.
+ *
+ * This callback is used by the atomic modeset helpers and by the
+ * transitional plane helpers, but it is optional.
+ *
+ * RETURNS:
+ *
+ * 0 on success or one of the following negative error codes allowed by
+ * the atomic_commit hook in &drm_mode_config_funcs. When using helpers
+ * this callback is the only one which can fail an atomic commit,
+ * everything else must complete successfully.
+ */
+ int (*prepare_fb)(struct drm_plane *plane,
+ const struct drm_plane_state *new_state);
+ /**
+ * @cleanup_fb:
+ *
+ * This hook is called to clean up any resources allocated for the given
+ * framebuffer and plane configuration in @prepare_fb.
+ *
+ * This callback is used by the atomic modeset helpers and by the
+ * transitional plane helpers, but it is optional.
+ */
+ void (*cleanup_fb)(struct drm_plane *plane,
+ const struct drm_plane_state *old_state);
+
+ /**
+ * @atomic_check:
+ *
+ * Drivers should check plane specific constraints in this hook.
+ *
+ * When using drm_atomic_helper_check_planes() plane's ->atomic_check()
+ * hooks are called before the ones for CRTCs, which allows drivers to
+ * request shared resources that the CRTC controls here. For more
+ * complicated dependencies the driver can call the provided check helpers
+ * multiple times until the computed state has a final configuration and
+ * everything has been checked.
+ *
+ * This function is also allowed to inspect any other object's state and
+ * can add more state objects to the atomic commit if needed. Care must
+ * be taken though to ensure that state check&compute functions for
+ * these added states are all called, and derived state in other objects
+ * all updated. Again the recommendation is to just call check helpers
+ * until a maximal configuration is reached.
+ *
+ * This callback is used by the atomic modeset helpers and by the
+ * transitional plane helpers, but it is optional.
+ *
+ * NOTE:
+ *
+ * This function is called in the check phase of an atomic update. The
+ * driver is not allowed to change anything outside of the free-standing
+ * state objects passed-in or assembled in the overall &drm_atomic_state
+ * update tracking structure.
+ *
+ * RETURNS:
+ *
+ * 0 on success, -EINVAL if the state or the transition can't be
+ * supported, -ENOMEM on memory allocation failure and -EDEADLK if an
+ * attempt to obtain another state object ran into a &drm_modeset_lock
+ * deadlock.
+ */
+ int (*atomic_check)(struct drm_plane *plane,
+ struct drm_plane_state *state);
+
+ /**
+ * @atomic_update:
+ *
+ * Drivers should use this function to update the plane state. This
+ * hook is called in-between the ->atomic_begin() and
+ * ->atomic_flush() of &drm_crtc_helper_funcs.
+ *
+ * Note that the power state of the display pipe when this function is
+ * called depends upon the exact helpers and calling sequence the driver
+ * has picked. See drm_atomic_commit_planes() for a discussion of the
+ * tradeoffs and variants of plane commit helpers.
+ *
+ * This callback is used by the atomic modeset helpers and by the
+ * transitional plane helpers, but it is optional.
+ */
+ void (*atomic_update)(struct drm_plane *plane,
+ struct drm_plane_state *old_state);
+ /**
+ * @atomic_disable:
+ *
+ * Drivers should use this function to unconditionally disable a plane.
+ * This hook is called in-between the ->atomic_begin() and
+ * ->atomic_flush() of &drm_crtc_helper_funcs. It is an alternative to
+ * @atomic_update, which will be called for disabling planes, too, if
+ * the @atomic_disable hook isn't implemented.
+ *
+ * This hook is also useful to disable planes in preparation of a modeset,
+ * by calling drm_atomic_helper_disable_planes_on_crtc() from the
+ * ->disable() hook in &drm_crtc_helper_funcs.
+ *
+ * Note that the power state of the display pipe when this function is
+ * called depends upon the exact helpers and calling sequence the driver
+ * has picked. See drm_atomic_commit_planes() for a discussion of the
+ * tradeoffs and variants of plane commit helpers.
+ *
+ * This callback is used by the atomic modeset helpers and by the
+ * transitional plane helpers, but it is optional.
+ */
+ void (*atomic_disable)(struct drm_plane *plane,
+ struct drm_plane_state *old_state);
+};
+
+/**
+ * drm_plane_helper_add - sets the helper vtable for a plane
+ * @plane: DRM plane
+ * @funcs: helper vtable to set for @plane
+ */
+static inline void drm_plane_helper_add(struct drm_plane *plane,
+ const struct drm_plane_helper_funcs *funcs)
+{
+ plane->helper_private = funcs;
+}
+
+#endif
diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h
index 94938d89347c..c5576fbcb909 100644
--- a/include/drm/drm_modeset_lock.h
+++ b/include/drm/drm_modeset_lock.h
@@ -138,7 +138,7 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
struct drm_modeset_acquire_ctx *
drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc);
-int drm_modeset_lock_all_crtcs(struct drm_device *dev,
- struct drm_modeset_acquire_ctx *ctx);
+int drm_modeset_lock_all_ctx(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx);
#endif /* DRM_MODESET_LOCK_H_ */
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h
index 5a7f9d4efb1d..4421f3f4ca8d 100644
--- a/include/drm/drm_plane_helper.h
+++ b/include/drm/drm_plane_helper.h
@@ -26,6 +26,7 @@
#include <drm/drm_rect.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_modeset_helper_vtables.h>
/*
* Drivers that don't allow primary plane scaling may pass this macro in place
@@ -36,46 +37,9 @@
*/
#define DRM_PLANE_HELPER_NO_SCALING (1<<16)
-/**
- * DOC: plane helpers
- *
- * Helper functions to assist with creation and handling of CRTC primary
- * planes.
- */
-
int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
const struct drm_crtc_funcs *funcs);
-/**
- * drm_plane_helper_funcs - helper operations for CRTCs
- * @prepare_fb: prepare a framebuffer for use by the plane
- * @cleanup_fb: cleanup a framebuffer when it's no longer used by the plane
- * @atomic_check: check that a given atomic state is valid and can be applied
- * @atomic_update: apply an atomic state to the plane (mandatory)
- * @atomic_disable: disable the plane
- *
- * The helper operations are called by the mid-layer CRTC helper.
- */
-struct drm_plane_helper_funcs {
- int (*prepare_fb)(struct drm_plane *plane,
- const struct drm_plane_state *new_state);
- void (*cleanup_fb)(struct drm_plane *plane,
- const struct drm_plane_state *old_state);
-
- int (*atomic_check)(struct drm_plane *plane,
- struct drm_plane_state *state);
- void (*atomic_update)(struct drm_plane *plane,
- struct drm_plane_state *old_state);
- void (*atomic_disable)(struct drm_plane *plane,
- struct drm_plane_state *old_state);
-};
-
-static inline void drm_plane_helper_add(struct drm_plane *plane,
- const struct drm_plane_helper_funcs *funcs)
-{
- plane->helper_private = funcs;
-}
-
int drm_plane_helper_check_update(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
diff --git a/include/drm/drm_rect.h b/include/drm/drm_rect.h
index 26bb55e9e8b6..83bb156d4356 100644
--- a/include/drm/drm_rect.h
+++ b/include/drm/drm_rect.h
@@ -162,7 +162,8 @@ int drm_rect_calc_hscale_relaxed(struct drm_rect *src,
int drm_rect_calc_vscale_relaxed(struct drm_rect *src,
struct drm_rect *dst,
int min_vscale, int max_vscale);
-void drm_rect_debug_print(const struct drm_rect *r, bool fixed_point);
+void drm_rect_debug_print(const char *prefix,
+ const struct drm_rect *r, bool fixed_point);
void drm_rect_rotate(struct drm_rect *r,
int width, int height,
unsigned int rotation);
diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
index 30d89e0da2c6..b46fa0ef3005 100644
--- a/include/drm/i915_component.h
+++ b/include/drm/i915_component.h
@@ -31,47 +31,94 @@
#define MAX_PORTS 5
/**
- * struct i915_audio_component_ops - callbacks defined in gfx driver
- * @owner: the module owner
- * @get_power: get the POWER_DOMAIN_AUDIO power well
- * @put_power: put the POWER_DOMAIN_AUDIO power well
- * @codec_wake_override: Enable/Disable generating the codec wake signal
- * @get_cdclk_freq: get the Core Display Clock in KHz
- * @sync_audio_rate: set n/cts based on the sample rate
+ * struct i915_audio_component_ops - Ops implemented by i915 driver, called by hda driver
*/
struct i915_audio_component_ops {
+ /**
+ * @owner: i915 module
+ */
struct module *owner;
+ /**
+ * @get_power: get the POWER_DOMAIN_AUDIO power well
+ *
+ * Request the power well to be turned on.
+ */
void (*get_power)(struct device *);
+ /**
+ * @put_power: put the POWER_DOMAIN_AUDIO power well
+ *
+ * Allow the power well to be turned off.
+ */
void (*put_power)(struct device *);
+ /**
+ * @codec_wake_override: Enable/disable codec wake signal
+ */
void (*codec_wake_override)(struct device *, bool enable);
+ /**
+ * @get_cdclk_freq: Get the Core Display Clock in kHz
+ */
int (*get_cdclk_freq)(struct device *);
+ /**
+ * @sync_audio_rate: set n/cts based on the sample rate
+ *
+ * Called from audio driver. After audio driver sets the
+ * sample rate, it will call this function to set n/cts
+ */
int (*sync_audio_rate)(struct device *, int port, int rate);
+ /**
+ * @get_eld: fill the audio state and ELD bytes for the given port
+ *
+ * Called from audio driver to get the HDMI/DP audio state of the given
+ * digital port, and also fetch ELD bytes to the given pointer.
+ *
+ * It returns the byte size of the original ELD (not the actually
+ * copied size), zero for an invalid ELD, or a negative error code.
+ *
+ * Note that the returned size may be over @max_bytes. Then it
+ * implies that only a part of ELD has been copied to the buffer.
+ */
+ int (*get_eld)(struct device *, int port, bool *enabled,
+ unsigned char *buf, int max_bytes);
};
+/**
+ * struct i915_audio_component_audio_ops - Ops implemented by hda driver, called by i915 driver
+ */
struct i915_audio_component_audio_ops {
+ /**
+ * @audio_ptr: Pointer to be used in call to pin_eld_notify
+ */
void *audio_ptr;
/**
- * Call from i915 driver, notifying the HDA driver that
- * pin sense and/or ELD information has changed.
- * @audio_ptr: HDA driver object
- * @port: Which port has changed (PORTA / PORTB / PORTC etc)
+ * @pin_eld_notify: Notify the HDA driver that pin sense and/or ELD information has changed
+ *
+ * Called when the i915 driver has set up audio pipeline or has just
+ * begun to tear it down. This allows the HDA driver to update its
+ * status accordingly (even when the HDA controller is in power save
+ * mode).
*/
void (*pin_eld_notify)(void *audio_ptr, int port);
};
/**
- * struct i915_audio_component - used for audio video interaction
- * @dev: the device from gfx driver
- * @aud_sample_rate: the array of audio sample rate per port
- * @ops: callback for audio driver calling
- * @audio_ops: Call from i915 driver
+ * struct i915_audio_component - Used for direct communication between i915 and hda drivers
*/
struct i915_audio_component {
+ /**
+ * @dev: i915 device, used as parameter for ops
+ */
struct device *dev;
+ /**
+ * @aud_sample_rate: the array of audio sample rate per port
+ */
int aud_sample_rate[MAX_PORTS];
-
+ /**
+ * @ops: Ops implemented by i915 driver, called by hda driver
+ */
const struct i915_audio_component_ops *ops;
-
+ /**
+ * @audio_ops: Ops implemented by hda driver, called by i915 driver
+ */
const struct i915_audio_component_audio_ops *audio_ops;
};
diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h
index 17c445612e01..f97020904717 100644
--- a/include/drm/i915_pciids.h
+++ b/include/drm/i915_pciids.h
@@ -279,16 +279,59 @@
#define INTEL_SKL_GT3_IDS(info) \
INTEL_VGA_DEVICE(0x1926, info), /* ULT GT3 */ \
INTEL_VGA_DEVICE(0x192B, info), /* Halo GT3 */ \
- INTEL_VGA_DEVICE(0x192A, info) /* SRV GT3 */ \
+ INTEL_VGA_DEVICE(0x192A, info) /* SRV GT3 */
-#define INTEL_SKL_IDS(info) \
+#define INTEL_SKL_GT4_IDS(info) \
+ INTEL_VGA_DEVICE(0x1932, info), /* DT GT4 */ \
+ INTEL_VGA_DEVICE(0x193B, info), /* Halo GT4 */ \
+ INTEL_VGA_DEVICE(0x193D, info), /* WKS GT4 */ \
+ INTEL_VGA_DEVICE(0x193A, info) /* SRV GT4 */
+
+#define INTEL_SKL_IDS(info) \
INTEL_SKL_GT1_IDS(info), \
INTEL_SKL_GT2_IDS(info), \
- INTEL_SKL_GT3_IDS(info)
+ INTEL_SKL_GT3_IDS(info), \
+ INTEL_SKL_GT4_IDS(info)
#define INTEL_BXT_IDS(info) \
INTEL_VGA_DEVICE(0x0A84, info), \
INTEL_VGA_DEVICE(0x1A84, info), \
INTEL_VGA_DEVICE(0x5A84, info)
+#define INTEL_KBL_GT1_IDS(info) \
+ INTEL_VGA_DEVICE(0x5913, info), /* ULT GT1.5 */ \
+ INTEL_VGA_DEVICE(0x5915, info), /* ULX GT1.5 */ \
+ INTEL_VGA_DEVICE(0x5917, info), /* DT GT1.5 */ \
+ INTEL_VGA_DEVICE(0x5906, info), /* ULT GT1 */ \
+ INTEL_VGA_DEVICE(0x590E, info), /* ULX GT1 */ \
+ INTEL_VGA_DEVICE(0x5902, info), /* DT GT1 */ \
+ INTEL_VGA_DEVICE(0x590B, info), /* Halo GT1 */ \
+ INTEL_VGA_DEVICE(0x590A, info) /* SRV GT1 */
+
+#define INTEL_KBL_GT2_IDS(info) \
+ INTEL_VGA_DEVICE(0x5916, info), /* ULT GT2 */ \
+ INTEL_VGA_DEVICE(0x5921, info), /* ULT GT2F */ \
+ INTEL_VGA_DEVICE(0x591E, info), /* ULX GT2 */ \
+ INTEL_VGA_DEVICE(0x5912, info), /* DT GT2 */ \
+ INTEL_VGA_DEVICE(0x591B, info), /* Halo GT2 */ \
+ INTEL_VGA_DEVICE(0x591A, info), /* SRV GT2 */ \
+ INTEL_VGA_DEVICE(0x591D, info) /* WKS GT2 */
+
+#define INTEL_KBL_GT3_IDS(info) \
+ INTEL_VGA_DEVICE(0x5926, info), /* ULT GT3 */ \
+ INTEL_VGA_DEVICE(0x592B, info), /* Halo GT3 */ \
+ INTEL_VGA_DEVICE(0x592A, info) /* SRV GT3 */
+
+#define INTEL_KBL_GT4_IDS(info) \
+ INTEL_VGA_DEVICE(0x5932, info), /* DT GT4 */ \
+ INTEL_VGA_DEVICE(0x593B, info), /* Halo GT4 */ \
+ INTEL_VGA_DEVICE(0x593A, info), /* SRV GT4 */ \
+ INTEL_VGA_DEVICE(0x593D, info) /* WKS GT4 */
+
+#define INTEL_KBL_IDS(info) \
+ INTEL_KBL_GT1_IDS(info), \
+ INTEL_KBL_GT2_IDS(info), \
+ INTEL_KBL_GT3_IDS(info), \
+ INTEL_KBL_GT4_IDS(info)
+
#endif /* _I915_PCIIDS_H */
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index c768ddfbe53c..afae2316bd43 100644
--- a/include/drm/ttm/ttm_bo_api.h
+++ b/include/drm/ttm/ttm_bo_api.h
@@ -383,6 +383,16 @@ extern void ttm_bo_add_to_lru(struct ttm_buffer_object *bo);
*/
extern int ttm_bo_del_from_lru(struct ttm_buffer_object *bo);
+/**
+ * ttm_bo_move_to_lru_tail
+ *
+ * @bo: The buffer object.
+ *
+ * Move this BO to the tail of all lru lists used to lookup and reserve an
+ * object. This function must be called with struct ttm_bo_global::lru_lock
+ * held, and is used to make a BO less likely to be considered for eviction.
+ */
+extern void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo);
/**
* ttm_bo_lock_delayed_workqueue
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 813042cede57..3d4bf08aa21f 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -826,10 +826,10 @@ static inline int __ttm_bo_reserve(struct ttm_buffer_object *bo,
* reserved, the validation sequence is checked against the validation
* sequence of the process currently reserving the buffer,
* and if the current validation sequence is greater than that of the process
- * holding the reservation, the function returns -EAGAIN. Otherwise it sleeps
+ * holding the reservation, the function returns -EDEADLK. Otherwise it sleeps
* waiting for the buffer to become unreserved, after which it retries
* reserving.
- * The caller should, when receiving an -EAGAIN error
+ * The caller should, when receiving an -EDEADLK error
* release all its buffer reservations, wait for @bo to become unreserved, and
* then rerun the validation with the same validation sequence. This procedure
* will always guarantee that the process with the lowest validation sequence