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