Home | History | Annotate | Line # | Download | only in drm
      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 
     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 *
     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 *
     86 modifiers_ptr(struct drm_format_modifier_blob *blob)
     87 {
     88 	return (struct drm_format_modifier *)(((char *)blob) + blob->modifiers_offset);
     89 }
     90 
     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  */
    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 
    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 
    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  */
    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  */
    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 *
    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  */
    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  */
    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 
    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 
    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 
    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 
    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  */
    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  */
    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 
    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 
    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 
    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 
    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 
    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 
   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  */
   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 
   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