xref: /dragonfly/sys/dev/drm/include/drm/drm_atomic.h (revision 78973132)
12c9916cdSFrançois Tigeot /*
22c9916cdSFrançois Tigeot  * Copyright (C) 2014 Red Hat
32c9916cdSFrançois Tigeot  * Copyright (C) 2014 Intel Corp.
42c9916cdSFrançois Tigeot  *
52c9916cdSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
62c9916cdSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
72c9916cdSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
82c9916cdSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
92c9916cdSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
102c9916cdSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
112c9916cdSFrançois Tigeot  *
122c9916cdSFrançois Tigeot  * The above copyright notice and this permission notice shall be included in
132c9916cdSFrançois Tigeot  * all copies or substantial portions of the Software.
142c9916cdSFrançois Tigeot  *
152c9916cdSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
162c9916cdSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
172c9916cdSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
182c9916cdSFrançois Tigeot  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
192c9916cdSFrançois Tigeot  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
202c9916cdSFrançois Tigeot  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
212c9916cdSFrançois Tigeot  * OTHER DEALINGS IN THE SOFTWARE.
222c9916cdSFrançois Tigeot  *
232c9916cdSFrançois Tigeot  * Authors:
242c9916cdSFrançois Tigeot  * Rob Clark <robdclark@gmail.com>
252c9916cdSFrançois Tigeot  * Daniel Vetter <daniel.vetter@ffwll.ch>
262c9916cdSFrançois Tigeot  */
272c9916cdSFrançois Tigeot 
282c9916cdSFrançois Tigeot #ifndef DRM_ATOMIC_H_
292c9916cdSFrançois Tigeot #define DRM_ATOMIC_H_
302c9916cdSFrançois Tigeot 
312c9916cdSFrançois Tigeot #include <drm/drm_crtc.h>
322c9916cdSFrançois Tigeot 
331dedbd3bSFrançois Tigeot /**
341dedbd3bSFrançois Tigeot  * struct drm_crtc_commit - track modeset commits on a CRTC
351dedbd3bSFrançois Tigeot  *
361dedbd3bSFrançois Tigeot  * This structure is used to track pending modeset changes and atomic commit on
371dedbd3bSFrançois Tigeot  * a per-CRTC basis. Since updating the list should never block this structure
381dedbd3bSFrançois Tigeot  * is reference counted to allow waiters to safely wait on an event to complete,
391dedbd3bSFrançois Tigeot  * without holding any locks.
401dedbd3bSFrançois Tigeot  *
411dedbd3bSFrançois Tigeot  * It has 3 different events in total to allow a fine-grained synchronization
421dedbd3bSFrançois Tigeot  * between outstanding updates::
431dedbd3bSFrançois Tigeot  *
441dedbd3bSFrançois Tigeot  *	atomic commit thread			hardware
451dedbd3bSFrançois Tigeot  *
461dedbd3bSFrançois Tigeot  * 	write new state into hardware	---->	...
471dedbd3bSFrançois Tigeot  * 	signal hw_done
481dedbd3bSFrançois Tigeot  * 						switch to new state on next
491dedbd3bSFrançois Tigeot  * 	...					v/hblank
501dedbd3bSFrançois Tigeot  *
511dedbd3bSFrançois Tigeot  *	wait for buffers to show up		...
521dedbd3bSFrançois Tigeot  *
531dedbd3bSFrançois Tigeot  *	...					send completion irq
541dedbd3bSFrançois Tigeot  *						irq handler signals flip_done
551dedbd3bSFrançois Tigeot  *	cleanup old buffers
561dedbd3bSFrançois Tigeot  *
571dedbd3bSFrançois Tigeot  * 	signal cleanup_done
581dedbd3bSFrançois Tigeot  *
591dedbd3bSFrançois Tigeot  * 	wait for flip_done		<----
601dedbd3bSFrançois Tigeot  * 	clean up atomic state
611dedbd3bSFrançois Tigeot  *
621dedbd3bSFrançois Tigeot  * The important bit to know is that cleanup_done is the terminal event, but the
631dedbd3bSFrançois Tigeot  * ordering between flip_done and hw_done is entirely up to the specific driver
641dedbd3bSFrançois Tigeot  * and modeset state change.
651dedbd3bSFrançois Tigeot  *
661dedbd3bSFrançois Tigeot  * For an implementation of how to use this look at
671dedbd3bSFrançois Tigeot  * drm_atomic_helper_setup_commit() from the atomic helper library.
681dedbd3bSFrançois Tigeot  */
691dedbd3bSFrançois Tigeot struct drm_crtc_commit {
701dedbd3bSFrançois Tigeot 	/**
711dedbd3bSFrançois Tigeot 	 * @crtc:
721dedbd3bSFrançois Tigeot 	 *
731dedbd3bSFrançois Tigeot 	 * DRM CRTC for this commit.
741dedbd3bSFrançois Tigeot 	 */
751dedbd3bSFrançois Tigeot 	struct drm_crtc *crtc;
761dedbd3bSFrançois Tigeot 
771dedbd3bSFrançois Tigeot 	/**
781dedbd3bSFrançois Tigeot 	 * @ref:
791dedbd3bSFrançois Tigeot 	 *
801dedbd3bSFrançois Tigeot 	 * Reference count for this structure. Needed to allow blocking on
811dedbd3bSFrançois Tigeot 	 * completions without the risk of the completion disappearing
821dedbd3bSFrançois Tigeot 	 * meanwhile.
831dedbd3bSFrançois Tigeot 	 */
841dedbd3bSFrançois Tigeot 	struct kref ref;
851dedbd3bSFrançois Tigeot 
861dedbd3bSFrançois Tigeot 	/**
871dedbd3bSFrançois Tigeot 	 * @flip_done:
881dedbd3bSFrançois Tigeot 	 *
891dedbd3bSFrançois Tigeot 	 * Will be signaled when the hardware has flipped to the new set of
901dedbd3bSFrançois Tigeot 	 * buffers. Signals at the same time as when the drm event for this
911dedbd3bSFrançois Tigeot 	 * commit is sent to userspace, or when an out-fence is singalled. Note
921dedbd3bSFrançois Tigeot 	 * that for most hardware, in most cases this happens after @hw_done is
931dedbd3bSFrançois Tigeot 	 * signalled.
941dedbd3bSFrançois Tigeot 	 */
951dedbd3bSFrançois Tigeot 	struct completion flip_done;
961dedbd3bSFrançois Tigeot 
971dedbd3bSFrançois Tigeot 	/**
981dedbd3bSFrançois Tigeot 	 * @hw_done:
991dedbd3bSFrançois Tigeot 	 *
1001dedbd3bSFrançois Tigeot 	 * Will be signalled when all hw register changes for this commit have
1011dedbd3bSFrançois Tigeot 	 * been written out. Especially when disabling a pipe this can be much
1021dedbd3bSFrançois Tigeot 	 * later than than @flip_done, since that can signal already when the
1031dedbd3bSFrançois Tigeot 	 * screen goes black, whereas to fully shut down a pipe more register
1041dedbd3bSFrançois Tigeot 	 * I/O is required.
1051dedbd3bSFrançois Tigeot 	 *
1061dedbd3bSFrançois Tigeot 	 * Note that this does not need to include separately reference-counted
1071dedbd3bSFrançois Tigeot 	 * resources like backing storage buffer pinning, or runtime pm
1081dedbd3bSFrançois Tigeot 	 * management.
1091dedbd3bSFrançois Tigeot 	 */
1101dedbd3bSFrançois Tigeot 	struct completion hw_done;
1111dedbd3bSFrançois Tigeot 
1121dedbd3bSFrançois Tigeot 	/**
1131dedbd3bSFrançois Tigeot 	 * @cleanup_done:
1141dedbd3bSFrançois Tigeot 	 *
1151dedbd3bSFrançois Tigeot 	 * Will be signalled after old buffers have been cleaned up by calling
1161dedbd3bSFrançois Tigeot 	 * drm_atomic_helper_cleanup_planes(). Since this can only happen after
1171dedbd3bSFrançois Tigeot 	 * a vblank wait completed it might be a bit later. This completion is
1181dedbd3bSFrançois Tigeot 	 * useful to throttle updates and avoid hardware updates getting ahead
1191dedbd3bSFrançois Tigeot 	 * of the buffer cleanup too much.
1201dedbd3bSFrançois Tigeot 	 */
1211dedbd3bSFrançois Tigeot 	struct completion cleanup_done;
1221dedbd3bSFrançois Tigeot 
1231dedbd3bSFrançois Tigeot 	/**
1241dedbd3bSFrançois Tigeot 	 * @commit_entry:
1251dedbd3bSFrançois Tigeot 	 *
126a85cb24fSFrançois Tigeot 	 * Entry on the per-CRTC &drm_crtc.commit_list. Protected by
127a85cb24fSFrançois Tigeot 	 * $drm_crtc.commit_lock.
1281dedbd3bSFrançois Tigeot 	 */
1291dedbd3bSFrançois Tigeot 	struct list_head commit_entry;
1301dedbd3bSFrançois Tigeot 
1311dedbd3bSFrançois Tigeot 	/**
1321dedbd3bSFrançois Tigeot 	 * @event:
1331dedbd3bSFrançois Tigeot 	 *
1341dedbd3bSFrançois Tigeot 	 * &drm_pending_vblank_event pointer to clean up private events.
1351dedbd3bSFrançois Tigeot 	 */
1361dedbd3bSFrançois Tigeot 	struct drm_pending_vblank_event *event;
1373f2dd94aSFrançois Tigeot 
1383f2dd94aSFrançois Tigeot 	/**
1393f2dd94aSFrançois Tigeot 	 * @abort_completion:
1403f2dd94aSFrançois Tigeot 	 *
1413f2dd94aSFrançois Tigeot 	 * A flag that's set after drm_atomic_helper_setup_commit takes a second
1423f2dd94aSFrançois Tigeot 	 * reference for the completion of $drm_crtc_state.event. It's used by
1433f2dd94aSFrançois Tigeot 	 * the free code to remove the second reference if commit fails.
1443f2dd94aSFrançois Tigeot 	 */
1453f2dd94aSFrançois Tigeot 	bool abort_completion;
1461dedbd3bSFrançois Tigeot };
1471dedbd3bSFrançois Tigeot 
1481dedbd3bSFrançois Tigeot struct __drm_planes_state {
1491dedbd3bSFrançois Tigeot 	struct drm_plane *ptr;
150a85cb24fSFrançois Tigeot 	struct drm_plane_state *state, *old_state, *new_state;
1511dedbd3bSFrançois Tigeot };
1521dedbd3bSFrançois Tigeot 
1531dedbd3bSFrançois Tigeot struct __drm_crtcs_state {
1541dedbd3bSFrançois Tigeot 	struct drm_crtc *ptr;
155a85cb24fSFrançois Tigeot 	struct drm_crtc_state *state, *old_state, *new_state;
1564be47400SFrançois Tigeot 	s32 __user *out_fence_ptr;
157a85cb24fSFrançois Tigeot 	unsigned last_vblank_count;
1581dedbd3bSFrançois Tigeot };
1591dedbd3bSFrançois Tigeot 
1601dedbd3bSFrançois Tigeot struct __drm_connnectors_state {
1611dedbd3bSFrançois Tigeot 	struct drm_connector *ptr;
162a85cb24fSFrançois Tigeot 	struct drm_connector_state *state, *old_state, *new_state;
1631dedbd3bSFrançois Tigeot };
1641dedbd3bSFrançois Tigeot 
1653f2dd94aSFrançois Tigeot struct drm_private_obj;
1663f2dd94aSFrançois Tigeot struct drm_private_state;
1673f2dd94aSFrançois Tigeot 
1683f2dd94aSFrançois Tigeot /**
1693f2dd94aSFrançois Tigeot  * struct drm_private_state_funcs - atomic state functions for private objects
1703f2dd94aSFrançois Tigeot  *
1713f2dd94aSFrançois Tigeot  * These hooks are used by atomic helpers to create, swap and destroy states of
1723f2dd94aSFrançois Tigeot  * private objects. The structure itself is used as a vtable to identify the
1733f2dd94aSFrançois Tigeot  * associated private object type. Each private object type that needs to be
1743f2dd94aSFrançois Tigeot  * added to the atomic states is expected to have an implementation of these
1753f2dd94aSFrançois Tigeot  * hooks and pass a pointer to it's drm_private_state_funcs struct to
1763f2dd94aSFrançois Tigeot  * drm_atomic_get_private_obj_state().
1773f2dd94aSFrançois Tigeot  */
1783f2dd94aSFrançois Tigeot struct drm_private_state_funcs {
1793f2dd94aSFrançois Tigeot 	/**
1803f2dd94aSFrançois Tigeot 	 * @atomic_duplicate_state:
1813f2dd94aSFrançois Tigeot 	 *
1823f2dd94aSFrançois Tigeot 	 * Duplicate the current state of the private object and return it. It
1833f2dd94aSFrançois Tigeot 	 * is an error to call this before obj->state has been initialized.
1843f2dd94aSFrançois Tigeot 	 *
1853f2dd94aSFrançois Tigeot 	 * RETURNS:
1863f2dd94aSFrançois Tigeot 	 *
1873f2dd94aSFrançois Tigeot 	 * Duplicated atomic state or NULL when obj->state is not
1883f2dd94aSFrançois Tigeot 	 * initialized or allocation failed.
1893f2dd94aSFrançois Tigeot 	 */
1903f2dd94aSFrançois Tigeot 	struct drm_private_state *(*atomic_duplicate_state)(struct drm_private_obj *obj);
1913f2dd94aSFrançois Tigeot 
1923f2dd94aSFrançois Tigeot 	/**
1933f2dd94aSFrançois Tigeot 	 * @atomic_destroy_state:
1943f2dd94aSFrançois Tigeot 	 *
1953f2dd94aSFrançois Tigeot 	 * Frees the private object state created with @atomic_duplicate_state.
1963f2dd94aSFrançois Tigeot 	 */
1973f2dd94aSFrançois Tigeot 	void (*atomic_destroy_state)(struct drm_private_obj *obj,
1983f2dd94aSFrançois Tigeot 				     struct drm_private_state *state);
1993f2dd94aSFrançois Tigeot };
2003f2dd94aSFrançois Tigeot 
2013f2dd94aSFrançois Tigeot struct drm_private_obj {
2023f2dd94aSFrançois Tigeot 	struct drm_private_state *state;
2033f2dd94aSFrançois Tigeot 
2043f2dd94aSFrançois Tigeot 	const struct drm_private_state_funcs *funcs;
2053f2dd94aSFrançois Tigeot };
2063f2dd94aSFrançois Tigeot 
2073f2dd94aSFrançois Tigeot struct drm_private_state {
2083f2dd94aSFrançois Tigeot 	struct drm_atomic_state *state;
2093f2dd94aSFrançois Tigeot };
2103f2dd94aSFrançois Tigeot 
2113f2dd94aSFrançois Tigeot struct __drm_private_objs_state {
2123f2dd94aSFrançois Tigeot 	struct drm_private_obj *ptr;
2133f2dd94aSFrançois Tigeot 	struct drm_private_state *state, *old_state, *new_state;
2143f2dd94aSFrançois Tigeot };
2153f2dd94aSFrançois Tigeot 
2161dedbd3bSFrançois Tigeot /**
2171dedbd3bSFrançois Tigeot  * struct drm_atomic_state - the global state object for atomic updates
2184be47400SFrançois Tigeot  * @ref: count of all references to this state (will not be freed until zero)
2191dedbd3bSFrançois Tigeot  * @dev: parent DRM device
2201dedbd3bSFrançois Tigeot  * @allow_modeset: allow full modeset
2211dedbd3bSFrançois Tigeot  * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics
2223f2dd94aSFrançois Tigeot  * @async_update: hint for asynchronous plane update
2231dedbd3bSFrançois Tigeot  * @planes: pointer to array of structures with per-plane data
2241dedbd3bSFrançois Tigeot  * @crtcs: pointer to array of CRTC pointers
2251dedbd3bSFrançois Tigeot  * @num_connector: size of the @connectors and @connector_states arrays
2261dedbd3bSFrançois Tigeot  * @connectors: pointer to array of structures with per-connector data
2273f2dd94aSFrançois Tigeot  * @num_private_objs: size of the @private_objs array
2283f2dd94aSFrançois Tigeot  * @private_objs: pointer to array of private object pointers
2291dedbd3bSFrançois Tigeot  * @acquire_ctx: acquire context for this atomic modeset state update
2301dedbd3bSFrançois Tigeot  */
2311dedbd3bSFrançois Tigeot struct drm_atomic_state {
2324be47400SFrançois Tigeot 	struct kref ref;
2334be47400SFrançois Tigeot 
2341dedbd3bSFrançois Tigeot 	struct drm_device *dev;
2351dedbd3bSFrançois Tigeot 	bool allow_modeset : 1;
2361dedbd3bSFrançois Tigeot 	bool legacy_cursor_update : 1;
2373f2dd94aSFrançois Tigeot 	bool async_update : 1;
2381dedbd3bSFrançois Tigeot 	struct __drm_planes_state *planes;
2391dedbd3bSFrançois Tigeot 	struct __drm_crtcs_state *crtcs;
2401dedbd3bSFrançois Tigeot 	int num_connector;
2411dedbd3bSFrançois Tigeot 	struct __drm_connnectors_state *connectors;
2423f2dd94aSFrançois Tigeot 	int num_private_objs;
2433f2dd94aSFrançois Tigeot 	struct __drm_private_objs_state *private_objs;
2441dedbd3bSFrançois Tigeot 
2451dedbd3bSFrançois Tigeot 	struct drm_modeset_acquire_ctx *acquire_ctx;
2461dedbd3bSFrançois Tigeot 
2471dedbd3bSFrançois Tigeot 	/**
2483f2dd94aSFrançois Tigeot 	 * @fake_commit:
2493f2dd94aSFrançois Tigeot 	 *
2503f2dd94aSFrançois Tigeot 	 * Used for signaling unbound planes/connectors.
2513f2dd94aSFrançois Tigeot 	 * When a connector or plane is not bound to any CRTC, it's still important
2523f2dd94aSFrançois Tigeot 	 * to preserve linearity to prevent the atomic states from being freed to early.
2533f2dd94aSFrançois Tigeot 	 *
2543f2dd94aSFrançois Tigeot 	 * This commit (if set) is not bound to any crtc, but will be completed when
2553f2dd94aSFrançois Tigeot 	 * drm_atomic_helper_commit_hw_done() is called.
2563f2dd94aSFrançois Tigeot 	 */
2573f2dd94aSFrançois Tigeot 	struct drm_crtc_commit *fake_commit;
2583f2dd94aSFrançois Tigeot 
2593f2dd94aSFrançois Tigeot 	/**
2601dedbd3bSFrançois Tigeot 	 * @commit_work:
2611dedbd3bSFrançois Tigeot 	 *
2621dedbd3bSFrançois Tigeot 	 * Work item which can be used by the driver or helpers to execute the
2631dedbd3bSFrançois Tigeot 	 * commit without blocking.
2641dedbd3bSFrançois Tigeot 	 */
2651dedbd3bSFrançois Tigeot 	struct work_struct commit_work;
2661dedbd3bSFrançois Tigeot };
2671dedbd3bSFrançois Tigeot 
268a85cb24fSFrançois Tigeot void __drm_crtc_commit_free(struct kref *kref);
269a85cb24fSFrançois Tigeot 
270a85cb24fSFrançois Tigeot /**
271a85cb24fSFrançois Tigeot  * drm_crtc_commit_get - acquire a reference to the CRTC commit
272a85cb24fSFrançois Tigeot  * @commit: CRTC commit
273a85cb24fSFrançois Tigeot  *
274a85cb24fSFrançois Tigeot  * Increases the reference of @commit.
2753f2dd94aSFrançois Tigeot  *
2763f2dd94aSFrançois Tigeot  * Returns:
2773f2dd94aSFrançois Tigeot  * The pointer to @commit, with reference increased.
278a85cb24fSFrançois Tigeot  */
drm_crtc_commit_get(struct drm_crtc_commit * commit)2793f2dd94aSFrançois Tigeot static inline struct drm_crtc_commit *drm_crtc_commit_get(struct drm_crtc_commit *commit)
2801dedbd3bSFrançois Tigeot {
2811dedbd3bSFrançois Tigeot 	kref_get(&commit->ref);
2823f2dd94aSFrançois Tigeot 	return commit;
2831dedbd3bSFrançois Tigeot }
2841dedbd3bSFrançois Tigeot 
285a85cb24fSFrançois Tigeot /**
286a85cb24fSFrançois Tigeot  * drm_crtc_commit_put - release a reference to the CRTC commmit
287a85cb24fSFrançois Tigeot  * @commit: CRTC commit
288a85cb24fSFrançois Tigeot  *
289a85cb24fSFrançois Tigeot  * This releases a reference to @commit which is freed after removing the
290a85cb24fSFrançois Tigeot  * final reference. No locking required and callable from any context.
291a85cb24fSFrançois Tigeot  */
drm_crtc_commit_put(struct drm_crtc_commit * commit)292a85cb24fSFrançois Tigeot static inline void drm_crtc_commit_put(struct drm_crtc_commit *commit)
293a85cb24fSFrançois Tigeot {
294a85cb24fSFrançois Tigeot 	kref_put(&commit->ref, __drm_crtc_commit_free);
295a85cb24fSFrançois Tigeot }
296a85cb24fSFrançois Tigeot 
2972c9916cdSFrançois Tigeot struct drm_atomic_state * __must_check
2982c9916cdSFrançois Tigeot drm_atomic_state_alloc(struct drm_device *dev);
2992c9916cdSFrançois Tigeot void drm_atomic_state_clear(struct drm_atomic_state *state);
3004be47400SFrançois Tigeot 
3014be47400SFrançois Tigeot /**
3024be47400SFrançois Tigeot  * drm_atomic_state_get - acquire a reference to the atomic state
3034be47400SFrançois Tigeot  * @state: The atomic state
3044be47400SFrançois Tigeot  *
3054be47400SFrançois Tigeot  * Returns a new reference to the @state
3064be47400SFrançois Tigeot  */
3074be47400SFrançois Tigeot static inline struct drm_atomic_state *
drm_atomic_state_get(struct drm_atomic_state * state)3084be47400SFrançois Tigeot drm_atomic_state_get(struct drm_atomic_state *state)
3094be47400SFrançois Tigeot {
3104be47400SFrançois Tigeot 	kref_get(&state->ref);
3114be47400SFrançois Tigeot 	return state;
3124be47400SFrançois Tigeot }
3134be47400SFrançois Tigeot 
3144be47400SFrançois Tigeot void __drm_atomic_state_free(struct kref *ref);
3154be47400SFrançois Tigeot 
3164be47400SFrançois Tigeot /**
3174be47400SFrançois Tigeot  * drm_atomic_state_put - release a reference to the atomic state
3184be47400SFrançois Tigeot  * @state: The atomic state
3194be47400SFrançois Tigeot  *
3204be47400SFrançois Tigeot  * This releases a reference to @state which is freed after removing the
3214be47400SFrançois Tigeot  * final reference. No locking required and callable from any context.
3224be47400SFrançois Tigeot  */
drm_atomic_state_put(struct drm_atomic_state * state)3234be47400SFrançois Tigeot static inline void drm_atomic_state_put(struct drm_atomic_state *state)
3244be47400SFrançois Tigeot {
3254be47400SFrançois Tigeot 	kref_put(&state->ref, __drm_atomic_state_free);
3264be47400SFrançois Tigeot }
3272c9916cdSFrançois Tigeot 
32819c468b4SFrançois Tigeot int  __must_check
32919c468b4SFrançois Tigeot drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state);
33019c468b4SFrançois Tigeot void drm_atomic_state_default_clear(struct drm_atomic_state *state);
33119c468b4SFrançois Tigeot void drm_atomic_state_default_release(struct drm_atomic_state *state);
33219c468b4SFrançois Tigeot 
3332c9916cdSFrançois Tigeot struct drm_crtc_state * __must_check
3342c9916cdSFrançois Tigeot drm_atomic_get_crtc_state(struct drm_atomic_state *state,
3352c9916cdSFrançois Tigeot 			  struct drm_crtc *crtc);
3362c9916cdSFrançois Tigeot int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
3372c9916cdSFrançois Tigeot 		struct drm_crtc_state *state, struct drm_property *property,
3382c9916cdSFrançois Tigeot 		uint64_t val);
3392c9916cdSFrançois Tigeot struct drm_plane_state * __must_check
3402c9916cdSFrançois Tigeot drm_atomic_get_plane_state(struct drm_atomic_state *state,
3412c9916cdSFrançois Tigeot 			   struct drm_plane *plane);
3422c9916cdSFrançois Tigeot struct drm_connector_state * __must_check
3432c9916cdSFrançois Tigeot drm_atomic_get_connector_state(struct drm_atomic_state *state,
3442c9916cdSFrançois Tigeot 			       struct drm_connector *connector);
3453f2dd94aSFrançois Tigeot 
3463f2dd94aSFrançois Tigeot void drm_atomic_private_obj_init(struct drm_private_obj *obj,
3473f2dd94aSFrançois Tigeot 				 struct drm_private_state *state,
3483f2dd94aSFrançois Tigeot 				 const struct drm_private_state_funcs *funcs);
3493f2dd94aSFrançois Tigeot void drm_atomic_private_obj_fini(struct drm_private_obj *obj);
3503f2dd94aSFrançois Tigeot 
3513f2dd94aSFrançois Tigeot struct drm_private_state * __must_check
3523f2dd94aSFrançois Tigeot drm_atomic_get_private_obj_state(struct drm_atomic_state *state,
3533f2dd94aSFrançois Tigeot 				 struct drm_private_obj *obj);
3542c9916cdSFrançois Tigeot 
35519c468b4SFrançois Tigeot /**
35619c468b4SFrançois Tigeot  * drm_atomic_get_existing_crtc_state - get crtc state, if it exists
35719c468b4SFrançois Tigeot  * @state: global atomic state object
35819c468b4SFrançois Tigeot  * @crtc: crtc to grab
35919c468b4SFrançois Tigeot  *
36019c468b4SFrançois Tigeot  * This function returns the crtc state for the given crtc, or NULL
36119c468b4SFrançois Tigeot  * if the crtc is not part of the global atomic state.
362a85cb24fSFrançois Tigeot  *
363a85cb24fSFrançois Tigeot  * This function is deprecated, @drm_atomic_get_old_crtc_state or
364a85cb24fSFrançois Tigeot  * @drm_atomic_get_new_crtc_state should be used instead.
36519c468b4SFrançois Tigeot  */
36619c468b4SFrançois Tigeot static inline struct drm_crtc_state *
drm_atomic_get_existing_crtc_state(struct drm_atomic_state * state,struct drm_crtc * crtc)36719c468b4SFrançois Tigeot drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state,
36819c468b4SFrançois Tigeot 				   struct drm_crtc *crtc)
36919c468b4SFrançois Tigeot {
3701dedbd3bSFrançois Tigeot 	return state->crtcs[drm_crtc_index(crtc)].state;
37119c468b4SFrançois Tigeot }
37219c468b4SFrançois Tigeot 
37319c468b4SFrançois Tigeot /**
374a85cb24fSFrançois Tigeot  * drm_atomic_get_old_crtc_state - get old crtc state, if it exists
375a85cb24fSFrançois Tigeot  * @state: global atomic state object
376a85cb24fSFrançois Tigeot  * @crtc: crtc to grab
377a85cb24fSFrançois Tigeot  *
378a85cb24fSFrançois Tigeot  * This function returns the old crtc state for the given crtc, or
379a85cb24fSFrançois Tigeot  * NULL if the crtc is not part of the global atomic state.
380a85cb24fSFrançois Tigeot  */
381a85cb24fSFrançois Tigeot static inline struct drm_crtc_state *
drm_atomic_get_old_crtc_state(struct drm_atomic_state * state,struct drm_crtc * crtc)382a85cb24fSFrançois Tigeot drm_atomic_get_old_crtc_state(struct drm_atomic_state *state,
383a85cb24fSFrançois Tigeot 			      struct drm_crtc *crtc)
384a85cb24fSFrançois Tigeot {
385a85cb24fSFrançois Tigeot 	return state->crtcs[drm_crtc_index(crtc)].old_state;
386a85cb24fSFrançois Tigeot }
387a85cb24fSFrançois Tigeot /**
388a85cb24fSFrançois Tigeot  * drm_atomic_get_new_crtc_state - get new crtc state, if it exists
389a85cb24fSFrançois Tigeot  * @state: global atomic state object
390a85cb24fSFrançois Tigeot  * @crtc: crtc to grab
391a85cb24fSFrançois Tigeot  *
392a85cb24fSFrançois Tigeot  * This function returns the new crtc state for the given crtc, or
393a85cb24fSFrançois Tigeot  * NULL if the crtc is not part of the global atomic state.
394a85cb24fSFrançois Tigeot  */
395a85cb24fSFrançois Tigeot static inline struct drm_crtc_state *
drm_atomic_get_new_crtc_state(struct drm_atomic_state * state,struct drm_crtc * crtc)396a85cb24fSFrançois Tigeot drm_atomic_get_new_crtc_state(struct drm_atomic_state *state,
397a85cb24fSFrançois Tigeot 			      struct drm_crtc *crtc)
398a85cb24fSFrançois Tigeot {
399a85cb24fSFrançois Tigeot 	return state->crtcs[drm_crtc_index(crtc)].new_state;
400a85cb24fSFrançois Tigeot }
401a85cb24fSFrançois Tigeot 
402a85cb24fSFrançois Tigeot /**
40319c468b4SFrançois Tigeot  * drm_atomic_get_existing_plane_state - get plane state, if it exists
40419c468b4SFrançois Tigeot  * @state: global atomic state object
40519c468b4SFrançois Tigeot  * @plane: plane to grab
40619c468b4SFrançois Tigeot  *
40719c468b4SFrançois Tigeot  * This function returns the plane state for the given plane, or NULL
40819c468b4SFrançois Tigeot  * if the plane is not part of the global atomic state.
409a85cb24fSFrançois Tigeot  *
410a85cb24fSFrançois Tigeot  * This function is deprecated, @drm_atomic_get_old_plane_state or
411a85cb24fSFrançois Tigeot  * @drm_atomic_get_new_plane_state should be used instead.
41219c468b4SFrançois Tigeot  */
41319c468b4SFrançois Tigeot static inline struct drm_plane_state *
drm_atomic_get_existing_plane_state(struct drm_atomic_state * state,struct drm_plane * plane)41419c468b4SFrançois Tigeot drm_atomic_get_existing_plane_state(struct drm_atomic_state *state,
41519c468b4SFrançois Tigeot 				    struct drm_plane *plane)
41619c468b4SFrançois Tigeot {
4171dedbd3bSFrançois Tigeot 	return state->planes[drm_plane_index(plane)].state;
41819c468b4SFrançois Tigeot }
41919c468b4SFrançois Tigeot 
42019c468b4SFrançois Tigeot /**
421a85cb24fSFrançois Tigeot  * drm_atomic_get_old_plane_state - get plane state, if it exists
422a85cb24fSFrançois Tigeot  * @state: global atomic state object
423a85cb24fSFrançois Tigeot  * @plane: plane to grab
424a85cb24fSFrançois Tigeot  *
425a85cb24fSFrançois Tigeot  * This function returns the old plane state for the given plane, or
426a85cb24fSFrançois Tigeot  * NULL if the plane is not part of the global atomic state.
427a85cb24fSFrançois Tigeot  */
428a85cb24fSFrançois Tigeot static inline struct drm_plane_state *
drm_atomic_get_old_plane_state(struct drm_atomic_state * state,struct drm_plane * plane)429a85cb24fSFrançois Tigeot drm_atomic_get_old_plane_state(struct drm_atomic_state *state,
430a85cb24fSFrançois Tigeot 			       struct drm_plane *plane)
431a85cb24fSFrançois Tigeot {
432a85cb24fSFrançois Tigeot 	return state->planes[drm_plane_index(plane)].old_state;
433a85cb24fSFrançois Tigeot }
434a85cb24fSFrançois Tigeot 
435a85cb24fSFrançois Tigeot /**
436a85cb24fSFrançois Tigeot  * drm_atomic_get_new_plane_state - get plane state, if it exists
437a85cb24fSFrançois Tigeot  * @state: global atomic state object
438a85cb24fSFrançois Tigeot  * @plane: plane to grab
439a85cb24fSFrançois Tigeot  *
440a85cb24fSFrançois Tigeot  * This function returns the new plane state for the given plane, or
441a85cb24fSFrançois Tigeot  * NULL if the plane is not part of the global atomic state.
442a85cb24fSFrançois Tigeot  */
443a85cb24fSFrançois Tigeot static inline struct drm_plane_state *
drm_atomic_get_new_plane_state(struct drm_atomic_state * state,struct drm_plane * plane)444a85cb24fSFrançois Tigeot drm_atomic_get_new_plane_state(struct drm_atomic_state *state,
445a85cb24fSFrançois Tigeot 			       struct drm_plane *plane)
446a85cb24fSFrançois Tigeot {
447a85cb24fSFrançois Tigeot 	return state->planes[drm_plane_index(plane)].new_state;
448a85cb24fSFrançois Tigeot }
449a85cb24fSFrançois Tigeot 
450a85cb24fSFrançois Tigeot /**
45119c468b4SFrançois Tigeot  * drm_atomic_get_existing_connector_state - get connector state, if it exists
45219c468b4SFrançois Tigeot  * @state: global atomic state object
45319c468b4SFrançois Tigeot  * @connector: connector to grab
45419c468b4SFrançois Tigeot  *
45519c468b4SFrançois Tigeot  * This function returns the connector state for the given connector,
45619c468b4SFrançois Tigeot  * or NULL if the connector is not part of the global atomic state.
457a85cb24fSFrançois Tigeot  *
458a85cb24fSFrançois Tigeot  * This function is deprecated, @drm_atomic_get_old_connector_state or
459a85cb24fSFrançois Tigeot  * @drm_atomic_get_new_connector_state should be used instead.
46019c468b4SFrançois Tigeot  */
46119c468b4SFrançois Tigeot static inline struct drm_connector_state *
drm_atomic_get_existing_connector_state(struct drm_atomic_state * state,struct drm_connector * connector)46219c468b4SFrançois Tigeot drm_atomic_get_existing_connector_state(struct drm_atomic_state *state,
46319c468b4SFrançois Tigeot 					struct drm_connector *connector)
46419c468b4SFrançois Tigeot {
46519c468b4SFrançois Tigeot 	int index = drm_connector_index(connector);
46619c468b4SFrançois Tigeot 
46719c468b4SFrançois Tigeot 	if (index >= state->num_connector)
46819c468b4SFrançois Tigeot 		return NULL;
46919c468b4SFrançois Tigeot 
4701dedbd3bSFrançois Tigeot 	return state->connectors[index].state;
4711dedbd3bSFrançois Tigeot }
4721dedbd3bSFrançois Tigeot 
4731dedbd3bSFrançois Tigeot /**
474a85cb24fSFrançois Tigeot  * drm_atomic_get_old_connector_state - get connector state, if it exists
475a85cb24fSFrançois Tigeot  * @state: global atomic state object
476a85cb24fSFrançois Tigeot  * @connector: connector to grab
477a85cb24fSFrançois Tigeot  *
478a85cb24fSFrançois Tigeot  * This function returns the old connector state for the given connector,
479a85cb24fSFrançois Tigeot  * or NULL if the connector is not part of the global atomic state.
480a85cb24fSFrançois Tigeot  */
481a85cb24fSFrançois Tigeot static inline struct drm_connector_state *
drm_atomic_get_old_connector_state(struct drm_atomic_state * state,struct drm_connector * connector)482a85cb24fSFrançois Tigeot drm_atomic_get_old_connector_state(struct drm_atomic_state *state,
483a85cb24fSFrançois Tigeot 				   struct drm_connector *connector)
484a85cb24fSFrançois Tigeot {
485a85cb24fSFrançois Tigeot 	int index = drm_connector_index(connector);
486a85cb24fSFrançois Tigeot 
487a85cb24fSFrançois Tigeot 	if (index >= state->num_connector)
488a85cb24fSFrançois Tigeot 		return NULL;
489a85cb24fSFrançois Tigeot 
490a85cb24fSFrançois Tigeot 	return state->connectors[index].old_state;
491a85cb24fSFrançois Tigeot }
492a85cb24fSFrançois Tigeot 
493a85cb24fSFrançois Tigeot /**
494a85cb24fSFrançois Tigeot  * drm_atomic_get_new_connector_state - get connector state, if it exists
495a85cb24fSFrançois Tigeot  * @state: global atomic state object
496a85cb24fSFrançois Tigeot  * @connector: connector to grab
497a85cb24fSFrançois Tigeot  *
498a85cb24fSFrançois Tigeot  * This function returns the new connector state for the given connector,
499a85cb24fSFrançois Tigeot  * or NULL if the connector is not part of the global atomic state.
500a85cb24fSFrançois Tigeot  */
501a85cb24fSFrançois Tigeot static inline struct drm_connector_state *
drm_atomic_get_new_connector_state(struct drm_atomic_state * state,struct drm_connector * connector)502a85cb24fSFrançois Tigeot drm_atomic_get_new_connector_state(struct drm_atomic_state *state,
503a85cb24fSFrançois Tigeot 				   struct drm_connector *connector)
504a85cb24fSFrançois Tigeot {
505a85cb24fSFrançois Tigeot 	int index = drm_connector_index(connector);
506a85cb24fSFrançois Tigeot 
507a85cb24fSFrançois Tigeot 	if (index >= state->num_connector)
508a85cb24fSFrançois Tigeot 		return NULL;
509a85cb24fSFrançois Tigeot 
510a85cb24fSFrançois Tigeot 	return state->connectors[index].new_state;
511a85cb24fSFrançois Tigeot }
512a85cb24fSFrançois Tigeot 
513a85cb24fSFrançois Tigeot /**
5141dedbd3bSFrançois Tigeot  * __drm_atomic_get_current_plane_state - get current plane state
5151dedbd3bSFrançois Tigeot  * @state: global atomic state object
5161dedbd3bSFrançois Tigeot  * @plane: plane to grab
5171dedbd3bSFrançois Tigeot  *
5181dedbd3bSFrançois Tigeot  * This function returns the plane state for the given plane, either from
5191dedbd3bSFrançois Tigeot  * @state, or if the plane isn't part of the atomic state update, from @plane.
5201dedbd3bSFrançois Tigeot  * This is useful in atomic check callbacks, when drivers need to peek at, but
5211dedbd3bSFrançois Tigeot  * not change, state of other planes, since it avoids threading an error code
5221dedbd3bSFrançois Tigeot  * back up the call chain.
5231dedbd3bSFrançois Tigeot  *
5241dedbd3bSFrançois Tigeot  * WARNING:
5251dedbd3bSFrançois Tigeot  *
5261dedbd3bSFrançois Tigeot  * Note that this function is in general unsafe since it doesn't check for the
5271dedbd3bSFrançois Tigeot  * required locking for access state structures. Drivers must ensure that it is
5281dedbd3bSFrançois Tigeot  * safe to access the returned state structure through other means. One common
5291dedbd3bSFrançois Tigeot  * example is when planes are fixed to a single CRTC, and the driver knows that
5301dedbd3bSFrançois Tigeot  * the CRTC lock is held already. In that case holding the CRTC lock gives a
5311dedbd3bSFrançois Tigeot  * read-lock on all planes connected to that CRTC. But if planes can be
5321dedbd3bSFrançois Tigeot  * reassigned things get more tricky. In that case it's better to use
5331dedbd3bSFrançois Tigeot  * drm_atomic_get_plane_state and wire up full error handling.
5341dedbd3bSFrançois Tigeot  *
5351dedbd3bSFrançois Tigeot  * Returns:
5361dedbd3bSFrançois Tigeot  *
5371dedbd3bSFrançois Tigeot  * Read-only pointer to the current plane state.
5381dedbd3bSFrançois Tigeot  */
5391dedbd3bSFrançois Tigeot static inline const struct drm_plane_state *
__drm_atomic_get_current_plane_state(struct drm_atomic_state * state,struct drm_plane * plane)5401dedbd3bSFrançois Tigeot __drm_atomic_get_current_plane_state(struct drm_atomic_state *state,
5411dedbd3bSFrançois Tigeot 				     struct drm_plane *plane)
5421dedbd3bSFrançois Tigeot {
5431dedbd3bSFrançois Tigeot 	if (state->planes[drm_plane_index(plane)].state)
5441dedbd3bSFrançois Tigeot 		return state->planes[drm_plane_index(plane)].state;
5451dedbd3bSFrançois Tigeot 
5461dedbd3bSFrançois Tigeot 	return plane->state;
54719c468b4SFrançois Tigeot }
54819c468b4SFrançois Tigeot 
54919c468b4SFrançois Tigeot int __must_check
55019c468b4SFrançois Tigeot drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
5513f2dd94aSFrançois Tigeot 			     const struct drm_display_mode *mode);
55219c468b4SFrançois Tigeot int __must_check
55319c468b4SFrançois Tigeot drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
55419c468b4SFrançois Tigeot 				  struct drm_property_blob *blob);
5552c9916cdSFrançois Tigeot int __must_check
5562c9916cdSFrançois Tigeot drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
5572c9916cdSFrançois Tigeot 			      struct drm_crtc *crtc);
5582c9916cdSFrançois Tigeot void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
5592c9916cdSFrançois Tigeot 				 struct drm_framebuffer *fb);
5604be47400SFrançois Tigeot void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
5614be47400SFrançois Tigeot 				    struct dma_fence *fence);
5622c9916cdSFrançois Tigeot int __must_check
5632c9916cdSFrançois Tigeot drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
5642c9916cdSFrançois Tigeot 				  struct drm_crtc *crtc);
5652c9916cdSFrançois Tigeot int __must_check
5662c9916cdSFrançois Tigeot drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
5672c9916cdSFrançois Tigeot 				   struct drm_crtc *crtc);
56819c468b4SFrançois Tigeot int __must_check
56919c468b4SFrançois Tigeot drm_atomic_add_affected_planes(struct drm_atomic_state *state,
57019c468b4SFrançois Tigeot 			       struct drm_crtc *crtc);
57119c468b4SFrançois Tigeot 
572352ff8bdSFrançois Tigeot void
573352ff8bdSFrançois Tigeot drm_atomic_clean_old_fb(struct drm_device *dev, unsigned plane_mask, int ret);
574352ff8bdSFrançois Tigeot 
5752c9916cdSFrançois Tigeot int __must_check drm_atomic_check_only(struct drm_atomic_state *state);
5762c9916cdSFrançois Tigeot int __must_check drm_atomic_commit(struct drm_atomic_state *state);
5778621f407SFrançois Tigeot int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state);
5782c9916cdSFrançois Tigeot 
5794be47400SFrançois Tigeot void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
5804be47400SFrançois Tigeot 
581a85cb24fSFrançois Tigeot /**
582a85cb24fSFrançois Tigeot  * for_each_oldnew_connector_in_state - iterate over all connectors in an atomic update
583a85cb24fSFrançois Tigeot  * @__state: &struct drm_atomic_state pointer
584a85cb24fSFrançois Tigeot  * @connector: &struct drm_connector iteration cursor
585a85cb24fSFrançois Tigeot  * @old_connector_state: &struct drm_connector_state iteration cursor for the
586a85cb24fSFrançois Tigeot  * 	old state
587a85cb24fSFrançois Tigeot  * @new_connector_state: &struct drm_connector_state iteration cursor for the
588a85cb24fSFrançois Tigeot  * 	new state
589a85cb24fSFrançois Tigeot  * @__i: int iteration cursor, for macro-internal use
590a85cb24fSFrançois Tigeot  *
591a85cb24fSFrançois Tigeot  * This iterates over all connectors in an atomic update, tracking both old and
592a85cb24fSFrançois Tigeot  * new state. This is useful in places where the state delta needs to be
593a85cb24fSFrançois Tigeot  * considered, for example in atomic check functions.
594a85cb24fSFrançois Tigeot  */
595a85cb24fSFrançois Tigeot #define for_each_oldnew_connector_in_state(__state, connector, old_connector_state, new_connector_state, __i) \
596a85cb24fSFrançois Tigeot 	for ((__i) = 0;								\
5973f2dd94aSFrançois Tigeot 	     (__i) < (__state)->num_connector;					\
5983f2dd94aSFrançois Tigeot 	     (__i)++)								\
5993f2dd94aSFrançois Tigeot 		for_each_if ((__state)->connectors[__i].ptr &&			\
600a85cb24fSFrançois Tigeot 			     ((connector) = (__state)->connectors[__i].ptr,	\
601a85cb24fSFrançois Tigeot 			     (old_connector_state) = (__state)->connectors[__i].old_state,	\
6023f2dd94aSFrançois Tigeot 			     (new_connector_state) = (__state)->connectors[__i].new_state, 1))
603a85cb24fSFrançois Tigeot 
604a85cb24fSFrançois Tigeot /**
605a85cb24fSFrançois Tigeot  * for_each_old_connector_in_state - iterate over all connectors in an atomic update
606a85cb24fSFrançois Tigeot  * @__state: &struct drm_atomic_state pointer
607a85cb24fSFrançois Tigeot  * @connector: &struct drm_connector iteration cursor
608a85cb24fSFrançois Tigeot  * @old_connector_state: &struct drm_connector_state iteration cursor for the
609a85cb24fSFrançois Tigeot  * 	old state
610a85cb24fSFrançois Tigeot  * @__i: int iteration cursor, for macro-internal use
611a85cb24fSFrançois Tigeot  *
612a85cb24fSFrançois Tigeot  * This iterates over all connectors in an atomic update, tracking only the old
613a85cb24fSFrançois Tigeot  * state. This is useful in disable functions, where we need the old state the
614a85cb24fSFrançois Tigeot  * hardware is still in.
615a85cb24fSFrançois Tigeot  */
616a85cb24fSFrançois Tigeot #define for_each_old_connector_in_state(__state, connector, old_connector_state, __i) \
617a85cb24fSFrançois Tigeot 	for ((__i) = 0;								\
6183f2dd94aSFrançois Tigeot 	     (__i) < (__state)->num_connector;					\
619a85cb24fSFrançois Tigeot 	     (__i)++)								\
6203f2dd94aSFrançois Tigeot 		for_each_if ((__state)->connectors[__i].ptr &&			\
6213f2dd94aSFrançois Tigeot 			     ((connector) = (__state)->connectors[__i].ptr,	\
6223f2dd94aSFrançois Tigeot 			     (old_connector_state) = (__state)->connectors[__i].old_state, 1))
623a85cb24fSFrançois Tigeot 
624a85cb24fSFrançois Tigeot /**
625a85cb24fSFrançois Tigeot  * for_each_new_connector_in_state - iterate over all connectors in an atomic update
626a85cb24fSFrançois Tigeot  * @__state: &struct drm_atomic_state pointer
627a85cb24fSFrançois Tigeot  * @connector: &struct drm_connector iteration cursor
628a85cb24fSFrançois Tigeot  * @new_connector_state: &struct drm_connector_state iteration cursor for the
629a85cb24fSFrançois Tigeot  * 	new state
630a85cb24fSFrançois Tigeot  * @__i: int iteration cursor, for macro-internal use
631a85cb24fSFrançois Tigeot  *
632a85cb24fSFrançois Tigeot  * This iterates over all connectors in an atomic update, tracking only the new
633a85cb24fSFrançois Tigeot  * state. This is useful in enable functions, where we need the new state the
634a85cb24fSFrançois Tigeot  * hardware should be in when the atomic commit operation has completed.
635a85cb24fSFrançois Tigeot  */
636a85cb24fSFrançois Tigeot #define for_each_new_connector_in_state(__state, connector, new_connector_state, __i) \
637a85cb24fSFrançois Tigeot 	for ((__i) = 0;								\
6383f2dd94aSFrançois Tigeot 	     (__i) < (__state)->num_connector;					\
6393f2dd94aSFrançois Tigeot 	     (__i)++)								\
6403f2dd94aSFrançois Tigeot 		for_each_if ((__state)->connectors[__i].ptr &&			\
641a85cb24fSFrançois Tigeot 			     ((connector) = (__state)->connectors[__i].ptr,	\
6423f2dd94aSFrançois Tigeot 			     (new_connector_state) = (__state)->connectors[__i].new_state, 1))
643477eb7f9SFrançois Tigeot 
644a85cb24fSFrançois Tigeot /**
645a85cb24fSFrançois Tigeot  * for_each_oldnew_crtc_in_state - iterate over all CRTCs in an atomic update
646a85cb24fSFrançois Tigeot  * @__state: &struct drm_atomic_state pointer
647a85cb24fSFrançois Tigeot  * @crtc: &struct drm_crtc iteration cursor
648a85cb24fSFrançois Tigeot  * @old_crtc_state: &struct drm_crtc_state iteration cursor for the old state
649a85cb24fSFrançois Tigeot  * @new_crtc_state: &struct drm_crtc_state iteration cursor for the new state
650a85cb24fSFrançois Tigeot  * @__i: int iteration cursor, for macro-internal use
651a85cb24fSFrançois Tigeot  *
652a85cb24fSFrançois Tigeot  * This iterates over all CRTCs in an atomic update, tracking both old and
653a85cb24fSFrançois Tigeot  * new state. This is useful in places where the state delta needs to be
654a85cb24fSFrançois Tigeot  * considered, for example in atomic check functions.
655a85cb24fSFrançois Tigeot  */
656a85cb24fSFrançois Tigeot #define for_each_oldnew_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \
657a85cb24fSFrançois Tigeot 	for ((__i) = 0;							\
6583f2dd94aSFrançois Tigeot 	     (__i) < (__state)->dev->mode_config.num_crtc;		\
6593f2dd94aSFrançois Tigeot 	     (__i)++)							\
6603f2dd94aSFrançois Tigeot 		for_each_if ((__state)->crtcs[__i].ptr &&		\
661a85cb24fSFrançois Tigeot 			     ((crtc) = (__state)->crtcs[__i].ptr,	\
662a85cb24fSFrançois Tigeot 			     (old_crtc_state) = (__state)->crtcs[__i].old_state, \
6633f2dd94aSFrançois Tigeot 			     (new_crtc_state) = (__state)->crtcs[__i].new_state, 1))
664a85cb24fSFrançois Tigeot 
665a85cb24fSFrançois Tigeot /**
666a85cb24fSFrançois Tigeot  * for_each_old_crtc_in_state - iterate over all CRTCs in an atomic update
667a85cb24fSFrançois Tigeot  * @__state: &struct drm_atomic_state pointer
668a85cb24fSFrançois Tigeot  * @crtc: &struct drm_crtc iteration cursor
669a85cb24fSFrançois Tigeot  * @old_crtc_state: &struct drm_crtc_state iteration cursor for the old state
670a85cb24fSFrançois Tigeot  * @__i: int iteration cursor, for macro-internal use
671a85cb24fSFrançois Tigeot  *
672a85cb24fSFrançois Tigeot  * This iterates over all CRTCs in an atomic update, tracking only the old
673a85cb24fSFrançois Tigeot  * state. This is useful in disable functions, where we need the old state the
674a85cb24fSFrançois Tigeot  * hardware is still in.
675a85cb24fSFrançois Tigeot  */
676a85cb24fSFrançois Tigeot #define for_each_old_crtc_in_state(__state, crtc, old_crtc_state, __i)	\
677a85cb24fSFrançois Tigeot 	for ((__i) = 0;							\
6783f2dd94aSFrançois Tigeot 	     (__i) < (__state)->dev->mode_config.num_crtc;		\
679a85cb24fSFrançois Tigeot 	     (__i)++)							\
6803f2dd94aSFrançois Tigeot 		for_each_if ((__state)->crtcs[__i].ptr &&		\
6813f2dd94aSFrançois Tigeot 			     ((crtc) = (__state)->crtcs[__i].ptr,	\
6823f2dd94aSFrançois Tigeot 			     (old_crtc_state) = (__state)->crtcs[__i].old_state, 1))
683a85cb24fSFrançois Tigeot 
684a85cb24fSFrançois Tigeot /**
685a85cb24fSFrançois Tigeot  * for_each_new_crtc_in_state - iterate over all CRTCs in an atomic update
686a85cb24fSFrançois Tigeot  * @__state: &struct drm_atomic_state pointer
687a85cb24fSFrançois Tigeot  * @crtc: &struct drm_crtc iteration cursor
688a85cb24fSFrançois Tigeot  * @new_crtc_state: &struct drm_crtc_state iteration cursor for the new state
689a85cb24fSFrançois Tigeot  * @__i: int iteration cursor, for macro-internal use
690a85cb24fSFrançois Tigeot  *
691a85cb24fSFrançois Tigeot  * This iterates over all CRTCs in an atomic update, tracking only the new
692a85cb24fSFrançois Tigeot  * state. This is useful in enable functions, where we need the new state the
693a85cb24fSFrançois Tigeot  * hardware should be in when the atomic commit operation has completed.
694a85cb24fSFrançois Tigeot  */
695a85cb24fSFrançois Tigeot #define for_each_new_crtc_in_state(__state, crtc, new_crtc_state, __i)	\
696a85cb24fSFrançois Tigeot 	for ((__i) = 0;							\
6973f2dd94aSFrançois Tigeot 	     (__i) < (__state)->dev->mode_config.num_crtc;		\
6983f2dd94aSFrançois Tigeot 	     (__i)++)							\
6993f2dd94aSFrançois Tigeot 		for_each_if ((__state)->crtcs[__i].ptr &&		\
700a85cb24fSFrançois Tigeot 			     ((crtc) = (__state)->crtcs[__i].ptr,	\
7013f2dd94aSFrançois Tigeot 			     (new_crtc_state) = (__state)->crtcs[__i].new_state, 1))
7021dedbd3bSFrançois Tigeot 
7031dedbd3bSFrançois Tigeot /**
704a85cb24fSFrançois Tigeot  * for_each_oldnew_plane_in_state - iterate over all planes in an atomic update
705a85cb24fSFrançois Tigeot  * @__state: &struct drm_atomic_state pointer
706a85cb24fSFrançois Tigeot  * @plane: &struct drm_plane iteration cursor
707a85cb24fSFrançois Tigeot  * @old_plane_state: &struct drm_plane_state iteration cursor for the old state
708a85cb24fSFrançois Tigeot  * @new_plane_state: &struct drm_plane_state iteration cursor for the new state
709a85cb24fSFrançois Tigeot  * @__i: int iteration cursor, for macro-internal use
710a85cb24fSFrançois Tigeot  *
711a85cb24fSFrançois Tigeot  * This iterates over all planes in an atomic update, tracking both old and
712a85cb24fSFrançois Tigeot  * new state. This is useful in places where the state delta needs to be
713a85cb24fSFrançois Tigeot  * considered, for example in atomic check functions.
714a85cb24fSFrançois Tigeot  */
715a85cb24fSFrançois Tigeot #define for_each_oldnew_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \
716a85cb24fSFrançois Tigeot 	for ((__i) = 0;							\
7173f2dd94aSFrançois Tigeot 	     (__i) < (__state)->dev->mode_config.num_total_plane;	\
7183f2dd94aSFrançois Tigeot 	     (__i)++)							\
7193f2dd94aSFrançois Tigeot 		for_each_if ((__state)->planes[__i].ptr &&		\
720a85cb24fSFrançois Tigeot 			     ((plane) = (__state)->planes[__i].ptr,	\
721a85cb24fSFrançois Tigeot 			      (old_plane_state) = (__state)->planes[__i].old_state,\
7223f2dd94aSFrançois Tigeot 			      (new_plane_state) = (__state)->planes[__i].new_state, 1))
723a85cb24fSFrançois Tigeot 
724a85cb24fSFrançois Tigeot /**
725*78973132SSergey Zigachev  * for_each_oldnew_plane_in_state_reverse - iterate over all planes in an atomic
726*78973132SSergey Zigachev  * update in reverse order
727*78973132SSergey Zigachev  * @__state: &struct drm_atomic_state pointer
728*78973132SSergey Zigachev  * @plane: &struct drm_plane iteration cursor
729*78973132SSergey Zigachev  * @old_plane_state: &struct drm_plane_state iteration cursor for the old state
730*78973132SSergey Zigachev  * @new_plane_state: &struct drm_plane_state iteration cursor for the new state
731*78973132SSergey Zigachev  * @__i: int iteration cursor, for macro-internal use
732*78973132SSergey Zigachev  *
733*78973132SSergey Zigachev  * This iterates over all planes in an atomic update in reverse order,
734*78973132SSergey Zigachev  * tracking both old and  new state. This is useful in places where the
735*78973132SSergey Zigachev  * state delta needs to be considered, for example in atomic check functions.
736*78973132SSergey Zigachev  */
737*78973132SSergey Zigachev #define for_each_oldnew_plane_in_state_reverse(__state, plane, old_plane_state, new_plane_state, __i) \
738*78973132SSergey Zigachev 	for ((__i) = ((__state)->dev->mode_config.num_total_plane - 1);	\
739*78973132SSergey Zigachev 	     (__i) >= 0;						\
740*78973132SSergey Zigachev 	     (__i)--)							\
741*78973132SSergey Zigachev 		for_each_if ((__state)->planes[__i].ptr &&		\
742*78973132SSergey Zigachev 			     ((plane) = (__state)->planes[__i].ptr,	\
743*78973132SSergey Zigachev 			      (old_plane_state) = (__state)->planes[__i].old_state,\
744*78973132SSergey Zigachev 			      (new_plane_state) = (__state)->planes[__i].new_state, 1))
745*78973132SSergey Zigachev 
746*78973132SSergey Zigachev /**
747a85cb24fSFrançois Tigeot  * for_each_old_plane_in_state - iterate over all planes in an atomic update
748a85cb24fSFrançois Tigeot  * @__state: &struct drm_atomic_state pointer
749a85cb24fSFrançois Tigeot  * @plane: &struct drm_plane iteration cursor
750a85cb24fSFrançois Tigeot  * @old_plane_state: &struct drm_plane_state iteration cursor for the old state
751a85cb24fSFrançois Tigeot  * @__i: int iteration cursor, for macro-internal use
752a85cb24fSFrançois Tigeot  *
753a85cb24fSFrançois Tigeot  * This iterates over all planes in an atomic update, tracking only the old
754a85cb24fSFrançois Tigeot  * state. This is useful in disable functions, where we need the old state the
755a85cb24fSFrançois Tigeot  * hardware is still in.
756a85cb24fSFrançois Tigeot  */
757a85cb24fSFrançois Tigeot #define for_each_old_plane_in_state(__state, plane, old_plane_state, __i) \
758a85cb24fSFrançois Tigeot 	for ((__i) = 0;							\
7593f2dd94aSFrançois Tigeot 	     (__i) < (__state)->dev->mode_config.num_total_plane;	\
760a85cb24fSFrançois Tigeot 	     (__i)++)							\
7613f2dd94aSFrançois Tigeot 		for_each_if ((__state)->planes[__i].ptr &&		\
7623f2dd94aSFrançois Tigeot 			     ((plane) = (__state)->planes[__i].ptr,	\
7633f2dd94aSFrançois Tigeot 			      (old_plane_state) = (__state)->planes[__i].old_state, 1))
764a85cb24fSFrançois Tigeot /**
765a85cb24fSFrançois Tigeot  * for_each_new_plane_in_state - iterate over all planes in an atomic update
766a85cb24fSFrançois Tigeot  * @__state: &struct drm_atomic_state pointer
767a85cb24fSFrançois Tigeot  * @plane: &struct drm_plane iteration cursor
768a85cb24fSFrançois Tigeot  * @new_plane_state: &struct drm_plane_state iteration cursor for the new state
769a85cb24fSFrançois Tigeot  * @__i: int iteration cursor, for macro-internal use
770a85cb24fSFrançois Tigeot  *
771a85cb24fSFrançois Tigeot  * This iterates over all planes in an atomic update, tracking only the new
772a85cb24fSFrançois Tigeot  * state. This is useful in enable functions, where we need the new state the
773a85cb24fSFrançois Tigeot  * hardware should be in when the atomic commit operation has completed.
774a85cb24fSFrançois Tigeot  */
775a85cb24fSFrançois Tigeot #define for_each_new_plane_in_state(__state, plane, new_plane_state, __i) \
776a85cb24fSFrançois Tigeot 	for ((__i) = 0;							\
7773f2dd94aSFrançois Tigeot 	     (__i) < (__state)->dev->mode_config.num_total_plane;	\
778a85cb24fSFrançois Tigeot 	     (__i)++)							\
7793f2dd94aSFrançois Tigeot 		for_each_if ((__state)->planes[__i].ptr &&		\
7803f2dd94aSFrançois Tigeot 			     ((plane) = (__state)->planes[__i].ptr,	\
7813f2dd94aSFrançois Tigeot 			      (new_plane_state) = (__state)->planes[__i].new_state, 1))
7823f2dd94aSFrançois Tigeot 
7833f2dd94aSFrançois Tigeot /**
7843f2dd94aSFrançois Tigeot  * for_each_oldnew_private_obj_in_state - iterate over all private objects in an atomic update
7853f2dd94aSFrançois Tigeot  * @__state: &struct drm_atomic_state pointer
7863f2dd94aSFrançois Tigeot  * @obj: &struct drm_private_obj iteration cursor
7873f2dd94aSFrançois Tigeot  * @old_obj_state: &struct drm_private_state iteration cursor for the old state
7883f2dd94aSFrançois Tigeot  * @new_obj_state: &struct drm_private_state iteration cursor for the new state
7893f2dd94aSFrançois Tigeot  * @__i: int iteration cursor, for macro-internal use
7903f2dd94aSFrançois Tigeot  *
7913f2dd94aSFrançois Tigeot  * This iterates over all private objects in an atomic update, tracking both
7923f2dd94aSFrançois Tigeot  * old and new state. This is useful in places where the state delta needs
7933f2dd94aSFrançois Tigeot  * to be considered, for example in atomic check functions.
7943f2dd94aSFrançois Tigeot  */
7953f2dd94aSFrançois Tigeot #define for_each_oldnew_private_obj_in_state(__state, obj, old_obj_state, new_obj_state, __i) \
7963f2dd94aSFrançois Tigeot 	for ((__i) = 0; \
7973f2dd94aSFrançois Tigeot 	     (__i) < (__state)->num_private_objs && \
7983f2dd94aSFrançois Tigeot 		     ((obj) = (__state)->private_objs[__i].ptr, \
7993f2dd94aSFrançois Tigeot 		      (old_obj_state) = (__state)->private_objs[__i].old_state,	\
8003f2dd94aSFrançois Tigeot 		      (new_obj_state) = (__state)->private_objs[__i].new_state, 1); \
8013f2dd94aSFrançois Tigeot 	     (__i)++)
8023f2dd94aSFrançois Tigeot 
8033f2dd94aSFrançois Tigeot /**
8043f2dd94aSFrançois Tigeot  * for_each_old_private_obj_in_state - iterate over all private objects in an atomic update
8053f2dd94aSFrançois Tigeot  * @__state: &struct drm_atomic_state pointer
8063f2dd94aSFrançois Tigeot  * @obj: &struct drm_private_obj iteration cursor
8073f2dd94aSFrançois Tigeot  * @old_obj_state: &struct drm_private_state iteration cursor for the old state
8083f2dd94aSFrançois Tigeot  * @__i: int iteration cursor, for macro-internal use
8093f2dd94aSFrançois Tigeot  *
8103f2dd94aSFrançois Tigeot  * This iterates over all private objects in an atomic update, tracking only
8113f2dd94aSFrançois Tigeot  * the old state. This is useful in disable functions, where we need the old
8123f2dd94aSFrançois Tigeot  * state the hardware is still in.
8133f2dd94aSFrançois Tigeot  */
8143f2dd94aSFrançois Tigeot #define for_each_old_private_obj_in_state(__state, obj, old_obj_state, __i) \
8153f2dd94aSFrançois Tigeot 	for ((__i) = 0; \
8163f2dd94aSFrançois Tigeot 	     (__i) < (__state)->num_private_objs && \
8173f2dd94aSFrançois Tigeot 		     ((obj) = (__state)->private_objs[__i].ptr, \
8183f2dd94aSFrançois Tigeot 		      (old_obj_state) = (__state)->private_objs[__i].old_state, 1); \
8193f2dd94aSFrançois Tigeot 	     (__i)++)
8203f2dd94aSFrançois Tigeot 
8213f2dd94aSFrançois Tigeot /**
8223f2dd94aSFrançois Tigeot  * for_each_new_private_obj_in_state - iterate over all private objects in an atomic update
8233f2dd94aSFrançois Tigeot  * @__state: &struct drm_atomic_state pointer
8243f2dd94aSFrançois Tigeot  * @obj: &struct drm_private_obj iteration cursor
8253f2dd94aSFrançois Tigeot  * @new_obj_state: &struct drm_private_state iteration cursor for the new state
8263f2dd94aSFrançois Tigeot  * @__i: int iteration cursor, for macro-internal use
8273f2dd94aSFrançois Tigeot  *
8283f2dd94aSFrançois Tigeot  * This iterates over all private objects in an atomic update, tracking only
8293f2dd94aSFrançois Tigeot  * the new state. This is useful in enable functions, where we need the new state the
8303f2dd94aSFrançois Tigeot  * hardware should be in when the atomic commit operation has completed.
8313f2dd94aSFrançois Tigeot  */
8323f2dd94aSFrançois Tigeot #define for_each_new_private_obj_in_state(__state, obj, new_obj_state, __i) \
8333f2dd94aSFrançois Tigeot 	for ((__i) = 0; \
8343f2dd94aSFrançois Tigeot 	     (__i) < (__state)->num_private_objs && \
8353f2dd94aSFrançois Tigeot 		     ((obj) = (__state)->private_objs[__i].ptr, \
8363f2dd94aSFrançois Tigeot 		      (new_obj_state) = (__state)->private_objs[__i].new_state, 1); \
8373f2dd94aSFrançois Tigeot 	     (__i)++)
838a85cb24fSFrançois Tigeot 
839a85cb24fSFrançois Tigeot /**
8401dedbd3bSFrançois Tigeot  * drm_atomic_crtc_needs_modeset - compute combined modeset need
8411dedbd3bSFrançois Tigeot  * @state: &drm_crtc_state for the CRTC
8421dedbd3bSFrançois Tigeot  *
843a85cb24fSFrançois Tigeot  * To give drivers flexibility &struct drm_crtc_state has 3 booleans to track
8441dedbd3bSFrançois Tigeot  * whether the state CRTC changed enough to need a full modeset cycle:
8453f2dd94aSFrançois Tigeot  * mode_changed, active_changed and connectors_changed. This helper simply
8461dedbd3bSFrançois Tigeot  * combines these three to compute the overall need for a modeset for @state.
8474be47400SFrançois Tigeot  *
8484be47400SFrançois Tigeot  * The atomic helper code sets these booleans, but drivers can and should
8494be47400SFrançois Tigeot  * change them appropriately to accurately represent whether a modeset is
8504be47400SFrançois Tigeot  * really needed. In general, drivers should avoid full modesets whenever
8514be47400SFrançois Tigeot  * possible.
8524be47400SFrançois Tigeot  *
8534be47400SFrançois Tigeot  * For example if the CRTC mode has changed, and the hardware is able to enact
8544be47400SFrançois Tigeot  * the requested mode change without going through a full modeset, the driver
855a85cb24fSFrançois Tigeot  * should clear mode_changed in its &drm_mode_config_funcs.atomic_check
856a85cb24fSFrançois Tigeot  * implementation.
8571dedbd3bSFrançois Tigeot  */
85819c468b4SFrançois Tigeot static inline bool
drm_atomic_crtc_needs_modeset(const struct drm_crtc_state * state)8594be47400SFrançois Tigeot drm_atomic_crtc_needs_modeset(const struct drm_crtc_state *state)
86019c468b4SFrançois Tigeot {
861a05eeebfSFrançois Tigeot 	return state->mode_changed || state->active_changed ||
862a05eeebfSFrançois Tigeot 	       state->connectors_changed;
86319c468b4SFrançois Tigeot }
86419c468b4SFrançois Tigeot 
8652c9916cdSFrançois Tigeot #endif /* DRM_ATOMIC_H_ */
866