summaryrefslogtreecommitdiff
path: root/include/drm
diff options
context:
space:
mode:
Diffstat (limited to 'include/drm')
-rw-r--r--include/drm/drmP.h1
-rw-r--r--include/drm/drm_atomic.h6
-rw-r--r--include/drm/drm_crtc.h149
3 files changed, 150 insertions, 6 deletions
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 086ad96d7d62..ae9ff73f1a0c 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -284,6 +284,7 @@ struct drm_ioctl_desc {
/* Event queued up for userspace to read */
struct drm_pending_event {
+ struct completion *completion;
struct drm_event *event;
struct fence *fence;
struct list_head link;
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index a16861c882aa..856a9c85a838 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -30,6 +30,12 @@
#include <drm/drm_crtc.h>
+void drm_crtc_commit_put(struct drm_crtc_commit *commit);
+static inline void drm_crtc_commit_get(struct drm_crtc_commit *commit)
+{
+ kref_get(&commit->ref);
+}
+
struct drm_atomic_state * __must_check
drm_atomic_state_alloc(struct drm_device *dev);
void drm_atomic_state_clear(struct drm_atomic_state *state);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 7bf065b61316..5eb1f0884848 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -728,9 +728,6 @@ struct drm_crtc_funcs {
* @gamma_store: gamma ramp values
* @helper_private: mid-layer private data
* @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
*
* Each CRTC may have one or more connectors associated with it. This structure
* allows the CRTC to be controlled.
@@ -787,11 +784,37 @@ struct drm_crtc {
struct drm_object_properties properties;
+ /**
+ * @state:
+ *
+ * Current atomic state for this CRTC.
+ */
struct drm_crtc_state *state;
- /*
- * For legacy crtc IOCTLs so that atomic drivers can get at the locking
- * acquire context.
+ /**
+ * @commit_list:
+ *
+ * List of &drm_crtc_commit structures tracking pending commits.
+ * Protected by @commit_lock. This list doesn't hold its own full
+ * reference, but burrows it from the ongoing commit. Commit entries
+ * must be removed from this list once the commit is fully completed,
+ * but before it's correspoding &drm_atomic_state gets destroyed.
+ */
+ struct list_head commit_list;
+
+ /**
+ * @commit_lock:
+ *
+ * Spinlock to protect @commit_list.
+ */
+ spinlock_t commit_lock;
+
+ /**
+ * @acquire_ctx:
+ *
+ * Per-CRTC implicit acquire context used by atomic drivers for legacy
+ * IOCTLs, so that atomic drivers can get at the locking acquire
+ * context.
*/
struct drm_modeset_acquire_ctx *acquire_ctx;
};
@@ -1733,6 +1756,111 @@ struct drm_bridge {
void *driver_private;
};
+/**
+ * struct drm_crtc_commit - track modeset commits on a CRTC
+ *
+ * This structure is used to track pending modeset changes and atomic commit on
+ * a per-CRTC basis. Since updating the list should never block this structure
+ * is reference counted to allow waiters to safely wait on an event to complete,
+ * without holding any locks.
+ *
+ * It has 3 different events in total to allow a fine-grained synchronization
+ * between outstanding updates::
+ *
+ * atomic commit thread hardware
+ *
+ * write new state into hardware ----> ...
+ * signal hw_done
+ * switch to new state on next
+ * ... v/hblank
+ *
+ * wait for buffers to show up ...
+ *
+ * ... send completion irq
+ * irq handler signals flip_done
+ * cleanup old buffers
+ *
+ * signal cleanup_done
+ *
+ * wait for flip_done <----
+ * clean up atomic state
+ *
+ * The important bit to know is that cleanup_done is the terminal event, but the
+ * ordering between flip_done and hw_done is entirely up to the specific driver
+ * and modeset state change.
+ *
+ * For an implementation of how to use this look at
+ * drm_atomic_helper_setup_commit() from the atomic helper library.
+ */
+struct drm_crtc_commit {
+ /**
+ * @crtc:
+ *
+ * DRM CRTC for this commit.
+ */
+ struct drm_crtc *crtc;
+
+ /**
+ * @ref:
+ *
+ * Reference count for this structure. Needed to allow blocking on
+ * completions without the risk of the completion disappearing
+ * meanwhile.
+ */
+ struct kref ref;
+
+ /**
+ * @flip_done:
+ *
+ * Will be signaled when the hardware has flipped to the new set of
+ * buffers. Signals at the same time as when the drm event for this
+ * commit is sent to userspace, or when an out-fence is singalled. Note
+ * that for most hardware, in most cases this happens after @hw_done is
+ * signalled.
+ */
+ struct completion flip_done;
+
+ /**
+ * @hw_done:
+ *
+ * Will be signalled when all hw register changes for this commit have
+ * been written out. Especially when disabling a pipe this can be much
+ * later than than @flip_done, since that can signal already when the
+ * screen goes black, whereas to fully shut down a pipe more register
+ * I/O is required.
+ *
+ * Note that this does not need to include separately reference-counted
+ * resources like backing storage buffer pinning, or runtime pm
+ * management.
+ */
+ struct completion hw_done;
+
+ /**
+ * @cleanup_done:
+ *
+ * Will be signalled after old buffers have been cleaned up by calling
+ * drm_atomic_helper_cleanup_planes(). Since this can only happen after
+ * a vblank wait completed it might be a bit later. This completion is
+ * useful to throttle updates and avoid hardware updates getting ahead
+ * of the buffer cleanup too much.
+ */
+ struct completion cleanup_done;
+
+ /**
+ * @commit_entry:
+ *
+ * Entry on the per-CRTC commit_list. Protected by crtc->commit_lock.
+ */
+ struct list_head commit_entry;
+
+ /**
+ * @event:
+ *
+ * &drm_pending_vblank_event pointer to clean up private events.
+ */
+ struct drm_pending_vblank_event *event;
+};
+
struct __drm_planes_state {
struct drm_plane *ptr;
struct drm_plane_state *state;
@@ -1741,6 +1869,7 @@ struct __drm_planes_state {
struct __drm_crtcs_state {
struct drm_crtc *ptr;
struct drm_crtc_state *state;
+ struct drm_crtc_commit *commit;
};
struct __drm_connnectors_state {
@@ -1771,6 +1900,14 @@ struct drm_atomic_state {
struct __drm_connnectors_state *connectors;
struct drm_modeset_acquire_ctx *acquire_ctx;
+
+ /**
+ * @commit_work:
+ *
+ * Work item which can be used by the driver or helpers to execute the
+ * commit without blocking.
+ */
+ struct work_struct commit_work;
};