16dd7b6ceSThomas Zimmermann // SPDX-License-Identifier: GPL-2.0-or-later
26dd7b6ceSThomas Zimmermann 
3820c1707SThomas Zimmermann #include <linux/dma-resv.h>
4*1ea28bc5SChristian 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>
8820c1707SThomas Zimmermann #include <drm/drm_gem.h>
96dd7b6ceSThomas Zimmermann #include <drm/drm_gem_atomic_helper.h>
106dd7b6ceSThomas Zimmermann #include <drm/drm_gem_framebuffer_helper.h>
116dd7b6ceSThomas Zimmermann #include <drm/drm_simple_kms_helper.h>
126dd7b6ceSThomas Zimmermann 
136dd7b6ceSThomas Zimmermann #include "drm_internal.h"
146dd7b6ceSThomas Zimmermann 
156dd7b6ceSThomas Zimmermann /**
166dd7b6ceSThomas Zimmermann  * DOC: overview
176dd7b6ceSThomas Zimmermann  *
186dd7b6ceSThomas Zimmermann  * The GEM atomic helpers library implements generic atomic-commit
196dd7b6ceSThomas Zimmermann  * functions for drivers that use GEM objects. Currently, it provides
20820c1707SThomas Zimmermann  * synchronization helpers, and plane state and framebuffer BO mappings
21820c1707SThomas Zimmermann  * for planes with shadow buffers.
22820c1707SThomas Zimmermann  *
23820c1707SThomas Zimmermann  * Before scanout, a plane's framebuffer needs to be synchronized with
24820c1707SThomas Zimmermann  * possible writers that draw into the framebuffer. All drivers should
25820c1707SThomas Zimmermann  * call drm_gem_plane_helper_prepare_fb() from their implementation of
26820c1707SThomas Zimmermann  * struct &drm_plane_helper.prepare_fb . It sets the plane's fence from
27820c1707SThomas Zimmermann  * the framebuffer so that the DRM core can synchronize access automatically.
28820c1707SThomas Zimmermann  *
29820c1707SThomas Zimmermann  * drm_gem_plane_helper_prepare_fb() can also be used directly as
30820c1707SThomas Zimmermann  * implementation of prepare_fb. For drivers based on
31820c1707SThomas Zimmermann  * struct drm_simple_display_pipe, drm_gem_simple_display_pipe_prepare_fb()
32820c1707SThomas Zimmermann  * provides equivalent functionality.
33820c1707SThomas Zimmermann  *
34820c1707SThomas Zimmermann  * .. code-block:: c
35820c1707SThomas Zimmermann  *
36820c1707SThomas Zimmermann  *	#include <drm/drm_gem_atomic_helper.h>
37820c1707SThomas Zimmermann  *
38820c1707SThomas Zimmermann  *	struct drm_plane_helper_funcs driver_plane_helper_funcs = {
39820c1707SThomas Zimmermann  *		...,
40820c1707SThomas Zimmermann  *		. prepare_fb = drm_gem_plane_helper_prepare_fb,
41820c1707SThomas Zimmermann  *	};
42820c1707SThomas Zimmermann  *
43820c1707SThomas Zimmermann  *	struct drm_simple_display_pipe_funcs driver_pipe_funcs = {
44820c1707SThomas Zimmermann  *		...,
45820c1707SThomas Zimmermann  *		. prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
46820c1707SThomas Zimmermann  *	};
479dc9067dSThomas Zimmermann  *
489dc9067dSThomas Zimmermann  * A driver using a shadow buffer copies the content of the shadow buffers
499dc9067dSThomas Zimmermann  * into the HW's framebuffer memory during an atomic update. This requires
509dc9067dSThomas Zimmermann  * a mapping of the shadow buffer into kernel address space. The mappings
519dc9067dSThomas Zimmermann  * cannot be established by commit-tail functions, such as atomic_update,
529dc9067dSThomas Zimmermann  * as this would violate locking rules around dma_buf_vmap().
539dc9067dSThomas Zimmermann  *
549dc9067dSThomas Zimmermann  * The helpers for shadow-buffered planes establish and release mappings,
559dc9067dSThomas Zimmermann  * and provide struct drm_shadow_plane_state, which stores the plane's mapping
560ae865efSCai Huoqing  * for commit-tail functions.
579dc9067dSThomas Zimmermann  *
589dc9067dSThomas Zimmermann  * Shadow-buffered planes can easily be enabled by using the provided macros
599dc9067dSThomas Zimmermann  * %DRM_GEM_SHADOW_PLANE_FUNCS and %DRM_GEM_SHADOW_PLANE_HELPER_FUNCS.
609dc9067dSThomas Zimmermann  * These macros set up the plane and plane-helper callbacks to point to the
619dc9067dSThomas Zimmermann  * shadow-buffer helpers.
629dc9067dSThomas Zimmermann  *
639dc9067dSThomas Zimmermann  * .. code-block:: c
649dc9067dSThomas Zimmermann  *
65820c1707SThomas Zimmermann  *	#include <drm/drm_gem_atomic_helper.h>
669dc9067dSThomas Zimmermann  *
679dc9067dSThomas Zimmermann  *	struct drm_plane_funcs driver_plane_funcs = {
689dc9067dSThomas Zimmermann  *		...,
699dc9067dSThomas Zimmermann  *		DRM_GEM_SHADOW_PLANE_FUNCS,
709dc9067dSThomas Zimmermann  *	};
719dc9067dSThomas Zimmermann  *
729dc9067dSThomas Zimmermann  *	struct drm_plane_helper_funcs driver_plane_helper_funcs = {
739dc9067dSThomas Zimmermann  *		...,
749dc9067dSThomas Zimmermann  *		DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
759dc9067dSThomas Zimmermann  *	};
769dc9067dSThomas Zimmermann  *
779dc9067dSThomas Zimmermann  * In the driver's atomic-update function, shadow-buffer mappings are available
789dc9067dSThomas Zimmermann  * from the plane state. Use to_drm_shadow_plane_state() to upcast from
799dc9067dSThomas Zimmermann  * struct drm_plane_state.
809dc9067dSThomas Zimmermann  *
819dc9067dSThomas Zimmermann  * .. code-block:: c
829dc9067dSThomas Zimmermann  *
839dc9067dSThomas Zimmermann  *	void driver_plane_atomic_update(struct drm_plane *plane,
849dc9067dSThomas Zimmermann  *					struct drm_plane_state *old_plane_state)
859dc9067dSThomas Zimmermann  *	{
869dc9067dSThomas Zimmermann  *		struct drm_plane_state *plane_state = plane->state;
879dc9067dSThomas Zimmermann  *		struct drm_shadow_plane_state *shadow_plane_state =
889dc9067dSThomas Zimmermann  *			to_drm_shadow_plane_state(plane_state);
899dc9067dSThomas Zimmermann  *
909dc9067dSThomas Zimmermann  *		// access shadow buffer via shadow_plane_state->map
919dc9067dSThomas Zimmermann  *	}
929dc9067dSThomas Zimmermann  *
939dc9067dSThomas Zimmermann  * A mapping address for each of the framebuffer's buffer object is stored in
949dc9067dSThomas Zimmermann  * struct &drm_shadow_plane_state.map. The mappings are valid while the state
959dc9067dSThomas Zimmermann  * is being used.
969dc9067dSThomas Zimmermann  *
979dc9067dSThomas Zimmermann  * Drivers that use struct drm_simple_display_pipe can use
989dc9067dSThomas Zimmermann  * %DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS to initialize the rsp
999dc9067dSThomas Zimmermann  * callbacks. Access to shadow-buffer mappings is similar to regular
1009dc9067dSThomas Zimmermann  * atomic_update.
1019dc9067dSThomas Zimmermann  *
1029dc9067dSThomas Zimmermann  * .. code-block:: c
1039dc9067dSThomas Zimmermann  *
1049dc9067dSThomas Zimmermann  *	struct drm_simple_display_pipe_funcs driver_pipe_funcs = {
1059dc9067dSThomas Zimmermann  *		...,
1069dc9067dSThomas Zimmermann  *		DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
1079dc9067dSThomas Zimmermann  *	};
1089dc9067dSThomas Zimmermann  *
1099dc9067dSThomas Zimmermann  *	void driver_pipe_enable(struct drm_simple_display_pipe *pipe,
1109dc9067dSThomas Zimmermann  *				struct drm_crtc_state *crtc_state,
1119dc9067dSThomas Zimmermann  *				struct drm_plane_state *plane_state)
1129dc9067dSThomas Zimmermann  *	{
1139dc9067dSThomas Zimmermann  *		struct drm_shadow_plane_state *shadow_plane_state =
1149dc9067dSThomas Zimmermann  *			to_drm_shadow_plane_state(plane_state);
1159dc9067dSThomas Zimmermann  *
1169dc9067dSThomas Zimmermann  *		// access shadow buffer via shadow_plane_state->map
1179dc9067dSThomas Zimmermann  *	}
1186dd7b6ceSThomas Zimmermann  */
1196dd7b6ceSThomas Zimmermann 
1206dd7b6ceSThomas Zimmermann /*
121820c1707SThomas Zimmermann  * Plane Helpers
122820c1707SThomas Zimmermann  */
123820c1707SThomas Zimmermann 
124820c1707SThomas Zimmermann /**
125820c1707SThomas Zimmermann  * drm_gem_plane_helper_prepare_fb() - Prepare a GEM backed framebuffer
126820c1707SThomas Zimmermann  * @plane: Plane
127820c1707SThomas Zimmermann  * @state: Plane state the fence will be attached to
128820c1707SThomas Zimmermann  *
129820c1707SThomas Zimmermann  * This function extracts the exclusive fence from &drm_gem_object.resv and
130820c1707SThomas Zimmermann  * attaches it to plane state for the atomic helper to wait on. This is
131820c1707SThomas Zimmermann  * necessary to correctly implement implicit synchronization for any buffers
132820c1707SThomas Zimmermann  * shared as a struct &dma_buf. This function can be used as the
133820c1707SThomas Zimmermann  * &drm_plane_helper_funcs.prepare_fb callback.
134820c1707SThomas Zimmermann  *
135820c1707SThomas Zimmermann  * There is no need for &drm_plane_helper_funcs.cleanup_fb hook for simple
136820c1707SThomas Zimmermann  * GEM based framebuffer drivers which have their buffers always pinned in
137820c1707SThomas Zimmermann  * memory.
138820c1707SThomas Zimmermann  *
1397d30963fSDaniel Vetter  * This function is the default implementation for GEM drivers of
1407d30963fSDaniel Vetter  * &drm_plane_helper_funcs.prepare_fb if no callback is provided.
141820c1707SThomas Zimmermann  */
142*1ea28bc5SChristian König int drm_gem_plane_helper_prepare_fb(struct drm_plane *plane,
143*1ea28bc5SChristian König 				    struct drm_plane_state *state)
144820c1707SThomas Zimmermann {
145*1ea28bc5SChristian König 	struct dma_fence *fence = dma_fence_get(state->fence);
146*1ea28bc5SChristian König 	enum dma_resv_usage usage;
147*1ea28bc5SChristian König 	size_t i;
148c382df71SChristian König 	int ret;
149820c1707SThomas Zimmermann 
150820c1707SThomas Zimmermann 	if (!state->fb)
151820c1707SThomas Zimmermann 		return 0;
152820c1707SThomas Zimmermann 
153*1ea28bc5SChristian König 	/*
154*1ea28bc5SChristian König 	 * Only add the kernel fences here if there is already a fence set via
155*1ea28bc5SChristian König 	 * explicit fencing interfaces on the atomic ioctl.
156*1ea28bc5SChristian König 	 *
157*1ea28bc5SChristian König 	 * This way explicit fencing can be used to overrule implicit fencing,
158*1ea28bc5SChristian König 	 * which is important to make explicit fencing use-cases work: One
159*1ea28bc5SChristian König 	 * example is using one buffer for 2 screens with different refresh
160*1ea28bc5SChristian König 	 * rates. Implicit fencing will clamp rendering to the refresh rate of
161*1ea28bc5SChristian König 	 * the slower screen, whereas explicit fence allows 2 independent
162*1ea28bc5SChristian König 	 * render and display loops on a single buffer. If a driver allows
163*1ea28bc5SChristian König 	 * obeys both implicit and explicit fences for plane updates, then it
164*1ea28bc5SChristian König 	 * will break all the benefits of explicit fencing.
165c382df71SChristian König 	 */
166*1ea28bc5SChristian König 	usage = fence ? DMA_RESV_USAGE_KERNEL : DMA_RESV_USAGE_WRITE;
167*1ea28bc5SChristian König 
168*1ea28bc5SChristian König 	for (i = 0; i < state->fb->format->num_planes; ++i) {
169*1ea28bc5SChristian König 		struct drm_gem_object *obj = drm_gem_fb_get_obj(state->fb, i);
170*1ea28bc5SChristian König 		struct dma_fence *new;
171*1ea28bc5SChristian König 
172*1ea28bc5SChristian König 		if (WARN_ON_ONCE(!obj))
173*1ea28bc5SChristian König 			continue;
174*1ea28bc5SChristian König 
175*1ea28bc5SChristian König 		ret = dma_resv_get_singleton(obj->resv, usage, &new);
176*1ea28bc5SChristian König 		if (ret)
177*1ea28bc5SChristian König 			goto error;
178*1ea28bc5SChristian König 
179*1ea28bc5SChristian König 		if (new && fence) {
180*1ea28bc5SChristian König 			struct dma_fence_chain *chain = dma_fence_chain_alloc();
181*1ea28bc5SChristian König 
182*1ea28bc5SChristian König 			if (!chain) {
183*1ea28bc5SChristian König 				ret = -ENOMEM;
184*1ea28bc5SChristian König 				goto error;
185*1ea28bc5SChristian König 			}
186*1ea28bc5SChristian König 
187*1ea28bc5SChristian König 			dma_fence_chain_init(chain, fence, new, 1);
188*1ea28bc5SChristian König 			fence = &chain->base;
189*1ea28bc5SChristian König 
190*1ea28bc5SChristian König 		} else if (new) {
191*1ea28bc5SChristian König 			fence = new;
192*1ea28bc5SChristian König 		}
193*1ea28bc5SChristian König 	}
194*1ea28bc5SChristian König 
195*1ea28bc5SChristian König 	dma_fence_put(state->fence);
196*1ea28bc5SChristian König 	state->fence = fence;
197820c1707SThomas Zimmermann 	return 0;
198*1ea28bc5SChristian König 
199*1ea28bc5SChristian König error:
200*1ea28bc5SChristian König 	dma_fence_put(fence);
201*1ea28bc5SChristian König 	return ret;
202820c1707SThomas Zimmermann }
203820c1707SThomas Zimmermann EXPORT_SYMBOL_GPL(drm_gem_plane_helper_prepare_fb);
204820c1707SThomas Zimmermann 
205820c1707SThomas Zimmermann /**
206820c1707SThomas Zimmermann  * drm_gem_simple_display_pipe_prepare_fb - prepare_fb helper for &drm_simple_display_pipe
207820c1707SThomas Zimmermann  * @pipe: Simple display pipe
208820c1707SThomas Zimmermann  * @plane_state: Plane state
209820c1707SThomas Zimmermann  *
210*1ea28bc5SChristian König  * This function uses drm_gem_plane_helper_prepare_fb() to extract the fences
211*1ea28bc5SChristian König  * from &drm_gem_object.resv and attaches them to the plane state for the atomic
212820c1707SThomas Zimmermann  * helper to wait on. This is necessary to correctly implement implicit
213820c1707SThomas Zimmermann  * synchronization for any buffers shared as a struct &dma_buf. Drivers can use
214820c1707SThomas Zimmermann  * this as their &drm_simple_display_pipe_funcs.prepare_fb callback.
215820c1707SThomas Zimmermann  *
216*1ea28bc5SChristian König  * See drm_gem_plane_helper_prepare_fb() for a discussion of implicit and
217820c1707SThomas Zimmermann  * explicit fencing in atomic modeset updates.
218820c1707SThomas Zimmermann  */
219820c1707SThomas Zimmermann int drm_gem_simple_display_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,
220820c1707SThomas Zimmermann 					   struct drm_plane_state *plane_state)
221820c1707SThomas Zimmermann {
222820c1707SThomas Zimmermann 	return drm_gem_plane_helper_prepare_fb(&pipe->plane, plane_state);
223820c1707SThomas Zimmermann }
224820c1707SThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_display_pipe_prepare_fb);
225820c1707SThomas Zimmermann 
226820c1707SThomas Zimmermann /*
2276dd7b6ceSThomas Zimmermann  * Shadow-buffered Planes
2286dd7b6ceSThomas Zimmermann  */
2296dd7b6ceSThomas Zimmermann 
2309dc9067dSThomas Zimmermann /**
231b7156502SThomas Zimmermann  * __drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state
232b7156502SThomas Zimmermann  * @plane: the plane
233b7156502SThomas Zimmermann  * @new_shadow_plane_state: the new shadow-buffered plane state
234b7156502SThomas Zimmermann  *
235b7156502SThomas Zimmermann  * This function duplicates shadow-buffered plane state. This is helpful for drivers
236b7156502SThomas Zimmermann  * that subclass struct drm_shadow_plane_state.
237b7156502SThomas Zimmermann  *
238b7156502SThomas Zimmermann  * The function does not duplicate existing mappings of the shadow buffers.
239b7156502SThomas Zimmermann  * Mappings are maintained during the atomic commit by the plane's prepare_fb
240b7156502SThomas Zimmermann  * and cleanup_fb helpers. See drm_gem_prepare_shadow_fb() and drm_gem_cleanup_shadow_fb()
241b7156502SThomas Zimmermann  * for corresponding helpers.
242b7156502SThomas Zimmermann  */
243b7156502SThomas Zimmermann void
244b7156502SThomas Zimmermann __drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane,
245b7156502SThomas Zimmermann 				       struct drm_shadow_plane_state *new_shadow_plane_state)
246b7156502SThomas Zimmermann {
247b7156502SThomas Zimmermann 	__drm_atomic_helper_plane_duplicate_state(plane, &new_shadow_plane_state->base);
248b7156502SThomas Zimmermann }
249b7156502SThomas Zimmermann EXPORT_SYMBOL(__drm_gem_duplicate_shadow_plane_state);
250b7156502SThomas Zimmermann 
251b7156502SThomas Zimmermann /**
2529dc9067dSThomas Zimmermann  * drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state
2539dc9067dSThomas Zimmermann  * @plane: the plane
2549dc9067dSThomas Zimmermann  *
2559dc9067dSThomas Zimmermann  * This function implements struct &drm_plane_funcs.atomic_duplicate_state for
2569dc9067dSThomas Zimmermann  * shadow-buffered planes. It assumes the existing state to be of type
2579dc9067dSThomas Zimmermann  * struct drm_shadow_plane_state and it allocates the new state to be of this
2589dc9067dSThomas Zimmermann  * type.
2599dc9067dSThomas Zimmermann  *
2609dc9067dSThomas Zimmermann  * The function does not duplicate existing mappings of the shadow buffers.
2619dc9067dSThomas Zimmermann  * Mappings are maintained during the atomic commit by the plane's prepare_fb
2629dc9067dSThomas Zimmermann  * and cleanup_fb helpers. See drm_gem_prepare_shadow_fb() and drm_gem_cleanup_shadow_fb()
2639dc9067dSThomas Zimmermann  * for corresponding helpers.
2649dc9067dSThomas Zimmermann  *
2659dc9067dSThomas Zimmermann  * Returns:
2669dc9067dSThomas Zimmermann  * A pointer to a new plane state on success, or NULL otherwise.
2679dc9067dSThomas Zimmermann  */
2689dc9067dSThomas Zimmermann struct drm_plane_state *
2696dd7b6ceSThomas Zimmermann drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane)
2706dd7b6ceSThomas Zimmermann {
2716dd7b6ceSThomas Zimmermann 	struct drm_plane_state *plane_state = plane->state;
2726dd7b6ceSThomas Zimmermann 	struct drm_shadow_plane_state *new_shadow_plane_state;
2736dd7b6ceSThomas Zimmermann 
2746dd7b6ceSThomas Zimmermann 	if (!plane_state)
2756dd7b6ceSThomas Zimmermann 		return NULL;
2766dd7b6ceSThomas Zimmermann 
2776dd7b6ceSThomas Zimmermann 	new_shadow_plane_state = kzalloc(sizeof(*new_shadow_plane_state), GFP_KERNEL);
2786dd7b6ceSThomas Zimmermann 	if (!new_shadow_plane_state)
2796dd7b6ceSThomas Zimmermann 		return NULL;
280b7156502SThomas Zimmermann 	__drm_gem_duplicate_shadow_plane_state(plane, new_shadow_plane_state);
2816dd7b6ceSThomas Zimmermann 
2826dd7b6ceSThomas Zimmermann 	return &new_shadow_plane_state->base;
2836dd7b6ceSThomas Zimmermann }
2849dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_duplicate_shadow_plane_state);
2856dd7b6ceSThomas Zimmermann 
2869dc9067dSThomas Zimmermann /**
287b7156502SThomas Zimmermann  * __drm_gem_destroy_shadow_plane_state - cleans up shadow-buffered plane state
288b7156502SThomas Zimmermann  * @shadow_plane_state: the shadow-buffered plane state
289b7156502SThomas Zimmermann  *
290b7156502SThomas Zimmermann  * This function cleans up shadow-buffered plane state. Helpful for drivers that
291b7156502SThomas Zimmermann  * subclass struct drm_shadow_plane_state.
292b7156502SThomas Zimmermann  */
293b7156502SThomas Zimmermann void __drm_gem_destroy_shadow_plane_state(struct drm_shadow_plane_state *shadow_plane_state)
294b7156502SThomas Zimmermann {
295b7156502SThomas Zimmermann 	__drm_atomic_helper_plane_destroy_state(&shadow_plane_state->base);
296b7156502SThomas Zimmermann }
297b7156502SThomas Zimmermann EXPORT_SYMBOL(__drm_gem_destroy_shadow_plane_state);
298b7156502SThomas Zimmermann 
299b7156502SThomas Zimmermann /**
3009dc9067dSThomas Zimmermann  * drm_gem_destroy_shadow_plane_state - deletes shadow-buffered plane state
3019dc9067dSThomas Zimmermann  * @plane: the plane
3029dc9067dSThomas Zimmermann  * @plane_state: the plane state of type struct drm_shadow_plane_state
3039dc9067dSThomas Zimmermann  *
3049dc9067dSThomas Zimmermann  * This function implements struct &drm_plane_funcs.atomic_destroy_state
3059dc9067dSThomas Zimmermann  * for shadow-buffered planes. It expects that mappings of shadow buffers
3069dc9067dSThomas Zimmermann  * have been released already.
3079dc9067dSThomas Zimmermann  */
3089dc9067dSThomas Zimmermann void drm_gem_destroy_shadow_plane_state(struct drm_plane *plane,
3096dd7b6ceSThomas Zimmermann 					struct drm_plane_state *plane_state)
3106dd7b6ceSThomas Zimmermann {
3116dd7b6ceSThomas Zimmermann 	struct drm_shadow_plane_state *shadow_plane_state =
3126dd7b6ceSThomas Zimmermann 		to_drm_shadow_plane_state(plane_state);
3136dd7b6ceSThomas Zimmermann 
314b7156502SThomas Zimmermann 	__drm_gem_destroy_shadow_plane_state(shadow_plane_state);
3156dd7b6ceSThomas Zimmermann 	kfree(shadow_plane_state);
3166dd7b6ceSThomas Zimmermann }
3179dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_destroy_shadow_plane_state);
3186dd7b6ceSThomas Zimmermann 
3199dc9067dSThomas Zimmermann /**
320b7156502SThomas Zimmermann  * __drm_gem_reset_shadow_plane - resets a shadow-buffered plane
321b7156502SThomas Zimmermann  * @plane: the plane
322b7156502SThomas Zimmermann  * @shadow_plane_state: the shadow-buffered plane state
323b7156502SThomas Zimmermann  *
324b7156502SThomas Zimmermann  * This function resets state for shadow-buffered planes. Helpful
325b7156502SThomas Zimmermann  * for drivers that subclass struct drm_shadow_plane_state.
326b7156502SThomas Zimmermann  */
327b7156502SThomas Zimmermann void __drm_gem_reset_shadow_plane(struct drm_plane *plane,
328b7156502SThomas Zimmermann 				  struct drm_shadow_plane_state *shadow_plane_state)
329b7156502SThomas Zimmermann {
330b7156502SThomas Zimmermann 	__drm_atomic_helper_plane_reset(plane, &shadow_plane_state->base);
331b7156502SThomas Zimmermann }
332b7156502SThomas Zimmermann EXPORT_SYMBOL(__drm_gem_reset_shadow_plane);
333b7156502SThomas Zimmermann 
334b7156502SThomas Zimmermann /**
3359dc9067dSThomas Zimmermann  * drm_gem_reset_shadow_plane - resets a shadow-buffered plane
3369dc9067dSThomas Zimmermann  * @plane: the plane
3379dc9067dSThomas Zimmermann  *
3389dc9067dSThomas Zimmermann  * This function implements struct &drm_plane_funcs.reset_plane for
3399dc9067dSThomas Zimmermann  * shadow-buffered planes. It assumes the current plane state to be
3409dc9067dSThomas Zimmermann  * of type struct drm_shadow_plane and it allocates the new state of
3419dc9067dSThomas Zimmermann  * this type.
3429dc9067dSThomas Zimmermann  */
3439dc9067dSThomas Zimmermann void drm_gem_reset_shadow_plane(struct drm_plane *plane)
3446dd7b6ceSThomas Zimmermann {
3456dd7b6ceSThomas Zimmermann 	struct drm_shadow_plane_state *shadow_plane_state;
3466dd7b6ceSThomas Zimmermann 
3476dd7b6ceSThomas Zimmermann 	if (plane->state) {
3486dd7b6ceSThomas Zimmermann 		drm_gem_destroy_shadow_plane_state(plane, plane->state);
3496dd7b6ceSThomas Zimmermann 		plane->state = NULL; /* must be set to NULL here */
3506dd7b6ceSThomas Zimmermann 	}
3516dd7b6ceSThomas Zimmermann 
3526dd7b6ceSThomas Zimmermann 	shadow_plane_state = kzalloc(sizeof(*shadow_plane_state), GFP_KERNEL);
3536dd7b6ceSThomas Zimmermann 	if (!shadow_plane_state)
3546dd7b6ceSThomas Zimmermann 		return;
355b7156502SThomas Zimmermann 	__drm_gem_reset_shadow_plane(plane, shadow_plane_state);
3566dd7b6ceSThomas Zimmermann }
3579dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_reset_shadow_plane);
3586dd7b6ceSThomas Zimmermann 
3599dc9067dSThomas Zimmermann /**
3609dc9067dSThomas Zimmermann  * drm_gem_prepare_shadow_fb - prepares shadow framebuffers
3619dc9067dSThomas Zimmermann  * @plane: the plane
3629dc9067dSThomas Zimmermann  * @plane_state: the plane state of type struct drm_shadow_plane_state
3639dc9067dSThomas Zimmermann  *
3649dc9067dSThomas Zimmermann  * This function implements struct &drm_plane_helper_funcs.prepare_fb. It
3659dc9067dSThomas Zimmermann  * maps all buffer objects of the plane's framebuffer into kernel address
3669dc9067dSThomas Zimmermann  * space and stores them in &struct drm_shadow_plane_state.map. The
3679dc9067dSThomas Zimmermann  * framebuffer will be synchronized as part of the atomic commit.
3689dc9067dSThomas Zimmermann  *
3699dc9067dSThomas Zimmermann  * See drm_gem_cleanup_shadow_fb() for cleanup.
3709dc9067dSThomas Zimmermann  *
3719dc9067dSThomas Zimmermann  * Returns:
3729dc9067dSThomas Zimmermann  * 0 on success, or a negative errno code otherwise.
3739dc9067dSThomas Zimmermann  */
3749dc9067dSThomas Zimmermann int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state)
3756dd7b6ceSThomas Zimmermann {
3766dd7b6ceSThomas Zimmermann 	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
3776dd7b6ceSThomas Zimmermann 	struct drm_framebuffer *fb = plane_state->fb;
3786dd7b6ceSThomas Zimmermann 	int ret;
3796dd7b6ceSThomas Zimmermann 
3806dd7b6ceSThomas Zimmermann 	if (!fb)
3816dd7b6ceSThomas Zimmermann 		return 0;
3826dd7b6ceSThomas Zimmermann 
383820c1707SThomas Zimmermann 	ret = drm_gem_plane_helper_prepare_fb(plane, plane_state);
3846dd7b6ceSThomas Zimmermann 	if (ret)
3856dd7b6ceSThomas Zimmermann 		return ret;
3866dd7b6ceSThomas Zimmermann 
38743b36232SThomas Zimmermann 	return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data);
3886dd7b6ceSThomas Zimmermann }
3899dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_prepare_shadow_fb);
3906dd7b6ceSThomas Zimmermann 
3919dc9067dSThomas Zimmermann /**
3929dc9067dSThomas Zimmermann  * drm_gem_cleanup_shadow_fb - releases shadow framebuffers
3939dc9067dSThomas Zimmermann  * @plane: the plane
3949dc9067dSThomas Zimmermann  * @plane_state: the plane state of type struct drm_shadow_plane_state
3959dc9067dSThomas Zimmermann  *
3969dc9067dSThomas Zimmermann  * This function implements struct &drm_plane_helper_funcs.cleanup_fb.
3979dc9067dSThomas Zimmermann  * This function unmaps all buffer objects of the plane's framebuffer.
3989dc9067dSThomas Zimmermann  *
3990ae865efSCai Huoqing  * See drm_gem_prepare_shadow_fb() for more information.
4009dc9067dSThomas Zimmermann  */
4019dc9067dSThomas Zimmermann void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state)
4026dd7b6ceSThomas Zimmermann {
4036dd7b6ceSThomas Zimmermann 	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
4046dd7b6ceSThomas Zimmermann 	struct drm_framebuffer *fb = plane_state->fb;
4056dd7b6ceSThomas Zimmermann 
4066dd7b6ceSThomas Zimmermann 	if (!fb)
4076dd7b6ceSThomas Zimmermann 		return;
4086dd7b6ceSThomas Zimmermann 
409f6424ecdSThomas Zimmermann 	drm_gem_fb_vunmap(fb, shadow_plane_state->map);
4106dd7b6ceSThomas Zimmermann }
4119dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_cleanup_shadow_fb);
4126dd7b6ceSThomas Zimmermann 
4136dd7b6ceSThomas Zimmermann /**
4146dd7b6ceSThomas Zimmermann  * drm_gem_simple_kms_prepare_shadow_fb - prepares shadow framebuffers
4156dd7b6ceSThomas Zimmermann  * @pipe: the simple display pipe
4166dd7b6ceSThomas Zimmermann  * @plane_state: the plane state of type struct drm_shadow_plane_state
4176dd7b6ceSThomas Zimmermann  *
4186dd7b6ceSThomas Zimmermann  * This function implements struct drm_simple_display_funcs.prepare_fb. It
4196dd7b6ceSThomas Zimmermann  * maps all buffer objects of the plane's framebuffer into kernel address
4206dd7b6ceSThomas Zimmermann  * space and stores them in struct drm_shadow_plane_state.map. The
4216dd7b6ceSThomas Zimmermann  * framebuffer will be synchronized as part of the atomic commit.
4226dd7b6ceSThomas Zimmermann  *
4236dd7b6ceSThomas Zimmermann  * See drm_gem_simple_kms_cleanup_shadow_fb() for cleanup.
4246dd7b6ceSThomas Zimmermann  *
4256dd7b6ceSThomas Zimmermann  * Returns:
4266dd7b6ceSThomas Zimmermann  * 0 on success, or a negative errno code otherwise.
4276dd7b6ceSThomas Zimmermann  */
4286dd7b6ceSThomas Zimmermann int drm_gem_simple_kms_prepare_shadow_fb(struct drm_simple_display_pipe *pipe,
4296dd7b6ceSThomas Zimmermann 					 struct drm_plane_state *plane_state)
4306dd7b6ceSThomas Zimmermann {
4316dd7b6ceSThomas Zimmermann 	return drm_gem_prepare_shadow_fb(&pipe->plane, plane_state);
4326dd7b6ceSThomas Zimmermann }
4336dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_prepare_shadow_fb);
4346dd7b6ceSThomas Zimmermann 
4356dd7b6ceSThomas Zimmermann /**
4366dd7b6ceSThomas Zimmermann  * drm_gem_simple_kms_cleanup_shadow_fb - releases shadow framebuffers
4376dd7b6ceSThomas Zimmermann  * @pipe: the simple display pipe
4386dd7b6ceSThomas Zimmermann  * @plane_state: the plane state of type struct drm_shadow_plane_state
4396dd7b6ceSThomas Zimmermann  *
4406dd7b6ceSThomas Zimmermann  * This function implements struct drm_simple_display_funcs.cleanup_fb.
4416dd7b6ceSThomas Zimmermann  * This function unmaps all buffer objects of the plane's framebuffer.
4426dd7b6ceSThomas Zimmermann  *
4436dd7b6ceSThomas Zimmermann  * See drm_gem_simple_kms_prepare_shadow_fb().
4446dd7b6ceSThomas Zimmermann  */
4456dd7b6ceSThomas Zimmermann void drm_gem_simple_kms_cleanup_shadow_fb(struct drm_simple_display_pipe *pipe,
4466dd7b6ceSThomas Zimmermann 					  struct drm_plane_state *plane_state)
4476dd7b6ceSThomas Zimmermann {
4486dd7b6ceSThomas Zimmermann 	drm_gem_cleanup_shadow_fb(&pipe->plane, plane_state);
4496dd7b6ceSThomas Zimmermann }
4506dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_cleanup_shadow_fb);
4516dd7b6ceSThomas Zimmermann 
4526dd7b6ceSThomas Zimmermann /**
4536dd7b6ceSThomas Zimmermann  * drm_gem_simple_kms_reset_shadow_plane - resets a shadow-buffered plane
4546dd7b6ceSThomas Zimmermann  * @pipe: the simple display pipe
4556dd7b6ceSThomas Zimmermann  *
4566dd7b6ceSThomas Zimmermann  * This function implements struct drm_simple_display_funcs.reset_plane
4576dd7b6ceSThomas Zimmermann  * for shadow-buffered planes.
4586dd7b6ceSThomas Zimmermann  */
4596dd7b6ceSThomas Zimmermann void drm_gem_simple_kms_reset_shadow_plane(struct drm_simple_display_pipe *pipe)
4606dd7b6ceSThomas Zimmermann {
4616dd7b6ceSThomas Zimmermann 	drm_gem_reset_shadow_plane(&pipe->plane);
4626dd7b6ceSThomas Zimmermann }
4636dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_reset_shadow_plane);
4646dd7b6ceSThomas Zimmermann 
4656dd7b6ceSThomas Zimmermann /**
4666dd7b6ceSThomas Zimmermann  * drm_gem_simple_kms_duplicate_shadow_plane_state - duplicates shadow-buffered plane state
4676dd7b6ceSThomas Zimmermann  * @pipe: the simple display pipe
4686dd7b6ceSThomas Zimmermann  *
4696dd7b6ceSThomas Zimmermann  * This function implements struct drm_simple_display_funcs.duplicate_plane_state
4706dd7b6ceSThomas Zimmermann  * for shadow-buffered planes. It does not duplicate existing mappings of the shadow
4716dd7b6ceSThomas Zimmermann  * buffers. Mappings are maintained during the atomic commit by the plane's prepare_fb
4726dd7b6ceSThomas Zimmermann  * and cleanup_fb helpers.
4736dd7b6ceSThomas Zimmermann  *
4746dd7b6ceSThomas Zimmermann  * Returns:
4756dd7b6ceSThomas Zimmermann  * A pointer to a new plane state on success, or NULL otherwise.
4766dd7b6ceSThomas Zimmermann  */
4776dd7b6ceSThomas Zimmermann struct drm_plane_state *
4786dd7b6ceSThomas Zimmermann drm_gem_simple_kms_duplicate_shadow_plane_state(struct drm_simple_display_pipe *pipe)
4796dd7b6ceSThomas Zimmermann {
4806dd7b6ceSThomas Zimmermann 	return drm_gem_duplicate_shadow_plane_state(&pipe->plane);
4816dd7b6ceSThomas Zimmermann }
4826dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_duplicate_shadow_plane_state);
4836dd7b6ceSThomas Zimmermann 
4846dd7b6ceSThomas Zimmermann /**
4856dd7b6ceSThomas Zimmermann  * drm_gem_simple_kms_destroy_shadow_plane_state - resets shadow-buffered plane state
4866dd7b6ceSThomas Zimmermann  * @pipe: the simple display pipe
4876dd7b6ceSThomas Zimmermann  * @plane_state: the plane state of type struct drm_shadow_plane_state
4886dd7b6ceSThomas Zimmermann  *
4896dd7b6ceSThomas Zimmermann  * This function implements struct drm_simple_display_funcs.destroy_plane_state
4906dd7b6ceSThomas Zimmermann  * for shadow-buffered planes. It expects that mappings of shadow buffers
4916dd7b6ceSThomas Zimmermann  * have been released already.
4926dd7b6ceSThomas Zimmermann  */
4936dd7b6ceSThomas Zimmermann void drm_gem_simple_kms_destroy_shadow_plane_state(struct drm_simple_display_pipe *pipe,
4946dd7b6ceSThomas Zimmermann 						   struct drm_plane_state *plane_state)
4956dd7b6ceSThomas Zimmermann {
4966dd7b6ceSThomas Zimmermann 	drm_gem_destroy_shadow_plane_state(&pipe->plane, plane_state);
4976dd7b6ceSThomas Zimmermann }
4986dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_destroy_shadow_plane_state);
499