16dd7b6ceSThomas Zimmermann // SPDX-License-Identifier: GPL-2.0-or-later
26dd7b6ceSThomas Zimmermann 
3820c1707SThomas Zimmermann #include <linux/dma-resv.h>
41ea28bc5SChristian König #include <linux/dma-fence-chain.h>
5820c1707SThomas Zimmermann 
66dd7b6ceSThomas Zimmermann #include <drm/drm_atomic_state_helper.h>
7820c1707SThomas Zimmermann #include <drm/drm_atomic_uapi.h>
8720cf96dSVille Syrjälä #include <drm/drm_framebuffer.h>
9820c1707SThomas Zimmermann #include <drm/drm_gem.h>
106dd7b6ceSThomas Zimmermann #include <drm/drm_gem_atomic_helper.h>
116dd7b6ceSThomas Zimmermann #include <drm/drm_gem_framebuffer_helper.h>
126dd7b6ceSThomas Zimmermann #include <drm/drm_simple_kms_helper.h>
136dd7b6ceSThomas Zimmermann 
146dd7b6ceSThomas Zimmermann #include "drm_internal.h"
156dd7b6ceSThomas Zimmermann 
166dd7b6ceSThomas Zimmermann /**
176dd7b6ceSThomas Zimmermann  * DOC: overview
186dd7b6ceSThomas Zimmermann  *
196dd7b6ceSThomas Zimmermann  * The GEM atomic helpers library implements generic atomic-commit
206dd7b6ceSThomas Zimmermann  * functions for drivers that use GEM objects. Currently, it provides
21820c1707SThomas Zimmermann  * synchronization helpers, and plane state and framebuffer BO mappings
22820c1707SThomas Zimmermann  * for planes with shadow buffers.
23820c1707SThomas Zimmermann  *
24820c1707SThomas Zimmermann  * Before scanout, a plane's framebuffer needs to be synchronized with
25820c1707SThomas Zimmermann  * possible writers that draw into the framebuffer. All drivers should
26820c1707SThomas Zimmermann  * call drm_gem_plane_helper_prepare_fb() from their implementation of
27820c1707SThomas Zimmermann  * struct &drm_plane_helper.prepare_fb . It sets the plane's fence from
28820c1707SThomas Zimmermann  * the framebuffer so that the DRM core can synchronize access automatically.
29820c1707SThomas Zimmermann  * drm_gem_plane_helper_prepare_fb() can also be used directly as
30*00b5497dSThomas Zimmermann  * implementation of prepare_fb.
31820c1707SThomas Zimmermann  *
32820c1707SThomas Zimmermann  * .. code-block:: c
33820c1707SThomas Zimmermann  *
34820c1707SThomas Zimmermann  *	#include <drm/drm_gem_atomic_helper.h>
35820c1707SThomas Zimmermann  *
36820c1707SThomas Zimmermann  *	struct drm_plane_helper_funcs driver_plane_helper_funcs = {
37820c1707SThomas Zimmermann  *		...,
38820c1707SThomas Zimmermann  *		. prepare_fb = drm_gem_plane_helper_prepare_fb,
39820c1707SThomas Zimmermann  *	};
40820c1707SThomas Zimmermann  *
419dc9067dSThomas Zimmermann  * A driver using a shadow buffer copies the content of the shadow buffers
429dc9067dSThomas Zimmermann  * into the HW's framebuffer memory during an atomic update. This requires
439dc9067dSThomas Zimmermann  * a mapping of the shadow buffer into kernel address space. The mappings
449dc9067dSThomas Zimmermann  * cannot be established by commit-tail functions, such as atomic_update,
459dc9067dSThomas Zimmermann  * as this would violate locking rules around dma_buf_vmap().
469dc9067dSThomas Zimmermann  *
479dc9067dSThomas Zimmermann  * The helpers for shadow-buffered planes establish and release mappings,
489dc9067dSThomas Zimmermann  * and provide struct drm_shadow_plane_state, which stores the plane's mapping
490ae865efSCai Huoqing  * for commit-tail functions.
509dc9067dSThomas Zimmermann  *
519dc9067dSThomas Zimmermann  * Shadow-buffered planes can easily be enabled by using the provided macros
529dc9067dSThomas Zimmermann  * %DRM_GEM_SHADOW_PLANE_FUNCS and %DRM_GEM_SHADOW_PLANE_HELPER_FUNCS.
539dc9067dSThomas Zimmermann  * These macros set up the plane and plane-helper callbacks to point to the
549dc9067dSThomas Zimmermann  * shadow-buffer helpers.
559dc9067dSThomas Zimmermann  *
569dc9067dSThomas Zimmermann  * .. code-block:: c
579dc9067dSThomas Zimmermann  *
58820c1707SThomas Zimmermann  *	#include <drm/drm_gem_atomic_helper.h>
599dc9067dSThomas Zimmermann  *
609dc9067dSThomas Zimmermann  *	struct drm_plane_funcs driver_plane_funcs = {
619dc9067dSThomas Zimmermann  *		...,
629dc9067dSThomas Zimmermann  *		DRM_GEM_SHADOW_PLANE_FUNCS,
639dc9067dSThomas Zimmermann  *	};
649dc9067dSThomas Zimmermann  *
659dc9067dSThomas Zimmermann  *	struct drm_plane_helper_funcs driver_plane_helper_funcs = {
669dc9067dSThomas Zimmermann  *		...,
679dc9067dSThomas Zimmermann  *		DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
689dc9067dSThomas Zimmermann  *	};
699dc9067dSThomas Zimmermann  *
709dc9067dSThomas Zimmermann  * In the driver's atomic-update function, shadow-buffer mappings are available
719dc9067dSThomas Zimmermann  * from the plane state. Use to_drm_shadow_plane_state() to upcast from
729dc9067dSThomas Zimmermann  * struct drm_plane_state.
739dc9067dSThomas Zimmermann  *
749dc9067dSThomas Zimmermann  * .. code-block:: c
759dc9067dSThomas Zimmermann  *
769dc9067dSThomas Zimmermann  *	void driver_plane_atomic_update(struct drm_plane *plane,
779dc9067dSThomas Zimmermann  *					struct drm_plane_state *old_plane_state)
789dc9067dSThomas Zimmermann  *	{
799dc9067dSThomas Zimmermann  *		struct drm_plane_state *plane_state = plane->state;
809dc9067dSThomas Zimmermann  *		struct drm_shadow_plane_state *shadow_plane_state =
819dc9067dSThomas Zimmermann  *			to_drm_shadow_plane_state(plane_state);
829dc9067dSThomas Zimmermann  *
839dc9067dSThomas Zimmermann  *		// access shadow buffer via shadow_plane_state->map
849dc9067dSThomas Zimmermann  *	}
859dc9067dSThomas Zimmermann  *
869dc9067dSThomas Zimmermann  * A mapping address for each of the framebuffer's buffer object is stored in
879dc9067dSThomas Zimmermann  * struct &drm_shadow_plane_state.map. The mappings are valid while the state
889dc9067dSThomas Zimmermann  * is being used.
899dc9067dSThomas Zimmermann  *
909dc9067dSThomas Zimmermann  * Drivers that use struct drm_simple_display_pipe can use
919dc9067dSThomas Zimmermann  * %DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS to initialize the rsp
929dc9067dSThomas Zimmermann  * callbacks. Access to shadow-buffer mappings is similar to regular
939dc9067dSThomas Zimmermann  * atomic_update.
949dc9067dSThomas Zimmermann  *
959dc9067dSThomas Zimmermann  * .. code-block:: c
969dc9067dSThomas Zimmermann  *
979dc9067dSThomas Zimmermann  *	struct drm_simple_display_pipe_funcs driver_pipe_funcs = {
989dc9067dSThomas Zimmermann  *		...,
999dc9067dSThomas Zimmermann  *		DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
1009dc9067dSThomas Zimmermann  *	};
1019dc9067dSThomas Zimmermann  *
1029dc9067dSThomas Zimmermann  *	void driver_pipe_enable(struct drm_simple_display_pipe *pipe,
1039dc9067dSThomas Zimmermann  *				struct drm_crtc_state *crtc_state,
1049dc9067dSThomas Zimmermann  *				struct drm_plane_state *plane_state)
1059dc9067dSThomas Zimmermann  *	{
1069dc9067dSThomas Zimmermann  *		struct drm_shadow_plane_state *shadow_plane_state =
1079dc9067dSThomas Zimmermann  *			to_drm_shadow_plane_state(plane_state);
1089dc9067dSThomas Zimmermann  *
1099dc9067dSThomas Zimmermann  *		// access shadow buffer via shadow_plane_state->map
1109dc9067dSThomas Zimmermann  *	}
1116dd7b6ceSThomas Zimmermann  */
1126dd7b6ceSThomas Zimmermann 
1136dd7b6ceSThomas Zimmermann /*
114820c1707SThomas Zimmermann  * Plane Helpers
115820c1707SThomas Zimmermann  */
116820c1707SThomas Zimmermann 
117820c1707SThomas Zimmermann /**
118820c1707SThomas Zimmermann  * drm_gem_plane_helper_prepare_fb() - Prepare a GEM backed framebuffer
119820c1707SThomas Zimmermann  * @plane: Plane
120820c1707SThomas Zimmermann  * @state: Plane state the fence will be attached to
121820c1707SThomas Zimmermann  *
122820c1707SThomas Zimmermann  * This function extracts the exclusive fence from &drm_gem_object.resv and
123820c1707SThomas Zimmermann  * attaches it to plane state for the atomic helper to wait on. This is
124820c1707SThomas Zimmermann  * necessary to correctly implement implicit synchronization for any buffers
125820c1707SThomas Zimmermann  * shared as a struct &dma_buf. This function can be used as the
126820c1707SThomas Zimmermann  * &drm_plane_helper_funcs.prepare_fb callback.
127820c1707SThomas Zimmermann  *
128820c1707SThomas Zimmermann  * There is no need for &drm_plane_helper_funcs.cleanup_fb hook for simple
129820c1707SThomas Zimmermann  * GEM based framebuffer drivers which have their buffers always pinned in
130820c1707SThomas Zimmermann  * memory.
131820c1707SThomas Zimmermann  *
1327d30963fSDaniel Vetter  * This function is the default implementation for GEM drivers of
1337d30963fSDaniel Vetter  * &drm_plane_helper_funcs.prepare_fb if no callback is provided.
134820c1707SThomas Zimmermann  */
1351ea28bc5SChristian König int drm_gem_plane_helper_prepare_fb(struct drm_plane *plane,
1361ea28bc5SChristian König 				    struct drm_plane_state *state)
137820c1707SThomas Zimmermann {
1381ea28bc5SChristian König 	struct dma_fence *fence = dma_fence_get(state->fence);
1391ea28bc5SChristian König 	enum dma_resv_usage usage;
1401ea28bc5SChristian König 	size_t i;
141c382df71SChristian König 	int ret;
142820c1707SThomas Zimmermann 
143820c1707SThomas Zimmermann 	if (!state->fb)
144820c1707SThomas Zimmermann 		return 0;
145820c1707SThomas Zimmermann 
1461ea28bc5SChristian König 	/*
1471ea28bc5SChristian König 	 * Only add the kernel fences here if there is already a fence set via
1481ea28bc5SChristian König 	 * explicit fencing interfaces on the atomic ioctl.
1491ea28bc5SChristian König 	 *
1501ea28bc5SChristian König 	 * This way explicit fencing can be used to overrule implicit fencing,
1511ea28bc5SChristian König 	 * which is important to make explicit fencing use-cases work: One
1521ea28bc5SChristian König 	 * example is using one buffer for 2 screens with different refresh
1531ea28bc5SChristian König 	 * rates. Implicit fencing will clamp rendering to the refresh rate of
1541ea28bc5SChristian König 	 * the slower screen, whereas explicit fence allows 2 independent
1551ea28bc5SChristian König 	 * render and display loops on a single buffer. If a driver allows
1561ea28bc5SChristian König 	 * obeys both implicit and explicit fences for plane updates, then it
1571ea28bc5SChristian König 	 * will break all the benefits of explicit fencing.
158c382df71SChristian König 	 */
1591ea28bc5SChristian König 	usage = fence ? DMA_RESV_USAGE_KERNEL : DMA_RESV_USAGE_WRITE;
1601ea28bc5SChristian König 
1611ea28bc5SChristian König 	for (i = 0; i < state->fb->format->num_planes; ++i) {
1621ea28bc5SChristian König 		struct drm_gem_object *obj = drm_gem_fb_get_obj(state->fb, i);
1631ea28bc5SChristian König 		struct dma_fence *new;
1641ea28bc5SChristian König 
165746b9c62SThomas Zimmermann 		if (!obj) {
166746b9c62SThomas Zimmermann 			ret = -EINVAL;
167746b9c62SThomas Zimmermann 			goto error;
168746b9c62SThomas Zimmermann 		}
1691ea28bc5SChristian König 
1701ea28bc5SChristian König 		ret = dma_resv_get_singleton(obj->resv, usage, &new);
1711ea28bc5SChristian König 		if (ret)
1721ea28bc5SChristian König 			goto error;
1731ea28bc5SChristian König 
1741ea28bc5SChristian König 		if (new && fence) {
1751ea28bc5SChristian König 			struct dma_fence_chain *chain = dma_fence_chain_alloc();
1761ea28bc5SChristian König 
1771ea28bc5SChristian König 			if (!chain) {
1781ea28bc5SChristian König 				ret = -ENOMEM;
1791ea28bc5SChristian König 				goto error;
1801ea28bc5SChristian König 			}
1811ea28bc5SChristian König 
1821ea28bc5SChristian König 			dma_fence_chain_init(chain, fence, new, 1);
1831ea28bc5SChristian König 			fence = &chain->base;
1841ea28bc5SChristian König 
1851ea28bc5SChristian König 		} else if (new) {
1861ea28bc5SChristian König 			fence = new;
1871ea28bc5SChristian König 		}
1881ea28bc5SChristian König 	}
1891ea28bc5SChristian König 
1901ea28bc5SChristian König 	dma_fence_put(state->fence);
1911ea28bc5SChristian König 	state->fence = fence;
192820c1707SThomas Zimmermann 	return 0;
1931ea28bc5SChristian König 
1941ea28bc5SChristian König error:
1951ea28bc5SChristian König 	dma_fence_put(fence);
1961ea28bc5SChristian König 	return ret;
197820c1707SThomas Zimmermann }
198820c1707SThomas Zimmermann EXPORT_SYMBOL_GPL(drm_gem_plane_helper_prepare_fb);
199820c1707SThomas Zimmermann 
200820c1707SThomas Zimmermann /*
2016dd7b6ceSThomas Zimmermann  * Shadow-buffered Planes
2026dd7b6ceSThomas Zimmermann  */
2036dd7b6ceSThomas Zimmermann 
2049dc9067dSThomas Zimmermann /**
205b7156502SThomas Zimmermann  * __drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state
206b7156502SThomas Zimmermann  * @plane: the plane
207b7156502SThomas Zimmermann  * @new_shadow_plane_state: the new shadow-buffered plane state
208b7156502SThomas Zimmermann  *
209b7156502SThomas Zimmermann  * This function duplicates shadow-buffered plane state. This is helpful for drivers
210b7156502SThomas Zimmermann  * that subclass struct drm_shadow_plane_state.
211b7156502SThomas Zimmermann  *
212b7156502SThomas Zimmermann  * The function does not duplicate existing mappings of the shadow buffers.
213b7156502SThomas Zimmermann  * Mappings are maintained during the atomic commit by the plane's prepare_fb
214b7156502SThomas Zimmermann  * and cleanup_fb helpers. See drm_gem_prepare_shadow_fb() and drm_gem_cleanup_shadow_fb()
215b7156502SThomas Zimmermann  * for corresponding helpers.
216b7156502SThomas Zimmermann  */
217b7156502SThomas Zimmermann void
218b7156502SThomas Zimmermann __drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane,
219b7156502SThomas Zimmermann 				       struct drm_shadow_plane_state *new_shadow_plane_state)
220b7156502SThomas Zimmermann {
221b7156502SThomas Zimmermann 	__drm_atomic_helper_plane_duplicate_state(plane, &new_shadow_plane_state->base);
222b7156502SThomas Zimmermann }
223b7156502SThomas Zimmermann EXPORT_SYMBOL(__drm_gem_duplicate_shadow_plane_state);
224b7156502SThomas Zimmermann 
225b7156502SThomas Zimmermann /**
2269dc9067dSThomas Zimmermann  * drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state
2279dc9067dSThomas Zimmermann  * @plane: the plane
2289dc9067dSThomas Zimmermann  *
2299dc9067dSThomas Zimmermann  * This function implements struct &drm_plane_funcs.atomic_duplicate_state for
2309dc9067dSThomas Zimmermann  * shadow-buffered planes. It assumes the existing state to be of type
2319dc9067dSThomas Zimmermann  * struct drm_shadow_plane_state and it allocates the new state to be of this
2329dc9067dSThomas Zimmermann  * type.
2339dc9067dSThomas Zimmermann  *
2349dc9067dSThomas Zimmermann  * The function does not duplicate existing mappings of the shadow buffers.
2359dc9067dSThomas Zimmermann  * Mappings are maintained during the atomic commit by the plane's prepare_fb
2369dc9067dSThomas Zimmermann  * and cleanup_fb helpers. See drm_gem_prepare_shadow_fb() and drm_gem_cleanup_shadow_fb()
2379dc9067dSThomas Zimmermann  * for corresponding helpers.
2389dc9067dSThomas Zimmermann  *
2399dc9067dSThomas Zimmermann  * Returns:
2409dc9067dSThomas Zimmermann  * A pointer to a new plane state on success, or NULL otherwise.
2419dc9067dSThomas Zimmermann  */
2429dc9067dSThomas Zimmermann struct drm_plane_state *
2436dd7b6ceSThomas Zimmermann drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane)
2446dd7b6ceSThomas Zimmermann {
2456dd7b6ceSThomas Zimmermann 	struct drm_plane_state *plane_state = plane->state;
2466dd7b6ceSThomas Zimmermann 	struct drm_shadow_plane_state *new_shadow_plane_state;
2476dd7b6ceSThomas Zimmermann 
2486dd7b6ceSThomas Zimmermann 	if (!plane_state)
2496dd7b6ceSThomas Zimmermann 		return NULL;
2506dd7b6ceSThomas Zimmermann 
2516dd7b6ceSThomas Zimmermann 	new_shadow_plane_state = kzalloc(sizeof(*new_shadow_plane_state), GFP_KERNEL);
2526dd7b6ceSThomas Zimmermann 	if (!new_shadow_plane_state)
2536dd7b6ceSThomas Zimmermann 		return NULL;
254b7156502SThomas Zimmermann 	__drm_gem_duplicate_shadow_plane_state(plane, new_shadow_plane_state);
2556dd7b6ceSThomas Zimmermann 
2566dd7b6ceSThomas Zimmermann 	return &new_shadow_plane_state->base;
2576dd7b6ceSThomas Zimmermann }
2589dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_duplicate_shadow_plane_state);
2596dd7b6ceSThomas Zimmermann 
2609dc9067dSThomas Zimmermann /**
261b7156502SThomas Zimmermann  * __drm_gem_destroy_shadow_plane_state - cleans up shadow-buffered plane state
262b7156502SThomas Zimmermann  * @shadow_plane_state: the shadow-buffered plane state
263b7156502SThomas Zimmermann  *
264b7156502SThomas Zimmermann  * This function cleans up shadow-buffered plane state. Helpful for drivers that
265b7156502SThomas Zimmermann  * subclass struct drm_shadow_plane_state.
266b7156502SThomas Zimmermann  */
267b7156502SThomas Zimmermann void __drm_gem_destroy_shadow_plane_state(struct drm_shadow_plane_state *shadow_plane_state)
268b7156502SThomas Zimmermann {
269b7156502SThomas Zimmermann 	__drm_atomic_helper_plane_destroy_state(&shadow_plane_state->base);
270b7156502SThomas Zimmermann }
271b7156502SThomas Zimmermann EXPORT_SYMBOL(__drm_gem_destroy_shadow_plane_state);
272b7156502SThomas Zimmermann 
273b7156502SThomas Zimmermann /**
2749dc9067dSThomas Zimmermann  * drm_gem_destroy_shadow_plane_state - deletes shadow-buffered plane state
2759dc9067dSThomas Zimmermann  * @plane: the plane
2769dc9067dSThomas Zimmermann  * @plane_state: the plane state of type struct drm_shadow_plane_state
2779dc9067dSThomas Zimmermann  *
2789dc9067dSThomas Zimmermann  * This function implements struct &drm_plane_funcs.atomic_destroy_state
2799dc9067dSThomas Zimmermann  * for shadow-buffered planes. It expects that mappings of shadow buffers
2809dc9067dSThomas Zimmermann  * have been released already.
2819dc9067dSThomas Zimmermann  */
2829dc9067dSThomas Zimmermann void drm_gem_destroy_shadow_plane_state(struct drm_plane *plane,
2836dd7b6ceSThomas Zimmermann 					struct drm_plane_state *plane_state)
2846dd7b6ceSThomas Zimmermann {
2856dd7b6ceSThomas Zimmermann 	struct drm_shadow_plane_state *shadow_plane_state =
2866dd7b6ceSThomas Zimmermann 		to_drm_shadow_plane_state(plane_state);
2876dd7b6ceSThomas Zimmermann 
288b7156502SThomas Zimmermann 	__drm_gem_destroy_shadow_plane_state(shadow_plane_state);
2896dd7b6ceSThomas Zimmermann 	kfree(shadow_plane_state);
2906dd7b6ceSThomas Zimmermann }
2919dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_destroy_shadow_plane_state);
2926dd7b6ceSThomas Zimmermann 
2939dc9067dSThomas Zimmermann /**
294b7156502SThomas Zimmermann  * __drm_gem_reset_shadow_plane - resets a shadow-buffered plane
295b7156502SThomas Zimmermann  * @plane: the plane
296b7156502SThomas Zimmermann  * @shadow_plane_state: the shadow-buffered plane state
297b7156502SThomas Zimmermann  *
298b7156502SThomas Zimmermann  * This function resets state for shadow-buffered planes. Helpful
299b7156502SThomas Zimmermann  * for drivers that subclass struct drm_shadow_plane_state.
300b7156502SThomas Zimmermann  */
301b7156502SThomas Zimmermann void __drm_gem_reset_shadow_plane(struct drm_plane *plane,
302b7156502SThomas Zimmermann 				  struct drm_shadow_plane_state *shadow_plane_state)
303b7156502SThomas Zimmermann {
304b7156502SThomas Zimmermann 	__drm_atomic_helper_plane_reset(plane, &shadow_plane_state->base);
305b7156502SThomas Zimmermann }
306b7156502SThomas Zimmermann EXPORT_SYMBOL(__drm_gem_reset_shadow_plane);
307b7156502SThomas Zimmermann 
308b7156502SThomas Zimmermann /**
3099dc9067dSThomas Zimmermann  * drm_gem_reset_shadow_plane - resets a shadow-buffered plane
3109dc9067dSThomas Zimmermann  * @plane: the plane
3119dc9067dSThomas Zimmermann  *
3129dc9067dSThomas Zimmermann  * This function implements struct &drm_plane_funcs.reset_plane for
3139dc9067dSThomas Zimmermann  * shadow-buffered planes. It assumes the current plane state to be
3149dc9067dSThomas Zimmermann  * of type struct drm_shadow_plane and it allocates the new state of
3159dc9067dSThomas Zimmermann  * this type.
3169dc9067dSThomas Zimmermann  */
3179dc9067dSThomas Zimmermann void drm_gem_reset_shadow_plane(struct drm_plane *plane)
3186dd7b6ceSThomas Zimmermann {
3196dd7b6ceSThomas Zimmermann 	struct drm_shadow_plane_state *shadow_plane_state;
3206dd7b6ceSThomas Zimmermann 
3216dd7b6ceSThomas Zimmermann 	if (plane->state) {
3226dd7b6ceSThomas Zimmermann 		drm_gem_destroy_shadow_plane_state(plane, plane->state);
3236dd7b6ceSThomas Zimmermann 		plane->state = NULL; /* must be set to NULL here */
3246dd7b6ceSThomas Zimmermann 	}
3256dd7b6ceSThomas Zimmermann 
3266dd7b6ceSThomas Zimmermann 	shadow_plane_state = kzalloc(sizeof(*shadow_plane_state), GFP_KERNEL);
3276dd7b6ceSThomas Zimmermann 	if (!shadow_plane_state)
3286dd7b6ceSThomas Zimmermann 		return;
329b7156502SThomas Zimmermann 	__drm_gem_reset_shadow_plane(plane, shadow_plane_state);
3306dd7b6ceSThomas Zimmermann }
3319dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_reset_shadow_plane);
3326dd7b6ceSThomas Zimmermann 
3339dc9067dSThomas Zimmermann /**
334359c6649SThomas Zimmermann  * drm_gem_begin_shadow_fb_access - prepares shadow framebuffers for CPU access
3359dc9067dSThomas Zimmermann  * @plane: the plane
3369dc9067dSThomas Zimmermann  * @plane_state: the plane state of type struct drm_shadow_plane_state
3379dc9067dSThomas Zimmermann  *
338359c6649SThomas Zimmermann  * This function implements struct &drm_plane_helper_funcs.begin_fb_access. It
3399dc9067dSThomas Zimmermann  * maps all buffer objects of the plane's framebuffer into kernel address
340359c6649SThomas Zimmermann  * space and stores them in struct &drm_shadow_plane_state.map. The first data
341359c6649SThomas Zimmermann  * bytes are available in struct &drm_shadow_plane_state.data.
3429dc9067dSThomas Zimmermann  *
343359c6649SThomas Zimmermann  * See drm_gem_end_shadow_fb_access() for cleanup.
3449dc9067dSThomas Zimmermann  *
3459dc9067dSThomas Zimmermann  * Returns:
3469dc9067dSThomas Zimmermann  * 0 on success, or a negative errno code otherwise.
3479dc9067dSThomas Zimmermann  */
348359c6649SThomas Zimmermann int drm_gem_begin_shadow_fb_access(struct drm_plane *plane, struct drm_plane_state *plane_state)
3496dd7b6ceSThomas Zimmermann {
3506dd7b6ceSThomas Zimmermann 	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
3516dd7b6ceSThomas Zimmermann 	struct drm_framebuffer *fb = plane_state->fb;
3526dd7b6ceSThomas Zimmermann 
3536dd7b6ceSThomas Zimmermann 	if (!fb)
3546dd7b6ceSThomas Zimmermann 		return 0;
3556dd7b6ceSThomas Zimmermann 
35643b36232SThomas Zimmermann 	return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data);
3576dd7b6ceSThomas Zimmermann }
358359c6649SThomas Zimmermann EXPORT_SYMBOL(drm_gem_begin_shadow_fb_access);
3596dd7b6ceSThomas Zimmermann 
3609dc9067dSThomas Zimmermann /**
361359c6649SThomas Zimmermann  * drm_gem_end_shadow_fb_access - releases shadow framebuffers from CPU access
3629dc9067dSThomas Zimmermann  * @plane: the plane
3639dc9067dSThomas Zimmermann  * @plane_state: the plane state of type struct drm_shadow_plane_state
3649dc9067dSThomas Zimmermann  *
365359c6649SThomas Zimmermann  * This function implements struct &drm_plane_helper_funcs.end_fb_access. It
366359c6649SThomas Zimmermann  * undoes all effects of drm_gem_begin_shadow_fb_access() in reverse order.
3679dc9067dSThomas Zimmermann  *
368359c6649SThomas Zimmermann  * See drm_gem_begin_shadow_fb_access() for more information.
3699dc9067dSThomas Zimmermann  */
370359c6649SThomas Zimmermann void drm_gem_end_shadow_fb_access(struct drm_plane *plane, struct drm_plane_state *plane_state)
3716dd7b6ceSThomas Zimmermann {
3726dd7b6ceSThomas Zimmermann 	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
3736dd7b6ceSThomas Zimmermann 	struct drm_framebuffer *fb = plane_state->fb;
3746dd7b6ceSThomas Zimmermann 
3756dd7b6ceSThomas Zimmermann 	if (!fb)
3766dd7b6ceSThomas Zimmermann 		return;
3776dd7b6ceSThomas Zimmermann 
378f6424ecdSThomas Zimmermann 	drm_gem_fb_vunmap(fb, shadow_plane_state->map);
3796dd7b6ceSThomas Zimmermann }
380359c6649SThomas Zimmermann EXPORT_SYMBOL(drm_gem_end_shadow_fb_access);
3816dd7b6ceSThomas Zimmermann 
3826dd7b6ceSThomas Zimmermann /**
38394d879eaSThomas Zimmermann  * drm_gem_simple_kms_begin_shadow_fb_access - prepares shadow framebuffers for CPU access
3846dd7b6ceSThomas Zimmermann  * @pipe: the simple display pipe
3856dd7b6ceSThomas Zimmermann  * @plane_state: the plane state of type struct drm_shadow_plane_state
3866dd7b6ceSThomas Zimmermann  *
38794d879eaSThomas Zimmermann  * This function implements struct drm_simple_display_funcs.begin_fb_access.
3886dd7b6ceSThomas Zimmermann  *
38994d879eaSThomas Zimmermann  * See drm_gem_begin_shadow_fb_access() for details and
39094d879eaSThomas Zimmermann  * drm_gem_simple_kms_cleanup_shadow_fb() for cleanup.
3916dd7b6ceSThomas Zimmermann  *
3926dd7b6ceSThomas Zimmermann  * Returns:
3936dd7b6ceSThomas Zimmermann  * 0 on success, or a negative errno code otherwise.
3946dd7b6ceSThomas Zimmermann  */
395359c6649SThomas Zimmermann int drm_gem_simple_kms_begin_shadow_fb_access(struct drm_simple_display_pipe *pipe,
3966dd7b6ceSThomas Zimmermann 					      struct drm_plane_state *plane_state)
3976dd7b6ceSThomas Zimmermann {
398359c6649SThomas Zimmermann 	return drm_gem_begin_shadow_fb_access(&pipe->plane, plane_state);
3996dd7b6ceSThomas Zimmermann }
400359c6649SThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_begin_shadow_fb_access);
4016dd7b6ceSThomas Zimmermann 
4026dd7b6ceSThomas Zimmermann /**
40394d879eaSThomas Zimmermann  * drm_gem_simple_kms_end_shadow_fb_access - releases shadow framebuffers from CPU access
4046dd7b6ceSThomas Zimmermann  * @pipe: the simple display pipe
4056dd7b6ceSThomas Zimmermann  * @plane_state: the plane state of type struct drm_shadow_plane_state
4066dd7b6ceSThomas Zimmermann  *
40794d879eaSThomas Zimmermann  * This function implements struct drm_simple_display_funcs.end_fb_access.
40894d879eaSThomas Zimmermann  * It undoes all effects of drm_gem_simple_kms_begin_shadow_fb_access() in
40994d879eaSThomas Zimmermann  * reverse order.
4106dd7b6ceSThomas Zimmermann  *
41194d879eaSThomas Zimmermann  * See drm_gem_simple_kms_begin_shadow_fb_access().
4126dd7b6ceSThomas Zimmermann  */
413359c6649SThomas Zimmermann void drm_gem_simple_kms_end_shadow_fb_access(struct drm_simple_display_pipe *pipe,
4146dd7b6ceSThomas Zimmermann 					     struct drm_plane_state *plane_state)
4156dd7b6ceSThomas Zimmermann {
416359c6649SThomas Zimmermann 	drm_gem_end_shadow_fb_access(&pipe->plane, plane_state);
4176dd7b6ceSThomas Zimmermann }
418359c6649SThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_end_shadow_fb_access);
4196dd7b6ceSThomas Zimmermann 
4206dd7b6ceSThomas Zimmermann /**
4216dd7b6ceSThomas Zimmermann  * drm_gem_simple_kms_reset_shadow_plane - resets a shadow-buffered plane
4226dd7b6ceSThomas Zimmermann  * @pipe: the simple display pipe
4236dd7b6ceSThomas Zimmermann  *
4246dd7b6ceSThomas Zimmermann  * This function implements struct drm_simple_display_funcs.reset_plane
4256dd7b6ceSThomas Zimmermann  * for shadow-buffered planes.
4266dd7b6ceSThomas Zimmermann  */
4276dd7b6ceSThomas Zimmermann void drm_gem_simple_kms_reset_shadow_plane(struct drm_simple_display_pipe *pipe)
4286dd7b6ceSThomas Zimmermann {
4296dd7b6ceSThomas Zimmermann 	drm_gem_reset_shadow_plane(&pipe->plane);
4306dd7b6ceSThomas Zimmermann }
4316dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_reset_shadow_plane);
4326dd7b6ceSThomas Zimmermann 
4336dd7b6ceSThomas Zimmermann /**
4346dd7b6ceSThomas Zimmermann  * drm_gem_simple_kms_duplicate_shadow_plane_state - duplicates shadow-buffered plane state
4356dd7b6ceSThomas Zimmermann  * @pipe: the simple display pipe
4366dd7b6ceSThomas Zimmermann  *
4376dd7b6ceSThomas Zimmermann  * This function implements struct drm_simple_display_funcs.duplicate_plane_state
4386dd7b6ceSThomas Zimmermann  * for shadow-buffered planes. It does not duplicate existing mappings of the shadow
4396dd7b6ceSThomas Zimmermann  * buffers. Mappings are maintained during the atomic commit by the plane's prepare_fb
4406dd7b6ceSThomas Zimmermann  * and cleanup_fb helpers.
4416dd7b6ceSThomas Zimmermann  *
4426dd7b6ceSThomas Zimmermann  * Returns:
4436dd7b6ceSThomas Zimmermann  * A pointer to a new plane state on success, or NULL otherwise.
4446dd7b6ceSThomas Zimmermann  */
4456dd7b6ceSThomas Zimmermann struct drm_plane_state *
4466dd7b6ceSThomas Zimmermann drm_gem_simple_kms_duplicate_shadow_plane_state(struct drm_simple_display_pipe *pipe)
4476dd7b6ceSThomas Zimmermann {
4486dd7b6ceSThomas Zimmermann 	return drm_gem_duplicate_shadow_plane_state(&pipe->plane);
4496dd7b6ceSThomas Zimmermann }
4506dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_duplicate_shadow_plane_state);
4516dd7b6ceSThomas Zimmermann 
4526dd7b6ceSThomas Zimmermann /**
4536dd7b6ceSThomas Zimmermann  * drm_gem_simple_kms_destroy_shadow_plane_state - resets shadow-buffered plane state
4546dd7b6ceSThomas Zimmermann  * @pipe: the simple display pipe
4556dd7b6ceSThomas Zimmermann  * @plane_state: the plane state of type struct drm_shadow_plane_state
4566dd7b6ceSThomas Zimmermann  *
4576dd7b6ceSThomas Zimmermann  * This function implements struct drm_simple_display_funcs.destroy_plane_state
4586dd7b6ceSThomas Zimmermann  * for shadow-buffered planes. It expects that mappings of shadow buffers
4596dd7b6ceSThomas Zimmermann  * have been released already.
4606dd7b6ceSThomas Zimmermann  */
4616dd7b6ceSThomas Zimmermann void drm_gem_simple_kms_destroy_shadow_plane_state(struct drm_simple_display_pipe *pipe,
4626dd7b6ceSThomas Zimmermann 						   struct drm_plane_state *plane_state)
4636dd7b6ceSThomas Zimmermann {
4646dd7b6ceSThomas Zimmermann 	drm_gem_destroy_shadow_plane_state(&pipe->plane, plane_state);
4656dd7b6ceSThomas Zimmermann }
4666dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_destroy_shadow_plane_state);
467