1380 lines · 49.2 KB · C
RawDownload
/* * Copyright (C) 2014 Red Hat * Copyright (C) 2014 Intel Corp. * * 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. * * Authors: * Rob Clark <robdclark@gmail.com> * Daniel Vetter <daniel.vetter@ffwll.ch> */ #ifndef DRM_ATOMIC_H_#define DRM_ATOMIC_H_ #include <drm/drm_crtc.h>#include <drm/drm_util.h> /** * 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. * * See also drm_crtc_commit_wait(). */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.	 *	 * Completion of this stage is signalled implicitly by calling	 * drm_crtc_send_vblank_event() on &drm_crtc_state.event.	 */	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 @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.	 *	 * Drivers should call drm_atomic_helper_commit_hw_done() to signal	 * completion of this stage.	 */	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.	 *	 * Drivers should call drm_atomic_helper_commit_cleanup_done() to signal	 * completion of this stage.	 */	struct completion cleanup_done; 	/**	 * @commit_entry:	 *	 * Entry on the per-CRTC &drm_crtc.commit_list. Protected by	 * $drm_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; 	/**	 * @abort_completion:	 *	 * A flag that's set after drm_atomic_helper_setup_commit() takes a	 * second reference for the completion of $drm_crtc_state.event. It's	 * used by the free code to remove the second reference if commit fails.	 */	bool abort_completion;}; struct __drm_colorops_state {	struct drm_colorop *ptr;	struct drm_colorop_state *state, *old_state, *new_state;}; struct __drm_planes_state {	struct drm_plane *ptr; 	/**	 * @state_to_destroy:	 *	 * Used to track the @drm_plane_state we will need to free when	 * tearing down the associated &drm_atomic_commit in	 * $drm_mode_config_funcs.atomic_state_clear or	 * drm_atomic_commit_default_clear().	 *	 * Before a commit, and the call to	 * drm_atomic_helper_swap_state() in particular, it points to	 * the same state than @new_state. After a commit, it points to	 * the same state than @old_state.	 */	struct drm_plane_state *state_to_destroy; 	struct drm_plane_state *old_state, *new_state;}; struct __drm_crtcs_state {	struct drm_crtc *ptr; 	/**	 * @state_to_destroy:	 *	 * Used to track the @drm_crtc_state we will need to free when	 * tearing down the associated &drm_atomic_commit in	 * $drm_mode_config_funcs.atomic_state_clear or	 * drm_atomic_commit_default_clear().	 *	 * Before a commit, and the call to	 * drm_atomic_helper_swap_state() in particular, it points to	 * the same state than @new_state. After a commit, it points to	 * the same state than @old_state.	 */	struct drm_crtc_state *state_to_destroy; 	struct drm_crtc_state *old_state, *new_state; 	/**	 * @commit:	 *	 * A reference to the CRTC commit object that is kept for use by	 * drm_atomic_helper_wait_for_flip_done() after	 * drm_atomic_helper_commit_hw_done() is called. This ensures that a	 * concurrent commit won't free a commit object that is still in use.	 */	struct drm_crtc_commit *commit; 	s32 __user *out_fence_ptr;	u64 last_vblank_count;}; struct __drm_connnectors_state {	struct drm_connector *ptr; 	/**	 * @state_to_destroy:	 *	 * Used to track the @drm_connector_state we will need to free	 * when tearing down the associated &drm_atomic_commit in	 * $drm_mode_config_funcs.atomic_state_clear or	 * drm_atomic_commit_default_clear().	 *	 * Before a commit, and the call to	 * drm_atomic_helper_swap_state() in particular, it points to	 * the same state than @new_state. After a commit, it points to	 * the same state than @old_state.	 */	struct drm_connector_state *state_to_destroy; 	struct drm_connector_state *old_state, *new_state; 	/**	 * @out_fence_ptr:	 *	 * User-provided pointer which the kernel uses to return a sync_file	 * file descriptor. Used by writeback connectors to signal completion of	 * the writeback.	 */	s32 __user *out_fence_ptr;}; struct drm_private_obj;struct drm_private_state; /** * struct drm_private_state_funcs - atomic state functions for private objects * * These hooks are used by atomic helpers to create, swap and destroy states of * private objects. The structure itself is used as a vtable to identify the * associated private object type. Each private object type that needs to be * added to the atomic states is expected to have an implementation of these * hooks and pass a pointer to its drm_private_state_funcs struct to * drm_atomic_get_private_obj_state(). */struct drm_private_state_funcs {	/**	 * @atomic_create_state:	 *	 * Allocates a pristine, initialized, state for the private	 * object and returns it. This callback must have no side	 * effects: in particular, the returned state must not be	 * assigned to the object's state pointer and it must not affect	 * the hardware state.	 *	 * RETURNS:	 *	 * A new, pristine, private state instance or an error pointer	 * on failure.	 */	struct drm_private_state *(*atomic_create_state)(struct drm_private_obj *obj); 	/**	 * @atomic_duplicate_state:	 *	 * Duplicate the current state of the private object and return it. It	 * is an error to call this before obj->state has been initialized.	 *	 * RETURNS:	 *	 * Duplicated atomic state or NULL when obj->state is not	 * initialized or allocation failed.	 */	struct drm_private_state *(*atomic_duplicate_state)(struct drm_private_obj *obj); 	/**	 * @atomic_destroy_state:	 *	 * Frees the private object state created with @atomic_duplicate_state.	 */	void (*atomic_destroy_state)(struct drm_private_obj *obj,				     struct drm_private_state *state); 	/**	 * @atomic_print_state:	 *	 * If driver subclasses &struct drm_private_state, it should implement	 * this optional hook for printing additional driver specific state.	 *	 * Do not call this directly, use drm_atomic_private_obj_print_state()	 * instead.	 */	void (*atomic_print_state)(struct drm_printer *p,				   const struct drm_private_state *state);}; /** * struct drm_private_obj - base struct for driver private atomic object * * A driver private object is initialized by calling * drm_atomic_private_obj_init() and cleaned up by calling * drm_atomic_private_obj_fini(). * * Currently only tracks the state update functions and the opaque driver * private state itself, but in the future might also track which * &drm_modeset_lock is required to duplicate and update this object's state. * * All private objects must be initialized before the DRM device they are * attached to is registered to the DRM subsystem (call to drm_dev_register()) * and should stay around until this DRM device is unregistered (call to * drm_dev_unregister()). In other words, private objects lifetime is tied * to the DRM device lifetime. This implies that: * * 1/ all calls to drm_atomic_private_obj_init() must be done before calling *    drm_dev_register() * 2/ all calls to drm_atomic_private_obj_fini() must be done after calling *    drm_dev_unregister() * * If that private object is used to store a state shared by multiple * CRTCs, proper care must be taken to ensure that non-blocking commits are * properly ordered to avoid a use-after-free issue. * * Indeed, assuming a sequence of two non-blocking &drm_atomic_commit on two * different &drm_crtc using different &drm_plane and &drm_connector, so with no * resources shared, there's no guarantee on which commit is going to happen * first. However, the second &drm_atomic_commit will consider the first * &drm_private_obj its old state, and will be in charge of freeing it whenever * the second &drm_atomic_commit is done. * * If the first &drm_atomic_commit happens after it, it will consider its * &drm_private_obj the new state and will be likely to access it, resulting in * an access to a freed memory region. Drivers should store (and get a reference * to) the &drm_crtc_commit structure in our private state in * &drm_mode_config_helper_funcs.atomic_commit_setup, and then wait for that * commit to complete as the first step of * &drm_mode_config_helper_funcs.atomic_commit_tail, similar to * drm_atomic_helper_wait_for_dependencies(). */struct drm_private_obj {	/**	 * @dev: parent DRM device	 */	struct drm_device *dev; 	/**	 * @head: List entry used to attach a private object to a &drm_device	 * (queued to &drm_mode_config.privobj_list).	 */	struct list_head head; 	/**	 * @lock: Modeset lock to protect the state object.	 */	struct drm_modeset_lock lock; 	/**	 * @state: Current atomic state for this driver private object.	 */	struct drm_private_state *state; 	/**	 * @funcs:	 *	 * Functions to manipulate the state of this driver private object, see	 * &drm_private_state_funcs.	 */	const struct drm_private_state_funcs *funcs;}; /** * drm_for_each_privobj() - private object iterator * * @privobj: pointer to the current private object. Updated after each *	     iteration * @dev: the DRM device we want get private objects from * * Allows one to iterate over all private objects attached to @dev */#define drm_for_each_privobj(privobj, dev) \	list_for_each_entry(privobj, &(dev)->mode_config.privobj_list, head) /** * struct drm_private_state - base struct for driver private object state * * Currently only contains a backpointer to the overall atomic update, * and the relevant private object but in the future also might hold * synchronization information similar to e.g. &drm_crtc.commit. */struct drm_private_state {	/**	 * @state: backpointer to global drm_atomic_commit	 */	struct drm_atomic_commit *state; 	/**	 * @obj: backpointer to the private object	 */	struct drm_private_obj *obj;}; struct __drm_private_objs_state {	struct drm_private_obj *ptr; 	/**	 * @state_to_destroy:	 *	 * Used to track the @drm_private_state we will need to free	 * when tearing down the associated &drm_atomic_commit in	 * $drm_mode_config_funcs.atomic_state_clear or	 * drm_atomic_commit_default_clear().	 *	 * Before a commit, and the call to	 * drm_atomic_helper_swap_state() in particular, it points to	 * the same state than @new_state. After a commit, it points to	 * the same state than @old_state.	 */	struct drm_private_state *state_to_destroy; 	struct drm_private_state *old_state, *new_state;}; /** * struct drm_atomic_commit - Atomic commit structure * * This structure is the kernel counterpart of @drm_mode_atomic and represents * an atomic commit that transitions from an old to a new display state. It * contains all the objects affected by the atomic commit and both the new * state structures and pointers to the old state structures for * these. * * States are added to an atomic update by calling drm_atomic_get_crtc_state(), * drm_atomic_get_plane_state(), drm_atomic_get_connector_state(), or for * private state structures, drm_atomic_get_private_obj_state(). * * NOTE: struct drm_atomic_commit first started as a single collection of * entities state pointers (drm_plane_state, drm_crtc_state, etc.). * * At atomic_check time, you could get the state about to be committed * from drm_atomic_commit, and the one currently running from the * entities state pointer (drm_crtc.state, for example). After the call * to drm_atomic_helper_swap_state(), the entities state pointer would * contain the state previously checked, and the drm_atomic_commit * structure the old state. * * Over time, and in order to avoid confusion, drm_atomic_commit has * grown to have both the old state (ie, the state we replace) and the * new state (ie, the state we want to apply). Those names are stable * during the commit process, which makes it easier to reason about. * * You can still find some traces of that evolution through some hooks * or callbacks taking a drm_atomic_commit parameter called names like * "old_state". This doesn't necessarily mean that the previous * drm_atomic_commit is passed, but rather that this used to be the state * collection we were replacing after drm_atomic_helper_swap_state(), * but the variable name was never updated. * * Some atomic operations implementations followed a similar process. We * first started to pass the entity state only. However, it was pretty * cumbersome for drivers, and especially CRTCs, to retrieve the states * of other components. Thus, we switched to passing the whole * drm_atomic_commit as a parameter to those operations. Similarly, the * transition isn't complete yet, and one might still find atomic * operations taking a drm_atomic_commit pointer, or a component state * pointer. The former is the preferred form. */struct drm_atomic_commit {	/**	 * @ref:	 *	 * Count of all references to this update (will not be freed until zero).	 */	struct kref ref; 	/**	 * @dev: Parent DRM Device.	 */	struct drm_device *dev; 	/**	 * @allow_modeset:	 *	 * Allow full modeset. This is used by the ATOMIC IOCTL handler to	 * implement the DRM_MODE_ATOMIC_ALLOW_MODESET flag. Drivers should

Lines 1–500 of 1380.