xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/drm_plane.c (revision ae4f76b16e7bcc419560eb3f4478c3a2077dc939)
1 /*	$NetBSD: drm_plane.c,v 1.4 2021/12/19 01:13:52 riastradh Exp $	*/
2 
3 /*
4  * Copyright (c) 2016 Intel Corporation
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that copyright
9  * notice and this permission notice appear in supporting documentation, and
10  * that the name of the copyright holders not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  The copyright holders make no representations
13  * about the suitability of this software for any purpose.  It is provided "as
14  * is" without express or implied warranty.
15  *
16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22  * OF THIS SOFTWARE.
23  */
24 
25 #include <sys/cdefs.h>
26 __KERNEL_RCSID(0, "$NetBSD: drm_plane.c,v 1.4 2021/12/19 01:13:52 riastradh Exp $");
27 
28 #include <linux/slab.h>
29 #include <linux/uaccess.h>
30 
31 #include <drm/drm_plane.h>
32 #include <drm/drm_drv.h>
33 #include <drm/drm_print.h>
34 #include <drm/drm_framebuffer.h>
35 #include <drm/drm_file.h>
36 #include <drm/drm_crtc.h>
37 #include <drm/drm_fourcc.h>
38 #include <drm/drm_vblank.h>
39 
40 #include "drm_crtc_internal.h"
41 
42 /**
43  * DOC: overview
44  *
45  * A plane represents an image source that can be blended with or overlayed on
46  * top of a CRTC during the scanout process. Planes take their input data from a
47  * &drm_framebuffer object. The plane itself specifies the cropping and scaling
48  * of that image, and where it is placed on the visible are of a display
49  * pipeline, represented by &drm_crtc. A plane can also have additional
50  * properties that specify how the pixels are positioned and blended, like
51  * rotation or Z-position. All these properties are stored in &drm_plane_state.
52  *
53  * To create a plane, a KMS drivers allocates and zeroes an instances of
54  * &struct drm_plane (possibly as part of a larger structure) and registers it
55  * with a call to drm_universal_plane_init().
56  *
57  * Cursor and overlay planes are optional. All drivers should provide one
58  * primary plane per CRTC to avoid surprising userspace too much. See enum
59  * drm_plane_type for a more in-depth discussion of these special uapi-relevant
60  * plane types. Special planes are associated with their CRTC by calling
61  * drm_crtc_init_with_planes().
62  *
63  * The type of a plane is exposed in the immutable "type" enumeration property,
64  * which has one of the following values: "Overlay", "Primary", "Cursor".
65  */
66 
drm_num_planes(struct drm_device * dev)67 static unsigned int drm_num_planes(struct drm_device *dev)
68 {
69 	unsigned int num = 0;
70 	struct drm_plane *tmp;
71 
72 	drm_for_each_plane(tmp, dev) {
73 		num++;
74 	}
75 
76 	return num;
77 }
78 
79 static inline u32 *
formats_ptr(struct drm_format_modifier_blob * blob)80 formats_ptr(struct drm_format_modifier_blob *blob)
81 {
82 	return (u32 *)(((char *)blob) + blob->formats_offset);
83 }
84 
85 static inline struct drm_format_modifier *
modifiers_ptr(struct drm_format_modifier_blob * blob)86 modifiers_ptr(struct drm_format_modifier_blob *blob)
87 {
88 	return (struct drm_format_modifier *)(((char *)blob) + blob->modifiers_offset);
89 }
90 
create_in_format_blob(struct drm_device * dev,struct drm_plane * plane)91 static int create_in_format_blob(struct drm_device *dev, struct drm_plane *plane)
92 {
93 	const struct drm_mode_config *config = &dev->mode_config;
94 	struct drm_property_blob *blob;
95 	struct drm_format_modifier *mod;
96 	size_t blob_size, formats_size, modifiers_size;
97 	struct drm_format_modifier_blob *blob_data;
98 	unsigned int i, j;
99 
100 	formats_size = sizeof(__u32) * plane->format_count;
101 	if (WARN_ON(!formats_size)) {
102 		/* 0 formats are never expected */
103 		return 0;
104 	}
105 
106 	modifiers_size =
107 		sizeof(struct drm_format_modifier) * plane->modifier_count;
108 
109 	blob_size = sizeof(struct drm_format_modifier_blob);
110 	/* Modifiers offset is a pointer to a struct with a 64 bit field so it
111 	 * should be naturally aligned to 8B.
112 	 */
113 	BUILD_BUG_ON(sizeof(struct drm_format_modifier_blob) % 8);
114 	blob_size += round_up(formats_size, 8);
115 	blob_size += modifiers_size;
116 
117 	blob = drm_property_create_blob(dev, blob_size, NULL);
118 	if (IS_ERR(blob))
119 		return -1;
120 
121 	blob_data = blob->data;
122 	blob_data->version = FORMAT_BLOB_CURRENT;
123 	blob_data->count_formats = plane->format_count;
124 	blob_data->formats_offset = sizeof(struct drm_format_modifier_blob);
125 	blob_data->count_modifiers = plane->modifier_count;
126 
127 	blob_data->modifiers_offset =
128 		round_up(blob_data->formats_offset + formats_size, 8);
129 
130 	memcpy(formats_ptr(blob_data), plane->format_types, formats_size);
131 
132 	/* If we can't determine support, just bail */
133 	if (!plane->funcs->format_mod_supported)
134 		goto done;
135 
136 	mod = modifiers_ptr(blob_data);
137 	for (i = 0; i < plane->modifier_count; i++) {
138 		for (j = 0; j < plane->format_count; j++) {
139 			if (plane->funcs->format_mod_supported(plane,
140 							       plane->format_types[j],
141 							       plane->modifiers[i])) {
142 
143 				mod->formats |= 1ULL << j;
144 			}
145 		}
146 
147 		mod->modifier = plane->modifiers[i];
148 		mod->offset = 0;
149 		mod->pad = 0;
150 		mod++;
151 	}
152 
153 done:
154 	drm_object_attach_property(&plane->base, config->modifiers_property,
155 				   blob->base.id);
156 
157 	return 0;
158 }
159 
160 /**
161  * drm_universal_plane_init - Initialize a new universal plane object
162  * @dev: DRM device
163  * @plane: plane object to init
164  * @possible_crtcs: bitmask of possible CRTCs
165  * @funcs: callbacks for the new plane
166  * @formats: array of supported formats (DRM_FORMAT\_\*)
167  * @format_count: number of elements in @formats
168  * @format_modifiers: array of struct drm_format modifiers terminated by
169  *                    DRM_FORMAT_MOD_INVALID
170  * @type: type of plane (overlay, primary, cursor)
171  * @name: printf style format string for the plane name, or NULL for default name
172  *
173  * Initializes a plane object of type @type.
174  *
175  * Returns:
176  * Zero on success, error code on failure.
177  */
drm_universal_plane_init(struct drm_device * dev,struct drm_plane * plane,uint32_t possible_crtcs,const struct drm_plane_funcs * funcs,const uint32_t * formats,unsigned int format_count,const uint64_t * format_modifiers,enum drm_plane_type type,const char * name,...)178 int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
179 			     uint32_t possible_crtcs,
180 			     const struct drm_plane_funcs *funcs,
181 			     const uint32_t *formats, unsigned int format_count,
182 			     const uint64_t *format_modifiers,
183 			     enum drm_plane_type type,
184 			     const char *name, ...)
185 {
186 	struct drm_mode_config *config = &dev->mode_config;
187 	unsigned int format_modifier_count = 0;
188 	int ret;
189 
190 	/* plane index is used with 32bit bitmasks */
191 	if (WARN_ON(config->num_total_plane >= 32))
192 		return -EINVAL;
193 
194 	WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
195 		(!funcs->atomic_destroy_state ||
196 		 !funcs->atomic_duplicate_state));
197 
198 	ret = drm_mode_object_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
199 	if (ret)
200 		return ret;
201 
202 	drm_modeset_lock_init(&plane->mutex);
203 
204 	plane->base.properties = &plane->properties;
205 	plane->dev = dev;
206 	plane->funcs = funcs;
207 	plane->format_types = kmalloc_array(format_count, sizeof(uint32_t),
208 					    GFP_KERNEL);
209 	if (!plane->format_types) {
210 		DRM_DEBUG_KMS("out of memory when allocating plane\n");
211 		drm_mode_object_unregister(dev, &plane->base);
212 		return -ENOMEM;
213 	}
214 
215 	/*
216 	 * First driver to need more than 64 formats needs to fix this. Each
217 	 * format is encoded as a bit and the current code only supports a u64.
218 	 */
219 	if (WARN_ON(format_count > 64))
220 		return -EINVAL;
221 
222 	if (format_modifiers) {
223 		const uint64_t *temp_modifiers = format_modifiers;
224 		while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
225 			format_modifier_count++;
226 	}
227 
228 	if (format_modifier_count)
229 		config->allow_fb_modifiers = true;
230 
231 	plane->modifier_count = format_modifier_count;
232 	plane->modifiers = kmalloc_array(format_modifier_count,
233 					 sizeof(format_modifiers[0]),
234 					 GFP_KERNEL);
235 
236 	if (format_modifier_count && !plane->modifiers) {
237 		DRM_DEBUG_KMS("out of memory when allocating plane\n");
238 		kfree(plane->format_types);
239 		drm_mode_object_unregister(dev, &plane->base);
240 		return -ENOMEM;
241 	}
242 
243 	if (name) {
244 		va_list ap;
245 
246 		va_start(ap, name);
247 		plane->name = kvasprintf(GFP_KERNEL, name, ap);
248 		va_end(ap);
249 	} else {
250 		plane->name = kasprintf(GFP_KERNEL, "plane-%d",
251 					drm_num_planes(dev));
252 	}
253 	if (!plane->name) {
254 		kfree(plane->format_types);
255 		kfree(plane->modifiers);
256 		drm_mode_object_unregister(dev, &plane->base);
257 		return -ENOMEM;
258 	}
259 
260 	memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
261 	plane->format_count = format_count;
262 	memcpy(plane->modifiers, format_modifiers,
263 	       format_modifier_count * sizeof(format_modifiers[0]));
264 	plane->possible_crtcs = possible_crtcs;
265 	plane->type = type;
266 
267 	list_add_tail(&plane->head, &config->plane_list);
268 	plane->index = config->num_total_plane++;
269 
270 	drm_object_attach_property(&plane->base,
271 				   config->plane_type_property,
272 				   plane->type);
273 
274 	if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
275 		drm_object_attach_property(&plane->base, config->prop_fb_id, 0);
276 		drm_object_attach_property(&plane->base, config->prop_in_fence_fd, -1);
277 		drm_object_attach_property(&plane->base, config->prop_crtc_id, 0);
278 		drm_object_attach_property(&plane->base, config->prop_crtc_x, 0);
279 		drm_object_attach_property(&plane->base, config->prop_crtc_y, 0);
280 		drm_object_attach_property(&plane->base, config->prop_crtc_w, 0);
281 		drm_object_attach_property(&plane->base, config->prop_crtc_h, 0);
282 		drm_object_attach_property(&plane->base, config->prop_src_x, 0);
283 		drm_object_attach_property(&plane->base, config->prop_src_y, 0);
284 		drm_object_attach_property(&plane->base, config->prop_src_w, 0);
285 		drm_object_attach_property(&plane->base, config->prop_src_h, 0);
286 	}
287 
288 	if (config->allow_fb_modifiers)
289 		create_in_format_blob(dev, plane);
290 
291 	return 0;
292 }
293 EXPORT_SYMBOL(drm_universal_plane_init);
294 
drm_plane_register_all(struct drm_device * dev)295 int drm_plane_register_all(struct drm_device *dev)
296 {
297 	struct drm_plane *plane;
298 	int ret = 0;
299 
300 	drm_for_each_plane(plane, dev) {
301 		if (plane->funcs->late_register)
302 			ret = plane->funcs->late_register(plane);
303 		if (ret)
304 			return ret;
305 	}
306 
307 	return 0;
308 }
309 
drm_plane_unregister_all(struct drm_device * dev)310 void drm_plane_unregister_all(struct drm_device *dev)
311 {
312 	struct drm_plane *plane;
313 
314 	drm_for_each_plane(plane, dev) {
315 		if (plane->funcs->early_unregister)
316 			plane->funcs->early_unregister(plane);
317 	}
318 }
319 
320 /**
321  * drm_plane_init - Initialize a legacy plane
322  * @dev: DRM device
323  * @plane: plane object to init
324  * @possible_crtcs: bitmask of possible CRTCs
325  * @funcs: callbacks for the new plane
326  * @formats: array of supported formats (DRM_FORMAT\_\*)
327  * @format_count: number of elements in @formats
328  * @is_primary: plane type (primary vs overlay)
329  *
330  * Legacy API to initialize a DRM plane.
331  *
332  * New drivers should call drm_universal_plane_init() instead.
333  *
334  * Returns:
335  * Zero on success, error code on failure.
336  */
drm_plane_init(struct drm_device * dev,struct drm_plane * plane,uint32_t possible_crtcs,const struct drm_plane_funcs * funcs,const uint32_t * formats,unsigned int format_count,bool is_primary)337 int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
338 		   uint32_t possible_crtcs,
339 		   const struct drm_plane_funcs *funcs,
340 		   const uint32_t *formats, unsigned int format_count,
341 		   bool is_primary)
342 {
343 	enum drm_plane_type type;
344 
345 	type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
346 	return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
347 					formats, format_count,
348 					NULL, type, NULL);
349 }
350 EXPORT_SYMBOL(drm_plane_init);
351 
352 /**
353  * drm_plane_cleanup - Clean up the core plane usage
354  * @plane: plane to cleanup
355  *
356  * This function cleans up @plane and removes it from the DRM mode setting
357  * core. Note that the function does *not* free the plane structure itself,
358  * this is the responsibility of the caller.
359  */
drm_plane_cleanup(struct drm_plane * plane)360 void drm_plane_cleanup(struct drm_plane *plane)
361 {
362 	struct drm_device *dev = plane->dev;
363 
364 	drm_modeset_lock_fini(&plane->mutex);
365 
366 	kfree(plane->format_types);
367 	kfree(plane->modifiers);
368 	drm_mode_object_unregister(dev, &plane->base);
369 
370 	BUG_ON(list_empty(&plane->head));
371 
372 	/* Note that the plane_list is considered to be static; should we
373 	 * remove the drm_plane at runtime we would have to decrement all
374 	 * the indices on the drm_plane after us in the plane_list.
375 	 */
376 
377 	list_del(&plane->head);
378 	dev->mode_config.num_total_plane--;
379 
380 	WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
381 	if (plane->state && plane->funcs->atomic_destroy_state)
382 		plane->funcs->atomic_destroy_state(plane, plane->state);
383 
384 	kfree(plane->name);
385 
386 	memset(plane, 0, sizeof(*plane));
387 }
388 EXPORT_SYMBOL(drm_plane_cleanup);
389 
390 /**
391  * drm_plane_from_index - find the registered plane at an index
392  * @dev: DRM device
393  * @idx: index of registered plane to find for
394  *
395  * Given a plane index, return the registered plane from DRM device's
396  * list of planes with matching index. This is the inverse of drm_plane_index().
397  */
398 struct drm_plane *
drm_plane_from_index(struct drm_device * dev,int idx)399 drm_plane_from_index(struct drm_device *dev, int idx)
400 {
401 	struct drm_plane *plane;
402 
403 	drm_for_each_plane(plane, dev)
404 		if (idx == plane->index)
405 			return plane;
406 
407 	return NULL;
408 }
409 EXPORT_SYMBOL(drm_plane_from_index);
410 
411 /**
412  * drm_plane_force_disable - Forcibly disable a plane
413  * @plane: plane to disable
414  *
415  * Forces the plane to be disabled.
416  *
417  * Used when the plane's current framebuffer is destroyed,
418  * and when restoring fbdev mode.
419  *
420  * Note that this function is not suitable for atomic drivers, since it doesn't
421  * wire through the lock acquisition context properly and hence can't handle
422  * retries or driver private locks. You probably want to use
423  * drm_atomic_helper_disable_plane() or
424  * drm_atomic_helper_disable_planes_on_crtc() instead.
425  */
drm_plane_force_disable(struct drm_plane * plane)426 void drm_plane_force_disable(struct drm_plane *plane)
427 {
428 	int ret;
429 
430 	if (!plane->fb)
431 		return;
432 
433 	WARN_ON(drm_drv_uses_atomic_modeset(plane->dev));
434 
435 	plane->old_fb = plane->fb;
436 	ret = plane->funcs->disable_plane(plane, NULL);
437 	if (ret) {
438 		DRM_ERROR("failed to disable plane with busy fb\n");
439 		plane->old_fb = NULL;
440 		return;
441 	}
442 	/* disconnect the plane from the fb and crtc: */
443 	drm_framebuffer_put(plane->old_fb);
444 	plane->old_fb = NULL;
445 	plane->fb = NULL;
446 	plane->crtc = NULL;
447 }
448 EXPORT_SYMBOL(drm_plane_force_disable);
449 
450 /**
451  * drm_mode_plane_set_obj_prop - set the value of a property
452  * @plane: drm plane object to set property value for
453  * @property: property to set
454  * @value: value the property should be set to
455  *
456  * This functions sets a given property on a given plane object. This function
457  * calls the driver's ->set_property callback and changes the software state of
458  * the property if the callback succeeds.
459  *
460  * Returns:
461  * Zero on success, error code on failure.
462  */
drm_mode_plane_set_obj_prop(struct drm_plane * plane,struct drm_property * property,uint64_t value)463 int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
464 				struct drm_property *property,
465 				uint64_t value)
466 {
467 	int ret = -EINVAL;
468 	struct drm_mode_object *obj = &plane->base;
469 
470 	if (plane->funcs->set_property)
471 		ret = plane->funcs->set_property(plane, property, value);
472 	if (!ret)
473 		drm_object_property_set_value(obj, property, value);
474 
475 	return ret;
476 }
477 EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
478 
drm_mode_getplane_res(struct drm_device * dev,void * data,struct drm_file * file_priv)479 int drm_mode_getplane_res(struct drm_device *dev, void *data,
480 			  struct drm_file *file_priv)
481 {
482 	struct drm_mode_get_plane_res *plane_resp = data;
483 	struct drm_plane *plane;
484 	uint32_t __user *plane_ptr;
485 	int count = 0;
486 
487 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
488 		return -EOPNOTSUPP;
489 
490 	plane_ptr = u64_to_user_ptr(plane_resp->plane_id_ptr);
491 
492 	/*
493 	 * This ioctl is called twice, once to determine how much space is
494 	 * needed, and the 2nd time to fill it.
495 	 */
496 	drm_for_each_plane(plane, dev) {
497 		/*
498 		 * Unless userspace set the 'universal planes'
499 		 * capability bit, only advertise overlays.
500 		 */
501 		if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
502 		    !file_priv->universal_planes)
503 			continue;
504 
505 		if (drm_lease_held(file_priv, plane->base.id)) {
506 			if (count < plane_resp->count_planes &&
507 			    put_user(plane->base.id, plane_ptr + count))
508 				return -EFAULT;
509 			count++;
510 		}
511 	}
512 	plane_resp->count_planes = count;
513 
514 	return 0;
515 }
516 
drm_mode_getplane(struct drm_device * dev,void * data,struct drm_file * file_priv)517 int drm_mode_getplane(struct drm_device *dev, void *data,
518 		      struct drm_file *file_priv)
519 {
520 	struct drm_mode_get_plane *plane_resp = data;
521 	struct drm_plane *plane;
522 	uint32_t __user *format_ptr;
523 
524 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
525 		return -EOPNOTSUPP;
526 
527 	plane = drm_plane_find(dev, file_priv, plane_resp->plane_id);
528 	if (!plane)
529 		return -ENOENT;
530 
531 	drm_modeset_lock(&plane->mutex, NULL);
532 	if (plane->state && plane->state->crtc && drm_lease_held(file_priv, plane->state->crtc->base.id))
533 		plane_resp->crtc_id = plane->state->crtc->base.id;
534 	else if (!plane->state && plane->crtc && drm_lease_held(file_priv, plane->crtc->base.id))
535 		plane_resp->crtc_id = plane->crtc->base.id;
536 	else
537 		plane_resp->crtc_id = 0;
538 
539 	if (plane->state && plane->state->fb)
540 		plane_resp->fb_id = plane->state->fb->base.id;
541 	else if (!plane->state && plane->fb)
542 		plane_resp->fb_id = plane->fb->base.id;
543 	else
544 		plane_resp->fb_id = 0;
545 	drm_modeset_unlock(&plane->mutex);
546 
547 	plane_resp->plane_id = plane->base.id;
548 	plane_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
549 							    plane->possible_crtcs);
550 
551 	plane_resp->gamma_size = 0;
552 
553 	/*
554 	 * This ioctl is called twice, once to determine how much space is
555 	 * needed, and the 2nd time to fill it.
556 	 */
557 	if (plane->format_count &&
558 	    (plane_resp->count_format_types >= plane->format_count)) {
559 		format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
560 		if (copy_to_user(format_ptr,
561 				 plane->format_types,
562 				 sizeof(uint32_t) * plane->format_count)) {
563 			return -EFAULT;
564 		}
565 	}
566 	plane_resp->count_format_types = plane->format_count;
567 
568 	return 0;
569 }
570 
drm_plane_check_pixel_format(struct drm_plane * plane,u32 format,u64 modifier)571 int drm_plane_check_pixel_format(struct drm_plane *plane,
572 				 u32 format, u64 modifier)
573 {
574 	unsigned int i;
575 
576 	for (i = 0; i < plane->format_count; i++) {
577 		if (format == plane->format_types[i])
578 			break;
579 	}
580 	if (i == plane->format_count)
581 		return -EINVAL;
582 
583 	if (plane->funcs->format_mod_supported) {
584 		if (!plane->funcs->format_mod_supported(plane, format, modifier))
585 			return -EINVAL;
586 	} else {
587 		if (!plane->modifier_count)
588 			return 0;
589 
590 		for (i = 0; i < plane->modifier_count; i++) {
591 			if (modifier == plane->modifiers[i])
592 				break;
593 		}
594 		if (i == plane->modifier_count)
595 			return -EINVAL;
596 	}
597 
598 	return 0;
599 }
600 
__setplane_check(struct drm_plane * plane,struct drm_crtc * crtc,struct drm_framebuffer * fb,int32_t crtc_x,int32_t crtc_y,uint32_t crtc_w,uint32_t crtc_h,uint32_t src_x,uint32_t src_y,uint32_t src_w,uint32_t src_h)601 static int __setplane_check(struct drm_plane *plane,
602 			    struct drm_crtc *crtc,
603 			    struct drm_framebuffer *fb,
604 			    int32_t crtc_x, int32_t crtc_y,
605 			    uint32_t crtc_w, uint32_t crtc_h,
606 			    uint32_t src_x, uint32_t src_y,
607 			    uint32_t src_w, uint32_t src_h)
608 {
609 	int ret;
610 
611 	/* Check whether this plane is usable on this CRTC */
612 	if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
613 		DRM_DEBUG_KMS("Invalid crtc for plane\n");
614 		return -EINVAL;
615 	}
616 
617 	/* Check whether this plane supports the fb pixel format. */
618 	ret = drm_plane_check_pixel_format(plane, fb->format->format,
619 					   fb->modifier);
620 	if (ret) {
621 		struct drm_format_name_buf format_name;
622 
623 		DRM_DEBUG_KMS("Invalid pixel format %s, modifier 0x%"PRIx64"\n",
624 			      drm_get_format_name(fb->format->format,
625 						  &format_name),
626 			      fb->modifier);
627 		return ret;
628 	}
629 
630 	/* Give drivers some help against integer overflows */
631 	if (crtc_w > INT_MAX ||
632 	    crtc_x > INT_MAX - (int32_t) crtc_w ||
633 	    crtc_h > INT_MAX ||
634 	    crtc_y > INT_MAX - (int32_t) crtc_h) {
635 		DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
636 			      crtc_w, crtc_h, crtc_x, crtc_y);
637 		return -ERANGE;
638 	}
639 
640 	ret = drm_framebuffer_check_src_coords(src_x, src_y, src_w, src_h, fb);
641 	if (ret)
642 		return ret;
643 
644 	return 0;
645 }
646 
647 /**
648  * drm_any_plane_has_format - Check whether any plane supports this format and modifier combination
649  * @dev: DRM device
650  * @format: pixel format (DRM_FORMAT_*)
651  * @modifier: data layout modifier
652  *
653  * Returns:
654  * Whether at least one plane supports the specified format and modifier combination.
655  */
drm_any_plane_has_format(struct drm_device * dev,u32 format,u64 modifier)656 bool drm_any_plane_has_format(struct drm_device *dev,
657 			      u32 format, u64 modifier)
658 {
659 	struct drm_plane *plane;
660 
661 	drm_for_each_plane(plane, dev) {
662 		if (drm_plane_check_pixel_format(plane, format, modifier) == 0)
663 			return true;
664 	}
665 
666 	return false;
667 }
668 EXPORT_SYMBOL(drm_any_plane_has_format);
669 
670 /*
671  * __setplane_internal - setplane handler for internal callers
672  *
673  * This function will take a reference on the new fb for the plane
674  * on success.
675  *
676  * src_{x,y,w,h} are provided in 16.16 fixed point format
677  */
__setplane_internal(struct drm_plane * plane,struct drm_crtc * crtc,struct drm_framebuffer * fb,int32_t crtc_x,int32_t crtc_y,uint32_t crtc_w,uint32_t crtc_h,uint32_t src_x,uint32_t src_y,uint32_t src_w,uint32_t src_h,struct drm_modeset_acquire_ctx * ctx)678 static int __setplane_internal(struct drm_plane *plane,
679 			       struct drm_crtc *crtc,
680 			       struct drm_framebuffer *fb,
681 			       int32_t crtc_x, int32_t crtc_y,
682 			       uint32_t crtc_w, uint32_t crtc_h,
683 			       /* src_{x,y,w,h} values are 16.16 fixed point */
684 			       uint32_t src_x, uint32_t src_y,
685 			       uint32_t src_w, uint32_t src_h,
686 			       struct drm_modeset_acquire_ctx *ctx)
687 {
688 	int ret = 0;
689 
690 	WARN_ON(drm_drv_uses_atomic_modeset(plane->dev));
691 
692 	/* No fb means shut it down */
693 	if (!fb) {
694 		plane->old_fb = plane->fb;
695 		ret = plane->funcs->disable_plane(plane, ctx);
696 		if (!ret) {
697 			plane->crtc = NULL;
698 			plane->fb = NULL;
699 		} else {
700 			plane->old_fb = NULL;
701 		}
702 		goto out;
703 	}
704 
705 	ret = __setplane_check(plane, crtc, fb,
706 			       crtc_x, crtc_y, crtc_w, crtc_h,
707 			       src_x, src_y, src_w, src_h);
708 	if (ret)
709 		goto out;
710 
711 	plane->old_fb = plane->fb;
712 	ret = plane->funcs->update_plane(plane, crtc, fb,
713 					 crtc_x, crtc_y, crtc_w, crtc_h,
714 					 src_x, src_y, src_w, src_h, ctx);
715 	if (!ret) {
716 		plane->crtc = crtc;
717 		plane->fb = fb;
718 		drm_framebuffer_get(plane->fb);
719 	} else {
720 		plane->old_fb = NULL;
721 	}
722 
723 out:
724 	if (plane->old_fb)
725 		drm_framebuffer_put(plane->old_fb);
726 	plane->old_fb = NULL;
727 
728 	return ret;
729 }
730 
__setplane_atomic(struct drm_plane * plane,struct drm_crtc * crtc,struct drm_framebuffer * fb,int32_t crtc_x,int32_t crtc_y,uint32_t crtc_w,uint32_t crtc_h,uint32_t src_x,uint32_t src_y,uint32_t src_w,uint32_t src_h,struct drm_modeset_acquire_ctx * ctx)731 static int __setplane_atomic(struct drm_plane *plane,
732 			     struct drm_crtc *crtc,
733 			     struct drm_framebuffer *fb,
734 			     int32_t crtc_x, int32_t crtc_y,
735 			     uint32_t crtc_w, uint32_t crtc_h,
736 			     uint32_t src_x, uint32_t src_y,
737 			     uint32_t src_w, uint32_t src_h,
738 			     struct drm_modeset_acquire_ctx *ctx)
739 {
740 	int ret;
741 
742 	WARN_ON(!drm_drv_uses_atomic_modeset(plane->dev));
743 
744 	/* No fb means shut it down */
745 	if (!fb)
746 		return plane->funcs->disable_plane(plane, ctx);
747 
748 	/*
749 	 * FIXME: This is redundant with drm_atomic_plane_check(),
750 	 * but the legacy cursor/"async" .update_plane() tricks
751 	 * don't call that so we still need this here. Should remove
752 	 * this when all .update_plane() implementations have been
753 	 * fixed to call drm_atomic_plane_check().
754 	 */
755 	ret = __setplane_check(plane, crtc, fb,
756 			       crtc_x, crtc_y, crtc_w, crtc_h,
757 			       src_x, src_y, src_w, src_h);
758 	if (ret)
759 		return ret;
760 
761 	return plane->funcs->update_plane(plane, crtc, fb,
762 					  crtc_x, crtc_y, crtc_w, crtc_h,
763 					  src_x, src_y, src_w, src_h, ctx);
764 }
765 
setplane_internal(struct drm_plane * plane,struct drm_crtc * crtc,struct drm_framebuffer * fb,int32_t crtc_x,int32_t crtc_y,uint32_t crtc_w,uint32_t crtc_h,uint32_t src_x,uint32_t src_y,uint32_t src_w,uint32_t src_h)766 static int setplane_internal(struct drm_plane *plane,
767 			     struct drm_crtc *crtc,
768 			     struct drm_framebuffer *fb,
769 			     int32_t crtc_x, int32_t crtc_y,
770 			     uint32_t crtc_w, uint32_t crtc_h,
771 			     /* src_{x,y,w,h} values are 16.16 fixed point */
772 			     uint32_t src_x, uint32_t src_y,
773 			     uint32_t src_w, uint32_t src_h)
774 {
775 	struct drm_modeset_acquire_ctx ctx;
776 	int ret;
777 
778 	DRM_MODESET_LOCK_ALL_BEGIN(plane->dev, ctx,
779 				   DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
780 
781 	if (drm_drv_uses_atomic_modeset(plane->dev))
782 		ret = __setplane_atomic(plane, crtc, fb,
783 					crtc_x, crtc_y, crtc_w, crtc_h,
784 					src_x, src_y, src_w, src_h, &ctx);
785 	else
786 		ret = __setplane_internal(plane, crtc, fb,
787 					  crtc_x, crtc_y, crtc_w, crtc_h,
788 					  src_x, src_y, src_w, src_h, &ctx);
789 
790 	DRM_MODESET_LOCK_ALL_END(ctx, ret);
791 
792 	return ret;
793 }
794 
drm_mode_setplane(struct drm_device * dev,void * data,struct drm_file * file_priv)795 int drm_mode_setplane(struct drm_device *dev, void *data,
796 		      struct drm_file *file_priv)
797 {
798 	struct drm_mode_set_plane *plane_req = data;
799 	struct drm_plane *plane;
800 	struct drm_crtc *crtc = NULL;
801 	struct drm_framebuffer *fb = NULL;
802 	int ret;
803 
804 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
805 		return -EOPNOTSUPP;
806 
807 	/*
808 	 * First, find the plane, crtc, and fb objects.  If not available,
809 	 * we don't bother to call the driver.
810 	 */
811 	plane = drm_plane_find(dev, file_priv, plane_req->plane_id);
812 	if (!plane) {
813 		DRM_DEBUG_KMS("Unknown plane ID %d\n",
814 			      plane_req->plane_id);
815 		return -ENOENT;
816 	}
817 
818 	if (plane_req->fb_id) {
819 		fb = drm_framebuffer_lookup(dev, file_priv, plane_req->fb_id);
820 		if (!fb) {
821 			DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
822 				      plane_req->fb_id);
823 			return -ENOENT;
824 		}
825 
826 		crtc = drm_crtc_find(dev, file_priv, plane_req->crtc_id);
827 		if (!crtc) {
828 			drm_framebuffer_put(fb);
829 			DRM_DEBUG_KMS("Unknown crtc ID %d\n",
830 				      plane_req->crtc_id);
831 			return -ENOENT;
832 		}
833 	}
834 
835 	ret = setplane_internal(plane, crtc, fb,
836 				plane_req->crtc_x, plane_req->crtc_y,
837 				plane_req->crtc_w, plane_req->crtc_h,
838 				plane_req->src_x, plane_req->src_y,
839 				plane_req->src_w, plane_req->src_h);
840 
841 	if (fb)
842 		drm_framebuffer_put(fb);
843 
844 	return ret;
845 }
846 
drm_mode_cursor_universal(struct drm_crtc * crtc,struct drm_mode_cursor2 * req,struct drm_file * file_priv,struct drm_modeset_acquire_ctx * ctx)847 static int drm_mode_cursor_universal(struct drm_crtc *crtc,
848 				     struct drm_mode_cursor2 *req,
849 				     struct drm_file *file_priv,
850 				     struct drm_modeset_acquire_ctx *ctx)
851 {
852 	struct drm_device *dev = crtc->dev;
853 	struct drm_plane *plane = crtc->cursor;
854 	struct drm_framebuffer *fb = NULL;
855 	struct drm_mode_fb_cmd2 fbreq = {
856 		.width = req->width,
857 		.height = req->height,
858 		.pixel_format = DRM_FORMAT_ARGB8888,
859 		.pitches = { req->width * 4 },
860 		.handles = { req->handle },
861 	};
862 	int32_t crtc_x, crtc_y;
863 	uint32_t crtc_w = 0, crtc_h = 0;
864 	uint32_t src_w = 0, src_h = 0;
865 	int ret = 0;
866 
867 	BUG_ON(!plane);
868 	WARN_ON(plane->crtc != crtc && plane->crtc != NULL);
869 
870 	/*
871 	 * Obtain fb we'll be using (either new or existing) and take an extra
872 	 * reference to it if fb != null.  setplane will take care of dropping
873 	 * the reference if the plane update fails.
874 	 */
875 	if (req->flags & DRM_MODE_CURSOR_BO) {
876 		if (req->handle) {
877 			fb = drm_internal_framebuffer_create(dev, &fbreq, file_priv);
878 			if (IS_ERR(fb)) {
879 				DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
880 				return PTR_ERR(fb);
881 			}
882 
883 			fb->hot_x = req->hot_x;
884 			fb->hot_y = req->hot_y;
885 		} else {
886 			fb = NULL;
887 		}
888 	} else {
889 		if (plane->state)
890 			fb = plane->state->fb;
891 		else
892 			fb = plane->fb;
893 
894 		if (fb)
895 			drm_framebuffer_get(fb);
896 	}
897 
898 	if (req->flags & DRM_MODE_CURSOR_MOVE) {
899 		crtc_x = req->x;
900 		crtc_y = req->y;
901 	} else {
902 		crtc_x = crtc->cursor_x;
903 		crtc_y = crtc->cursor_y;
904 	}
905 
906 	if (fb) {
907 		crtc_w = fb->width;
908 		crtc_h = fb->height;
909 		src_w = fb->width << 16;
910 		src_h = fb->height << 16;
911 	}
912 
913 	if (drm_drv_uses_atomic_modeset(dev))
914 		ret = __setplane_atomic(plane, crtc, fb,
915 					crtc_x, crtc_y, crtc_w, crtc_h,
916 					0, 0, src_w, src_h, ctx);
917 	else
918 		ret = __setplane_internal(plane, crtc, fb,
919 					  crtc_x, crtc_y, crtc_w, crtc_h,
920 					  0, 0, src_w, src_h, ctx);
921 
922 	if (fb)
923 		drm_framebuffer_put(fb);
924 
925 	/* Update successful; save new cursor position, if necessary */
926 	if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
927 		crtc->cursor_x = req->x;
928 		crtc->cursor_y = req->y;
929 	}
930 
931 	return ret;
932 }
933 
drm_mode_cursor_common(struct drm_device * dev,struct drm_mode_cursor2 * req,struct drm_file * file_priv)934 static int drm_mode_cursor_common(struct drm_device *dev,
935 				  struct drm_mode_cursor2 *req,
936 				  struct drm_file *file_priv)
937 {
938 	struct drm_crtc *crtc;
939 	struct drm_modeset_acquire_ctx ctx;
940 	int ret = 0;
941 
942 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
943 		return -EOPNOTSUPP;
944 
945 	if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
946 		return -EINVAL;
947 
948 	crtc = drm_crtc_find(dev, file_priv, req->crtc_id);
949 	if (!crtc) {
950 		DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
951 		return -ENOENT;
952 	}
953 
954 	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
955 retry:
956 	ret = drm_modeset_lock(&crtc->mutex, &ctx);
957 	if (ret)
958 		goto out;
959 	/*
960 	 * If this crtc has a universal cursor plane, call that plane's update
961 	 * handler rather than using legacy cursor handlers.
962 	 */
963 	if (crtc->cursor) {
964 		ret = drm_modeset_lock(&crtc->cursor->mutex, &ctx);
965 		if (ret)
966 			goto out;
967 
968 		if (!drm_lease_held(file_priv, crtc->cursor->base.id)) {
969 			ret = -EACCES;
970 			goto out;
971 		}
972 
973 		ret = drm_mode_cursor_universal(crtc, req, file_priv, &ctx);
974 		goto out;
975 	}
976 
977 	if (req->flags & DRM_MODE_CURSOR_BO) {
978 		if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
979 			ret = -ENXIO;
980 			goto out;
981 		}
982 		/* Turns off the cursor if handle is 0 */
983 		if (crtc->funcs->cursor_set2)
984 			ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle,
985 						      req->width, req->height, req->hot_x, req->hot_y);
986 		else
987 			ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
988 						      req->width, req->height);
989 	}
990 
991 	if (req->flags & DRM_MODE_CURSOR_MOVE) {
992 		if (crtc->funcs->cursor_move) {
993 			ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
994 		} else {
995 			ret = -EFAULT;
996 			goto out;
997 		}
998 	}
999 out:
1000 	if (ret == -EDEADLK) {
1001 		ret = drm_modeset_backoff(&ctx);
1002 		if (!ret)
1003 			goto retry;
1004 	}
1005 
1006 	drm_modeset_drop_locks(&ctx);
1007 	drm_modeset_acquire_fini(&ctx);
1008 
1009 	return ret;
1010 
1011 }
1012 
1013 
drm_mode_cursor_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1014 int drm_mode_cursor_ioctl(struct drm_device *dev,
1015 			  void *data, struct drm_file *file_priv)
1016 {
1017 	struct drm_mode_cursor *req = data;
1018 	struct drm_mode_cursor2 new_req;
1019 
1020 	memcpy(&new_req, req, sizeof(struct drm_mode_cursor));
1021 	new_req.hot_x = new_req.hot_y = 0;
1022 
1023 	return drm_mode_cursor_common(dev, &new_req, file_priv);
1024 }
1025 
1026 /*
1027  * Set the cursor configuration based on user request. This implements the 2nd
1028  * version of the cursor ioctl, which allows userspace to additionally specify
1029  * the hotspot of the pointer.
1030  */
drm_mode_cursor2_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1031 int drm_mode_cursor2_ioctl(struct drm_device *dev,
1032 			   void *data, struct drm_file *file_priv)
1033 {
1034 	struct drm_mode_cursor2 *req = data;
1035 
1036 	return drm_mode_cursor_common(dev, req, file_priv);
1037 }
1038 
drm_mode_page_flip_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1039 int drm_mode_page_flip_ioctl(struct drm_device *dev,
1040 			     void *data, struct drm_file *file_priv)
1041 {
1042 	struct drm_mode_crtc_page_flip_target *page_flip = data;
1043 	struct drm_crtc *crtc;
1044 	struct drm_plane *plane;
1045 	struct drm_framebuffer *fb = NULL, *old_fb;
1046 	struct drm_pending_vblank_event *e = NULL;
1047 	u32 target_vblank = page_flip->sequence;
1048 	struct drm_modeset_acquire_ctx ctx;
1049 	int ret = -EINVAL;
1050 
1051 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1052 		return -EOPNOTSUPP;
1053 
1054 	if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS)
1055 		return -EINVAL;
1056 
1057 	if (page_flip->sequence != 0 && !(page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET))
1058 		return -EINVAL;
1059 
1060 	/* Only one of the DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags
1061 	 * can be specified
1062 	 */
1063 	if ((page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) == DRM_MODE_PAGE_FLIP_TARGET)
1064 		return -EINVAL;
1065 
1066 	if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
1067 		return -EINVAL;
1068 
1069 	crtc = drm_crtc_find(dev, file_priv, page_flip->crtc_id);
1070 	if (!crtc)
1071 		return -ENOENT;
1072 
1073 	plane = crtc->primary;
1074 
1075 	if (!drm_lease_held(file_priv, plane->base.id))
1076 		return -EACCES;
1077 
1078 	if (crtc->funcs->page_flip_target) {
1079 		u32 current_vblank;
1080 		int r;
1081 
1082 		r = drm_crtc_vblank_get(crtc);
1083 		if (r)
1084 			return r;
1085 
1086 		current_vblank = (u32)drm_crtc_vblank_count(crtc);
1087 
1088 		switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) {
1089 		case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE:
1090 			if ((int)(target_vblank - current_vblank) > 1) {
1091 				DRM_DEBUG("Invalid absolute flip target %u, "
1092 					  "must be <= %u\n", target_vblank,
1093 					  current_vblank + 1);
1094 				drm_crtc_vblank_put(crtc);
1095 				return -EINVAL;
1096 			}
1097 			break;
1098 		case DRM_MODE_PAGE_FLIP_TARGET_RELATIVE:
1099 			if (target_vblank != 0 && target_vblank != 1) {
1100 				DRM_DEBUG("Invalid relative flip target %u, "
1101 					  "must be 0 or 1\n", target_vblank);
1102 				drm_crtc_vblank_put(crtc);
1103 				return -EINVAL;
1104 			}
1105 			target_vblank += current_vblank;
1106 			break;
1107 		default:
1108 			target_vblank = current_vblank +
1109 				!(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC);
1110 			break;
1111 		}
1112 	} else if (crtc->funcs->page_flip == NULL ||
1113 		   (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) {
1114 		return -EINVAL;
1115 	}
1116 
1117 	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
1118 retry:
1119 	ret = drm_modeset_lock(&crtc->mutex, &ctx);
1120 	if (ret)
1121 		goto out;
1122 	ret = drm_modeset_lock(&plane->mutex, &ctx);
1123 	if (ret)
1124 		goto out;
1125 
1126 	if (plane->state)
1127 		old_fb = plane->state->fb;
1128 	else
1129 		old_fb = plane->fb;
1130 
1131 	if (old_fb == NULL) {
1132 		/* The framebuffer is currently unbound, presumably
1133 		 * due to a hotplug event, that userspace has not
1134 		 * yet discovered.
1135 		 */
1136 		ret = -EBUSY;
1137 		goto out;
1138 	}
1139 
1140 	fb = drm_framebuffer_lookup(dev, file_priv, page_flip->fb_id);
1141 	if (!fb) {
1142 		ret = -ENOENT;
1143 		goto out;
1144 	}
1145 
1146 	if (plane->state) {
1147 		const struct drm_plane_state *state = plane->state;
1148 
1149 		ret = drm_framebuffer_check_src_coords(state->src_x,
1150 						       state->src_y,
1151 						       state->src_w,
1152 						       state->src_h,
1153 						       fb);
1154 	} else {
1155 		ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y,
1156 					      &crtc->mode, fb);
1157 	}
1158 	if (ret)
1159 		goto out;
1160 
1161 	if (old_fb->format != fb->format) {
1162 		DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
1163 		ret = -EINVAL;
1164 		goto out;
1165 	}
1166 
1167 	if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
1168 		e = kzalloc(sizeof *e, GFP_KERNEL);
1169 		if (!e) {
1170 			ret = -ENOMEM;
1171 			goto out;
1172 		}
1173 
1174 		e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
1175 		e->event.base.length = sizeof(e->event);
1176 		e->event.vbl.user_data = page_flip->user_data;
1177 		e->event.vbl.crtc_id = crtc->base.id;
1178 
1179 		ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
1180 		if (ret) {
1181 			kfree(e);
1182 			e = NULL;
1183 			goto out;
1184 		}
1185 	}
1186 
1187 	plane->old_fb = plane->fb;
1188 	if (crtc->funcs->page_flip_target)
1189 		ret = crtc->funcs->page_flip_target(crtc, fb, e,
1190 						    page_flip->flags,
1191 						    target_vblank,
1192 						    &ctx);
1193 	else
1194 		ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags,
1195 					     &ctx);
1196 	if (ret) {
1197 		if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
1198 			drm_event_cancel_free(dev, &e->base);
1199 		/* Keep the old fb, don't unref it. */
1200 		plane->old_fb = NULL;
1201 	} else {
1202 		if (!plane->state) {
1203 			plane->fb = fb;
1204 			drm_framebuffer_get(fb);
1205 		}
1206 	}
1207 
1208 out:
1209 	if (fb)
1210 		drm_framebuffer_put(fb);
1211 	if (plane->old_fb)
1212 		drm_framebuffer_put(plane->old_fb);
1213 	plane->old_fb = NULL;
1214 
1215 	if (ret == -EDEADLK) {
1216 		ret = drm_modeset_backoff(&ctx);
1217 		if (!ret)
1218 			goto retry;
1219 	}
1220 
1221 	drm_modeset_drop_locks(&ctx);
1222 	drm_modeset_acquire_fini(&ctx);
1223 
1224 	if (ret && crtc->funcs->page_flip_target)
1225 		drm_crtc_vblank_put(crtc);
1226 
1227 	return ret;
1228 }
1229