cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

drm_plane.c (46372B)


      1/*
      2 * Copyright (c) 2016 Intel Corporation
      3 *
      4 * Permission to use, copy, modify, distribute, and sell this software and its
      5 * documentation for any purpose is hereby granted without fee, provided that
      6 * the above copyright notice appear in all copies and that both that copyright
      7 * notice and this permission notice appear in supporting documentation, and
      8 * that the name of the copyright holders not be used in advertising or
      9 * publicity pertaining to distribution of the software without specific,
     10 * written prior permission.  The copyright holders make no representations
     11 * about the suitability of this software for any purpose.  It is provided "as
     12 * is" without express or implied warranty.
     13 *
     14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     20 * OF THIS SOFTWARE.
     21 */
     22
     23#include <linux/slab.h>
     24#include <linux/uaccess.h>
     25
     26#include <drm/drm_plane.h>
     27#include <drm/drm_drv.h>
     28#include <drm/drm_print.h>
     29#include <drm/drm_framebuffer.h>
     30#include <drm/drm_file.h>
     31#include <drm/drm_crtc.h>
     32#include <drm/drm_fourcc.h>
     33#include <drm/drm_managed.h>
     34#include <drm/drm_vblank.h>
     35
     36#include "drm_crtc_internal.h"
     37
     38/**
     39 * DOC: overview
     40 *
     41 * A plane represents an image source that can be blended with or overlaid on
     42 * top of a CRTC during the scanout process. Planes take their input data from a
     43 * &drm_framebuffer object. The plane itself specifies the cropping and scaling
     44 * of that image, and where it is placed on the visible area of a display
     45 * pipeline, represented by &drm_crtc. A plane can also have additional
     46 * properties that specify how the pixels are positioned and blended, like
     47 * rotation or Z-position. All these properties are stored in &drm_plane_state.
     48 *
     49 * To create a plane, a KMS drivers allocates and zeroes an instances of
     50 * &struct drm_plane (possibly as part of a larger structure) and registers it
     51 * with a call to drm_universal_plane_init().
     52 *
     53 * Each plane has a type, see enum drm_plane_type. A plane can be compatible
     54 * with multiple CRTCs, see &drm_plane.possible_crtcs.
     55 *
     56 * Each CRTC must have a unique primary plane userspace can attach to enable
     57 * the CRTC. In other words, userspace must be able to attach a different
     58 * primary plane to each CRTC at the same time. Primary planes can still be
     59 * compatible with multiple CRTCs. There must be exactly as many primary planes
     60 * as there are CRTCs.
     61 *
     62 * Legacy uAPI doesn't expose the primary and cursor planes directly. DRM core
     63 * relies on the driver to set the primary and optionally the cursor plane used
     64 * for legacy IOCTLs. This is done by calling drm_crtc_init_with_planes(). All
     65 * drivers must provide one primary plane per CRTC to avoid surprising legacy
     66 * userspace too much.
     67 */
     68
     69/**
     70 * DOC: standard plane properties
     71 *
     72 * DRM planes have a few standardized properties:
     73 *
     74 * type:
     75 *     Immutable property describing the type of the plane.
     76 *
     77 *     For user-space which has enabled the &DRM_CLIENT_CAP_ATOMIC capability,
     78 *     the plane type is just a hint and is mostly superseded by atomic
     79 *     test-only commits. The type hint can still be used to come up more
     80 *     easily with a plane configuration accepted by the driver.
     81 *
     82 *     The value of this property can be one of the following:
     83 *
     84 *     "Primary":
     85 *         To light up a CRTC, attaching a primary plane is the most likely to
     86 *         work if it covers the whole CRTC and doesn't have scaling or
     87 *         cropping set up.
     88 *
     89 *         Drivers may support more features for the primary plane, user-space
     90 *         can find out with test-only atomic commits.
     91 *
     92 *         Some primary planes are implicitly used by the kernel in the legacy
     93 *         IOCTLs &DRM_IOCTL_MODE_SETCRTC and &DRM_IOCTL_MODE_PAGE_FLIP.
     94 *         Therefore user-space must not mix explicit usage of any primary
     95 *         plane (e.g. through an atomic commit) with these legacy IOCTLs.
     96 *
     97 *     "Cursor":
     98 *         To enable this plane, using a framebuffer configured without scaling
     99 *         or cropping and with the following properties is the most likely to
    100 *         work:
    101 *
    102 *         - If the driver provides the capabilities &DRM_CAP_CURSOR_WIDTH and
    103 *           &DRM_CAP_CURSOR_HEIGHT, create the framebuffer with this size.
    104 *           Otherwise, create a framebuffer with the size 64x64.
    105 *         - If the driver doesn't support modifiers, create a framebuffer with
    106 *           a linear layout. Otherwise, use the IN_FORMATS plane property.
    107 *
    108 *         Drivers may support more features for the cursor plane, user-space
    109 *         can find out with test-only atomic commits.
    110 *
    111 *         Some cursor planes are implicitly used by the kernel in the legacy
    112 *         IOCTLs &DRM_IOCTL_MODE_CURSOR and &DRM_IOCTL_MODE_CURSOR2.
    113 *         Therefore user-space must not mix explicit usage of any cursor
    114 *         plane (e.g. through an atomic commit) with these legacy IOCTLs.
    115 *
    116 *         Some drivers may support cursors even if no cursor plane is exposed.
    117 *         In this case, the legacy cursor IOCTLs can be used to configure the
    118 *         cursor.
    119 *
    120 *     "Overlay":
    121 *         Neither primary nor cursor.
    122 *
    123 *         Overlay planes are the only planes exposed when the
    124 *         &DRM_CLIENT_CAP_UNIVERSAL_PLANES capability is disabled.
    125 *
    126 * IN_FORMATS:
    127 *     Blob property which contains the set of buffer format and modifier
    128 *     pairs supported by this plane. The blob is a struct
    129 *     drm_format_modifier_blob. Without this property the plane doesn't
    130 *     support buffers with modifiers. Userspace cannot change this property.
    131 *
    132 *     Note that userspace can check the &DRM_CAP_ADDFB2_MODIFIERS driver
    133 *     capability for general modifier support. If this flag is set then every
    134 *     plane will have the IN_FORMATS property, even when it only supports
    135 *     DRM_FORMAT_MOD_LINEAR. Before linux kernel release v5.1 there have been
    136 *     various bugs in this area with inconsistencies between the capability
    137 *     flag and per-plane properties.
    138 */
    139
    140static unsigned int drm_num_planes(struct drm_device *dev)
    141{
    142	unsigned int num = 0;
    143	struct drm_plane *tmp;
    144
    145	drm_for_each_plane(tmp, dev) {
    146		num++;
    147	}
    148
    149	return num;
    150}
    151
    152static inline u32 *
    153formats_ptr(struct drm_format_modifier_blob *blob)
    154{
    155	return (u32 *)(((char *)blob) + blob->formats_offset);
    156}
    157
    158static inline struct drm_format_modifier *
    159modifiers_ptr(struct drm_format_modifier_blob *blob)
    160{
    161	return (struct drm_format_modifier *)(((char *)blob) + blob->modifiers_offset);
    162}
    163
    164static int create_in_format_blob(struct drm_device *dev, struct drm_plane *plane)
    165{
    166	const struct drm_mode_config *config = &dev->mode_config;
    167	struct drm_property_blob *blob;
    168	struct drm_format_modifier *mod;
    169	size_t blob_size, formats_size, modifiers_size;
    170	struct drm_format_modifier_blob *blob_data;
    171	unsigned int i, j;
    172
    173	formats_size = sizeof(__u32) * plane->format_count;
    174	if (WARN_ON(!formats_size)) {
    175		/* 0 formats are never expected */
    176		return 0;
    177	}
    178
    179	modifiers_size =
    180		sizeof(struct drm_format_modifier) * plane->modifier_count;
    181
    182	blob_size = sizeof(struct drm_format_modifier_blob);
    183	/* Modifiers offset is a pointer to a struct with a 64 bit field so it
    184	 * should be naturally aligned to 8B.
    185	 */
    186	BUILD_BUG_ON(sizeof(struct drm_format_modifier_blob) % 8);
    187	blob_size += ALIGN(formats_size, 8);
    188	blob_size += modifiers_size;
    189
    190	blob = drm_property_create_blob(dev, blob_size, NULL);
    191	if (IS_ERR(blob))
    192		return -1;
    193
    194	blob_data = blob->data;
    195	blob_data->version = FORMAT_BLOB_CURRENT;
    196	blob_data->count_formats = plane->format_count;
    197	blob_data->formats_offset = sizeof(struct drm_format_modifier_blob);
    198	blob_data->count_modifiers = plane->modifier_count;
    199
    200	blob_data->modifiers_offset =
    201		ALIGN(blob_data->formats_offset + formats_size, 8);
    202
    203	memcpy(formats_ptr(blob_data), plane->format_types, formats_size);
    204
    205	mod = modifiers_ptr(blob_data);
    206	for (i = 0; i < plane->modifier_count; i++) {
    207		for (j = 0; j < plane->format_count; j++) {
    208			if (!plane->funcs->format_mod_supported ||
    209			    plane->funcs->format_mod_supported(plane,
    210							       plane->format_types[j],
    211							       plane->modifiers[i])) {
    212				mod->formats |= 1ULL << j;
    213			}
    214		}
    215
    216		mod->modifier = plane->modifiers[i];
    217		mod->offset = 0;
    218		mod->pad = 0;
    219		mod++;
    220	}
    221
    222	drm_object_attach_property(&plane->base, config->modifiers_property,
    223				   blob->base.id);
    224
    225	return 0;
    226}
    227
    228__printf(9, 0)
    229static int __drm_universal_plane_init(struct drm_device *dev,
    230				      struct drm_plane *plane,
    231				      uint32_t possible_crtcs,
    232				      const struct drm_plane_funcs *funcs,
    233				      const uint32_t *formats,
    234				      unsigned int format_count,
    235				      const uint64_t *format_modifiers,
    236				      enum drm_plane_type type,
    237				      const char *name, va_list ap)
    238{
    239	struct drm_mode_config *config = &dev->mode_config;
    240	static const uint64_t default_modifiers[] = {
    241		DRM_FORMAT_MOD_LINEAR,
    242	};
    243	unsigned int format_modifier_count = 0;
    244	int ret;
    245
    246	/* plane index is used with 32bit bitmasks */
    247	if (WARN_ON(config->num_total_plane >= 32))
    248		return -EINVAL;
    249
    250	/*
    251	 * First driver to need more than 64 formats needs to fix this. Each
    252	 * format is encoded as a bit and the current code only supports a u64.
    253	 */
    254	if (WARN_ON(format_count > 64))
    255		return -EINVAL;
    256
    257	WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
    258		(!funcs->atomic_destroy_state ||
    259		 !funcs->atomic_duplicate_state));
    260
    261	ret = drm_mode_object_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
    262	if (ret)
    263		return ret;
    264
    265	drm_modeset_lock_init(&plane->mutex);
    266
    267	plane->base.properties = &plane->properties;
    268	plane->dev = dev;
    269	plane->funcs = funcs;
    270	plane->format_types = kmalloc_array(format_count, sizeof(uint32_t),
    271					    GFP_KERNEL);
    272	if (!plane->format_types) {
    273		DRM_DEBUG_KMS("out of memory when allocating plane\n");
    274		drm_mode_object_unregister(dev, &plane->base);
    275		return -ENOMEM;
    276	}
    277
    278	if (format_modifiers) {
    279		const uint64_t *temp_modifiers = format_modifiers;
    280
    281		while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
    282			format_modifier_count++;
    283	} else {
    284		if (!dev->mode_config.fb_modifiers_not_supported) {
    285			format_modifiers = default_modifiers;
    286			format_modifier_count = ARRAY_SIZE(default_modifiers);
    287		}
    288	}
    289
    290	/* autoset the cap and check for consistency across all planes */
    291	drm_WARN_ON(dev, config->fb_modifiers_not_supported &&
    292				format_modifier_count);
    293
    294	plane->modifier_count = format_modifier_count;
    295	plane->modifiers = kmalloc_array(format_modifier_count,
    296					 sizeof(format_modifiers[0]),
    297					 GFP_KERNEL);
    298
    299	if (format_modifier_count && !plane->modifiers) {
    300		DRM_DEBUG_KMS("out of memory when allocating plane\n");
    301		kfree(plane->format_types);
    302		drm_mode_object_unregister(dev, &plane->base);
    303		return -ENOMEM;
    304	}
    305
    306	if (name) {
    307		plane->name = kvasprintf(GFP_KERNEL, name, ap);
    308	} else {
    309		plane->name = kasprintf(GFP_KERNEL, "plane-%d",
    310					drm_num_planes(dev));
    311	}
    312	if (!plane->name) {
    313		kfree(plane->format_types);
    314		kfree(plane->modifiers);
    315		drm_mode_object_unregister(dev, &plane->base);
    316		return -ENOMEM;
    317	}
    318
    319	memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
    320	plane->format_count = format_count;
    321	memcpy(plane->modifiers, format_modifiers,
    322	       format_modifier_count * sizeof(format_modifiers[0]));
    323	plane->possible_crtcs = possible_crtcs;
    324	plane->type = type;
    325
    326	list_add_tail(&plane->head, &config->plane_list);
    327	plane->index = config->num_total_plane++;
    328
    329	drm_object_attach_property(&plane->base,
    330				   config->plane_type_property,
    331				   plane->type);
    332
    333	if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
    334		drm_object_attach_property(&plane->base, config->prop_fb_id, 0);
    335		drm_object_attach_property(&plane->base, config->prop_in_fence_fd, -1);
    336		drm_object_attach_property(&plane->base, config->prop_crtc_id, 0);
    337		drm_object_attach_property(&plane->base, config->prop_crtc_x, 0);
    338		drm_object_attach_property(&plane->base, config->prop_crtc_y, 0);
    339		drm_object_attach_property(&plane->base, config->prop_crtc_w, 0);
    340		drm_object_attach_property(&plane->base, config->prop_crtc_h, 0);
    341		drm_object_attach_property(&plane->base, config->prop_src_x, 0);
    342		drm_object_attach_property(&plane->base, config->prop_src_y, 0);
    343		drm_object_attach_property(&plane->base, config->prop_src_w, 0);
    344		drm_object_attach_property(&plane->base, config->prop_src_h, 0);
    345	}
    346
    347	if (format_modifier_count)
    348		create_in_format_blob(dev, plane);
    349
    350	return 0;
    351}
    352
    353/**
    354 * drm_universal_plane_init - Initialize a new universal plane object
    355 * @dev: DRM device
    356 * @plane: plane object to init
    357 * @possible_crtcs: bitmask of possible CRTCs
    358 * @funcs: callbacks for the new plane
    359 * @formats: array of supported formats (DRM_FORMAT\_\*)
    360 * @format_count: number of elements in @formats
    361 * @format_modifiers: array of struct drm_format modifiers terminated by
    362 *                    DRM_FORMAT_MOD_INVALID
    363 * @type: type of plane (overlay, primary, cursor)
    364 * @name: printf style format string for the plane name, or NULL for default name
    365 *
    366 * Initializes a plane object of type @type. The &drm_plane_funcs.destroy hook
    367 * should call drm_plane_cleanup() and kfree() the plane structure. The plane
    368 * structure should not be allocated with devm_kzalloc().
    369 *
    370 * Note: consider using drmm_universal_plane_alloc() instead of
    371 * drm_universal_plane_init() to let the DRM managed resource infrastructure
    372 * take care of cleanup and deallocation.
    373 *
    374 * Drivers that only support the DRM_FORMAT_MOD_LINEAR modifier support may set
    375 * @format_modifiers to NULL. The plane will advertise the linear modifier.
    376 *
    377 * Returns:
    378 * Zero on success, error code on failure.
    379 */
    380int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
    381			     uint32_t possible_crtcs,
    382			     const struct drm_plane_funcs *funcs,
    383			     const uint32_t *formats, unsigned int format_count,
    384			     const uint64_t *format_modifiers,
    385			     enum drm_plane_type type,
    386			     const char *name, ...)
    387{
    388	va_list ap;
    389	int ret;
    390
    391	WARN_ON(!funcs->destroy);
    392
    393	va_start(ap, name);
    394	ret = __drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
    395					 formats, format_count, format_modifiers,
    396					 type, name, ap);
    397	va_end(ap);
    398	return ret;
    399}
    400EXPORT_SYMBOL(drm_universal_plane_init);
    401
    402static void drmm_universal_plane_alloc_release(struct drm_device *dev, void *ptr)
    403{
    404	struct drm_plane *plane = ptr;
    405
    406	if (WARN_ON(!plane->dev))
    407		return;
    408
    409	drm_plane_cleanup(plane);
    410}
    411
    412void *__drmm_universal_plane_alloc(struct drm_device *dev, size_t size,
    413				   size_t offset, uint32_t possible_crtcs,
    414				   const struct drm_plane_funcs *funcs,
    415				   const uint32_t *formats, unsigned int format_count,
    416				   const uint64_t *format_modifiers,
    417				   enum drm_plane_type type,
    418				   const char *name, ...)
    419{
    420	void *container;
    421	struct drm_plane *plane;
    422	va_list ap;
    423	int ret;
    424
    425	if (WARN_ON(!funcs || funcs->destroy))
    426		return ERR_PTR(-EINVAL);
    427
    428	container = drmm_kzalloc(dev, size, GFP_KERNEL);
    429	if (!container)
    430		return ERR_PTR(-ENOMEM);
    431
    432	plane = container + offset;
    433
    434	va_start(ap, name);
    435	ret = __drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
    436					 formats, format_count, format_modifiers,
    437					 type, name, ap);
    438	va_end(ap);
    439	if (ret)
    440		return ERR_PTR(ret);
    441
    442	ret = drmm_add_action_or_reset(dev, drmm_universal_plane_alloc_release,
    443				       plane);
    444	if (ret)
    445		return ERR_PTR(ret);
    446
    447	return container;
    448}
    449EXPORT_SYMBOL(__drmm_universal_plane_alloc);
    450
    451int drm_plane_register_all(struct drm_device *dev)
    452{
    453	unsigned int num_planes = 0;
    454	unsigned int num_zpos = 0;
    455	struct drm_plane *plane;
    456	int ret = 0;
    457
    458	drm_for_each_plane(plane, dev) {
    459		if (plane->funcs->late_register)
    460			ret = plane->funcs->late_register(plane);
    461		if (ret)
    462			return ret;
    463
    464		if (plane->zpos_property)
    465			num_zpos++;
    466		num_planes++;
    467	}
    468
    469	drm_WARN(dev, num_zpos && num_planes != num_zpos,
    470		 "Mixing planes with and without zpos property is invalid\n");
    471
    472	return 0;
    473}
    474
    475void drm_plane_unregister_all(struct drm_device *dev)
    476{
    477	struct drm_plane *plane;
    478
    479	drm_for_each_plane(plane, dev) {
    480		if (plane->funcs->early_unregister)
    481			plane->funcs->early_unregister(plane);
    482	}
    483}
    484
    485/**
    486 * drm_plane_init - Initialize a legacy plane
    487 * @dev: DRM device
    488 * @plane: plane object to init
    489 * @possible_crtcs: bitmask of possible CRTCs
    490 * @funcs: callbacks for the new plane
    491 * @formats: array of supported formats (DRM_FORMAT\_\*)
    492 * @format_count: number of elements in @formats
    493 * @is_primary: plane type (primary vs overlay)
    494 *
    495 * Legacy API to initialize a DRM plane.
    496 *
    497 * New drivers should call drm_universal_plane_init() instead.
    498 *
    499 * Returns:
    500 * Zero on success, error code on failure.
    501 */
    502int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
    503		   uint32_t possible_crtcs,
    504		   const struct drm_plane_funcs *funcs,
    505		   const uint32_t *formats, unsigned int format_count,
    506		   bool is_primary)
    507{
    508	enum drm_plane_type type;
    509
    510	type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
    511	return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
    512					formats, format_count,
    513					NULL, type, NULL);
    514}
    515EXPORT_SYMBOL(drm_plane_init);
    516
    517/**
    518 * drm_plane_cleanup - Clean up the core plane usage
    519 * @plane: plane to cleanup
    520 *
    521 * This function cleans up @plane and removes it from the DRM mode setting
    522 * core. Note that the function does *not* free the plane structure itself,
    523 * this is the responsibility of the caller.
    524 */
    525void drm_plane_cleanup(struct drm_plane *plane)
    526{
    527	struct drm_device *dev = plane->dev;
    528
    529	drm_modeset_lock_fini(&plane->mutex);
    530
    531	kfree(plane->format_types);
    532	kfree(plane->modifiers);
    533	drm_mode_object_unregister(dev, &plane->base);
    534
    535	BUG_ON(list_empty(&plane->head));
    536
    537	/* Note that the plane_list is considered to be static; should we
    538	 * remove the drm_plane at runtime we would have to decrement all
    539	 * the indices on the drm_plane after us in the plane_list.
    540	 */
    541
    542	list_del(&plane->head);
    543	dev->mode_config.num_total_plane--;
    544
    545	WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
    546	if (plane->state && plane->funcs->atomic_destroy_state)
    547		plane->funcs->atomic_destroy_state(plane, plane->state);
    548
    549	kfree(plane->name);
    550
    551	memset(plane, 0, sizeof(*plane));
    552}
    553EXPORT_SYMBOL(drm_plane_cleanup);
    554
    555/**
    556 * drm_plane_from_index - find the registered plane at an index
    557 * @dev: DRM device
    558 * @idx: index of registered plane to find for
    559 *
    560 * Given a plane index, return the registered plane from DRM device's
    561 * list of planes with matching index. This is the inverse of drm_plane_index().
    562 */
    563struct drm_plane *
    564drm_plane_from_index(struct drm_device *dev, int idx)
    565{
    566	struct drm_plane *plane;
    567
    568	drm_for_each_plane(plane, dev)
    569		if (idx == plane->index)
    570			return plane;
    571
    572	return NULL;
    573}
    574EXPORT_SYMBOL(drm_plane_from_index);
    575
    576/**
    577 * drm_plane_force_disable - Forcibly disable a plane
    578 * @plane: plane to disable
    579 *
    580 * Forces the plane to be disabled.
    581 *
    582 * Used when the plane's current framebuffer is destroyed,
    583 * and when restoring fbdev mode.
    584 *
    585 * Note that this function is not suitable for atomic drivers, since it doesn't
    586 * wire through the lock acquisition context properly and hence can't handle
    587 * retries or driver private locks. You probably want to use
    588 * drm_atomic_helper_disable_plane() or
    589 * drm_atomic_helper_disable_planes_on_crtc() instead.
    590 */
    591void drm_plane_force_disable(struct drm_plane *plane)
    592{
    593	int ret;
    594
    595	if (!plane->fb)
    596		return;
    597
    598	WARN_ON(drm_drv_uses_atomic_modeset(plane->dev));
    599
    600	plane->old_fb = plane->fb;
    601	ret = plane->funcs->disable_plane(plane, NULL);
    602	if (ret) {
    603		DRM_ERROR("failed to disable plane with busy fb\n");
    604		plane->old_fb = NULL;
    605		return;
    606	}
    607	/* disconnect the plane from the fb and crtc: */
    608	drm_framebuffer_put(plane->old_fb);
    609	plane->old_fb = NULL;
    610	plane->fb = NULL;
    611	plane->crtc = NULL;
    612}
    613EXPORT_SYMBOL(drm_plane_force_disable);
    614
    615/**
    616 * drm_mode_plane_set_obj_prop - set the value of a property
    617 * @plane: drm plane object to set property value for
    618 * @property: property to set
    619 * @value: value the property should be set to
    620 *
    621 * This functions sets a given property on a given plane object. This function
    622 * calls the driver's ->set_property callback and changes the software state of
    623 * the property if the callback succeeds.
    624 *
    625 * Returns:
    626 * Zero on success, error code on failure.
    627 */
    628int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
    629				struct drm_property *property,
    630				uint64_t value)
    631{
    632	int ret = -EINVAL;
    633	struct drm_mode_object *obj = &plane->base;
    634
    635	if (plane->funcs->set_property)
    636		ret = plane->funcs->set_property(plane, property, value);
    637	if (!ret)
    638		drm_object_property_set_value(obj, property, value);
    639
    640	return ret;
    641}
    642EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
    643
    644int drm_mode_getplane_res(struct drm_device *dev, void *data,
    645			  struct drm_file *file_priv)
    646{
    647	struct drm_mode_get_plane_res *plane_resp = data;
    648	struct drm_plane *plane;
    649	uint32_t __user *plane_ptr;
    650	int count = 0;
    651
    652	if (!drm_core_check_feature(dev, DRIVER_MODESET))
    653		return -EOPNOTSUPP;
    654
    655	plane_ptr = u64_to_user_ptr(plane_resp->plane_id_ptr);
    656
    657	/*
    658	 * This ioctl is called twice, once to determine how much space is
    659	 * needed, and the 2nd time to fill it.
    660	 */
    661	drm_for_each_plane(plane, dev) {
    662		/*
    663		 * Unless userspace set the 'universal planes'
    664		 * capability bit, only advertise overlays.
    665		 */
    666		if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
    667		    !file_priv->universal_planes)
    668			continue;
    669
    670		if (drm_lease_held(file_priv, plane->base.id)) {
    671			if (count < plane_resp->count_planes &&
    672			    put_user(plane->base.id, plane_ptr + count))
    673				return -EFAULT;
    674			count++;
    675		}
    676	}
    677	plane_resp->count_planes = count;
    678
    679	return 0;
    680}
    681
    682int drm_mode_getplane(struct drm_device *dev, void *data,
    683		      struct drm_file *file_priv)
    684{
    685	struct drm_mode_get_plane *plane_resp = data;
    686	struct drm_plane *plane;
    687	uint32_t __user *format_ptr;
    688
    689	if (!drm_core_check_feature(dev, DRIVER_MODESET))
    690		return -EOPNOTSUPP;
    691
    692	plane = drm_plane_find(dev, file_priv, plane_resp->plane_id);
    693	if (!plane)
    694		return -ENOENT;
    695
    696	drm_modeset_lock(&plane->mutex, NULL);
    697	if (plane->state && plane->state->crtc && drm_lease_held(file_priv, plane->state->crtc->base.id))
    698		plane_resp->crtc_id = plane->state->crtc->base.id;
    699	else if (!plane->state && plane->crtc && drm_lease_held(file_priv, plane->crtc->base.id))
    700		plane_resp->crtc_id = plane->crtc->base.id;
    701	else
    702		plane_resp->crtc_id = 0;
    703
    704	if (plane->state && plane->state->fb)
    705		plane_resp->fb_id = plane->state->fb->base.id;
    706	else if (!plane->state && plane->fb)
    707		plane_resp->fb_id = plane->fb->base.id;
    708	else
    709		plane_resp->fb_id = 0;
    710	drm_modeset_unlock(&plane->mutex);
    711
    712	plane_resp->plane_id = plane->base.id;
    713	plane_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
    714							    plane->possible_crtcs);
    715
    716	plane_resp->gamma_size = 0;
    717
    718	/*
    719	 * This ioctl is called twice, once to determine how much space is
    720	 * needed, and the 2nd time to fill it.
    721	 */
    722	if (plane->format_count &&
    723	    (plane_resp->count_format_types >= plane->format_count)) {
    724		format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
    725		if (copy_to_user(format_ptr,
    726				 plane->format_types,
    727				 sizeof(uint32_t) * plane->format_count)) {
    728			return -EFAULT;
    729		}
    730	}
    731	plane_resp->count_format_types = plane->format_count;
    732
    733	return 0;
    734}
    735
    736int drm_plane_check_pixel_format(struct drm_plane *plane,
    737				 u32 format, u64 modifier)
    738{
    739	unsigned int i;
    740
    741	for (i = 0; i < plane->format_count; i++) {
    742		if (format == plane->format_types[i])
    743			break;
    744	}
    745	if (i == plane->format_count)
    746		return -EINVAL;
    747
    748	if (plane->funcs->format_mod_supported) {
    749		if (!plane->funcs->format_mod_supported(plane, format, modifier))
    750			return -EINVAL;
    751	} else {
    752		if (!plane->modifier_count)
    753			return 0;
    754
    755		for (i = 0; i < plane->modifier_count; i++) {
    756			if (modifier == plane->modifiers[i])
    757				break;
    758		}
    759		if (i == plane->modifier_count)
    760			return -EINVAL;
    761	}
    762
    763	return 0;
    764}
    765
    766static int __setplane_check(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			    uint32_t src_x, uint32_t src_y,
    772			    uint32_t src_w, uint32_t src_h)
    773{
    774	int ret;
    775
    776	/* Check whether this plane is usable on this CRTC */
    777	if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
    778		DRM_DEBUG_KMS("Invalid crtc for plane\n");
    779		return -EINVAL;
    780	}
    781
    782	/* Check whether this plane supports the fb pixel format. */
    783	ret = drm_plane_check_pixel_format(plane, fb->format->format,
    784					   fb->modifier);
    785	if (ret) {
    786		DRM_DEBUG_KMS("Invalid pixel format %p4cc, modifier 0x%llx\n",
    787			      &fb->format->format, fb->modifier);
    788		return ret;
    789	}
    790
    791	/* Give drivers some help against integer overflows */
    792	if (crtc_w > INT_MAX ||
    793	    crtc_x > INT_MAX - (int32_t) crtc_w ||
    794	    crtc_h > INT_MAX ||
    795	    crtc_y > INT_MAX - (int32_t) crtc_h) {
    796		DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
    797			      crtc_w, crtc_h, crtc_x, crtc_y);
    798		return -ERANGE;
    799	}
    800
    801	ret = drm_framebuffer_check_src_coords(src_x, src_y, src_w, src_h, fb);
    802	if (ret)
    803		return ret;
    804
    805	return 0;
    806}
    807
    808/**
    809 * drm_any_plane_has_format - Check whether any plane supports this format and modifier combination
    810 * @dev: DRM device
    811 * @format: pixel format (DRM_FORMAT_*)
    812 * @modifier: data layout modifier
    813 *
    814 * Returns:
    815 * Whether at least one plane supports the specified format and modifier combination.
    816 */
    817bool drm_any_plane_has_format(struct drm_device *dev,
    818			      u32 format, u64 modifier)
    819{
    820	struct drm_plane *plane;
    821
    822	drm_for_each_plane(plane, dev) {
    823		if (drm_plane_check_pixel_format(plane, format, modifier) == 0)
    824			return true;
    825	}
    826
    827	return false;
    828}
    829EXPORT_SYMBOL(drm_any_plane_has_format);
    830
    831/*
    832 * __setplane_internal - setplane handler for internal callers
    833 *
    834 * This function will take a reference on the new fb for the plane
    835 * on success.
    836 *
    837 * src_{x,y,w,h} are provided in 16.16 fixed point format
    838 */
    839static int __setplane_internal(struct drm_plane *plane,
    840			       struct drm_crtc *crtc,
    841			       struct drm_framebuffer *fb,
    842			       int32_t crtc_x, int32_t crtc_y,
    843			       uint32_t crtc_w, uint32_t crtc_h,
    844			       /* src_{x,y,w,h} values are 16.16 fixed point */
    845			       uint32_t src_x, uint32_t src_y,
    846			       uint32_t src_w, uint32_t src_h,
    847			       struct drm_modeset_acquire_ctx *ctx)
    848{
    849	int ret = 0;
    850
    851	WARN_ON(drm_drv_uses_atomic_modeset(plane->dev));
    852
    853	/* No fb means shut it down */
    854	if (!fb) {
    855		plane->old_fb = plane->fb;
    856		ret = plane->funcs->disable_plane(plane, ctx);
    857		if (!ret) {
    858			plane->crtc = NULL;
    859			plane->fb = NULL;
    860		} else {
    861			plane->old_fb = NULL;
    862		}
    863		goto out;
    864	}
    865
    866	ret = __setplane_check(plane, crtc, fb,
    867			       crtc_x, crtc_y, crtc_w, crtc_h,
    868			       src_x, src_y, src_w, src_h);
    869	if (ret)
    870		goto out;
    871
    872	plane->old_fb = plane->fb;
    873	ret = plane->funcs->update_plane(plane, crtc, fb,
    874					 crtc_x, crtc_y, crtc_w, crtc_h,
    875					 src_x, src_y, src_w, src_h, ctx);
    876	if (!ret) {
    877		plane->crtc = crtc;
    878		plane->fb = fb;
    879		drm_framebuffer_get(plane->fb);
    880	} else {
    881		plane->old_fb = NULL;
    882	}
    883
    884out:
    885	if (plane->old_fb)
    886		drm_framebuffer_put(plane->old_fb);
    887	plane->old_fb = NULL;
    888
    889	return ret;
    890}
    891
    892static int __setplane_atomic(struct drm_plane *plane,
    893			     struct drm_crtc *crtc,
    894			     struct drm_framebuffer *fb,
    895			     int32_t crtc_x, int32_t crtc_y,
    896			     uint32_t crtc_w, uint32_t crtc_h,
    897			     uint32_t src_x, uint32_t src_y,
    898			     uint32_t src_w, uint32_t src_h,
    899			     struct drm_modeset_acquire_ctx *ctx)
    900{
    901	int ret;
    902
    903	WARN_ON(!drm_drv_uses_atomic_modeset(plane->dev));
    904
    905	/* No fb means shut it down */
    906	if (!fb)
    907		return plane->funcs->disable_plane(plane, ctx);
    908
    909	/*
    910	 * FIXME: This is redundant with drm_atomic_plane_check(),
    911	 * but the legacy cursor/"async" .update_plane() tricks
    912	 * don't call that so we still need this here. Should remove
    913	 * this when all .update_plane() implementations have been
    914	 * fixed to call drm_atomic_plane_check().
    915	 */
    916	ret = __setplane_check(plane, crtc, fb,
    917			       crtc_x, crtc_y, crtc_w, crtc_h,
    918			       src_x, src_y, src_w, src_h);
    919	if (ret)
    920		return ret;
    921
    922	return plane->funcs->update_plane(plane, crtc, fb,
    923					  crtc_x, crtc_y, crtc_w, crtc_h,
    924					  src_x, src_y, src_w, src_h, ctx);
    925}
    926
    927static int setplane_internal(struct drm_plane *plane,
    928			     struct drm_crtc *crtc,
    929			     struct drm_framebuffer *fb,
    930			     int32_t crtc_x, int32_t crtc_y,
    931			     uint32_t crtc_w, uint32_t crtc_h,
    932			     /* src_{x,y,w,h} values are 16.16 fixed point */
    933			     uint32_t src_x, uint32_t src_y,
    934			     uint32_t src_w, uint32_t src_h)
    935{
    936	struct drm_modeset_acquire_ctx ctx;
    937	int ret;
    938
    939	DRM_MODESET_LOCK_ALL_BEGIN(plane->dev, ctx,
    940				   DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
    941
    942	if (drm_drv_uses_atomic_modeset(plane->dev))
    943		ret = __setplane_atomic(plane, crtc, fb,
    944					crtc_x, crtc_y, crtc_w, crtc_h,
    945					src_x, src_y, src_w, src_h, &ctx);
    946	else
    947		ret = __setplane_internal(plane, crtc, fb,
    948					  crtc_x, crtc_y, crtc_w, crtc_h,
    949					  src_x, src_y, src_w, src_h, &ctx);
    950
    951	DRM_MODESET_LOCK_ALL_END(plane->dev, ctx, ret);
    952
    953	return ret;
    954}
    955
    956int drm_mode_setplane(struct drm_device *dev, void *data,
    957		      struct drm_file *file_priv)
    958{
    959	struct drm_mode_set_plane *plane_req = data;
    960	struct drm_plane *plane;
    961	struct drm_crtc *crtc = NULL;
    962	struct drm_framebuffer *fb = NULL;
    963	int ret;
    964
    965	if (!drm_core_check_feature(dev, DRIVER_MODESET))
    966		return -EOPNOTSUPP;
    967
    968	/*
    969	 * First, find the plane, crtc, and fb objects.  If not available,
    970	 * we don't bother to call the driver.
    971	 */
    972	plane = drm_plane_find(dev, file_priv, plane_req->plane_id);
    973	if (!plane) {
    974		DRM_DEBUG_KMS("Unknown plane ID %d\n",
    975			      plane_req->plane_id);
    976		return -ENOENT;
    977	}
    978
    979	if (plane_req->fb_id) {
    980		fb = drm_framebuffer_lookup(dev, file_priv, plane_req->fb_id);
    981		if (!fb) {
    982			DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
    983				      plane_req->fb_id);
    984			return -ENOENT;
    985		}
    986
    987		crtc = drm_crtc_find(dev, file_priv, plane_req->crtc_id);
    988		if (!crtc) {
    989			drm_framebuffer_put(fb);
    990			DRM_DEBUG_KMS("Unknown crtc ID %d\n",
    991				      plane_req->crtc_id);
    992			return -ENOENT;
    993		}
    994	}
    995
    996	ret = setplane_internal(plane, crtc, fb,
    997				plane_req->crtc_x, plane_req->crtc_y,
    998				plane_req->crtc_w, plane_req->crtc_h,
    999				plane_req->src_x, plane_req->src_y,
   1000				plane_req->src_w, plane_req->src_h);
   1001
   1002	if (fb)
   1003		drm_framebuffer_put(fb);
   1004
   1005	return ret;
   1006}
   1007
   1008static int drm_mode_cursor_universal(struct drm_crtc *crtc,
   1009				     struct drm_mode_cursor2 *req,
   1010				     struct drm_file *file_priv,
   1011				     struct drm_modeset_acquire_ctx *ctx)
   1012{
   1013	struct drm_device *dev = crtc->dev;
   1014	struct drm_plane *plane = crtc->cursor;
   1015	struct drm_framebuffer *fb = NULL;
   1016	struct drm_mode_fb_cmd2 fbreq = {
   1017		.width = req->width,
   1018		.height = req->height,
   1019		.pixel_format = DRM_FORMAT_ARGB8888,
   1020		.pitches = { req->width * 4 },
   1021		.handles = { req->handle },
   1022	};
   1023	int32_t crtc_x, crtc_y;
   1024	uint32_t crtc_w = 0, crtc_h = 0;
   1025	uint32_t src_w = 0, src_h = 0;
   1026	int ret = 0;
   1027
   1028	BUG_ON(!plane);
   1029	WARN_ON(plane->crtc != crtc && plane->crtc != NULL);
   1030
   1031	/*
   1032	 * Obtain fb we'll be using (either new or existing) and take an extra
   1033	 * reference to it if fb != null.  setplane will take care of dropping
   1034	 * the reference if the plane update fails.
   1035	 */
   1036	if (req->flags & DRM_MODE_CURSOR_BO) {
   1037		if (req->handle) {
   1038			fb = drm_internal_framebuffer_create(dev, &fbreq, file_priv);
   1039			if (IS_ERR(fb)) {
   1040				DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
   1041				return PTR_ERR(fb);
   1042			}
   1043
   1044			fb->hot_x = req->hot_x;
   1045			fb->hot_y = req->hot_y;
   1046		} else {
   1047			fb = NULL;
   1048		}
   1049	} else {
   1050		if (plane->state)
   1051			fb = plane->state->fb;
   1052		else
   1053			fb = plane->fb;
   1054
   1055		if (fb)
   1056			drm_framebuffer_get(fb);
   1057	}
   1058
   1059	if (req->flags & DRM_MODE_CURSOR_MOVE) {
   1060		crtc_x = req->x;
   1061		crtc_y = req->y;
   1062	} else {
   1063		crtc_x = crtc->cursor_x;
   1064		crtc_y = crtc->cursor_y;
   1065	}
   1066
   1067	if (fb) {
   1068		crtc_w = fb->width;
   1069		crtc_h = fb->height;
   1070		src_w = fb->width << 16;
   1071		src_h = fb->height << 16;
   1072	}
   1073
   1074	if (drm_drv_uses_atomic_modeset(dev))
   1075		ret = __setplane_atomic(plane, crtc, fb,
   1076					crtc_x, crtc_y, crtc_w, crtc_h,
   1077					0, 0, src_w, src_h, ctx);
   1078	else
   1079		ret = __setplane_internal(plane, crtc, fb,
   1080					  crtc_x, crtc_y, crtc_w, crtc_h,
   1081					  0, 0, src_w, src_h, ctx);
   1082
   1083	if (fb)
   1084		drm_framebuffer_put(fb);
   1085
   1086	/* Update successful; save new cursor position, if necessary */
   1087	if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
   1088		crtc->cursor_x = req->x;
   1089		crtc->cursor_y = req->y;
   1090	}
   1091
   1092	return ret;
   1093}
   1094
   1095static int drm_mode_cursor_common(struct drm_device *dev,
   1096				  struct drm_mode_cursor2 *req,
   1097				  struct drm_file *file_priv)
   1098{
   1099	struct drm_crtc *crtc;
   1100	struct drm_modeset_acquire_ctx ctx;
   1101	int ret = 0;
   1102
   1103	if (!drm_core_check_feature(dev, DRIVER_MODESET))
   1104		return -EOPNOTSUPP;
   1105
   1106	if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
   1107		return -EINVAL;
   1108
   1109	crtc = drm_crtc_find(dev, file_priv, req->crtc_id);
   1110	if (!crtc) {
   1111		DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
   1112		return -ENOENT;
   1113	}
   1114
   1115	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
   1116retry:
   1117	ret = drm_modeset_lock(&crtc->mutex, &ctx);
   1118	if (ret)
   1119		goto out;
   1120	/*
   1121	 * If this crtc has a universal cursor plane, call that plane's update
   1122	 * handler rather than using legacy cursor handlers.
   1123	 */
   1124	if (crtc->cursor) {
   1125		ret = drm_modeset_lock(&crtc->cursor->mutex, &ctx);
   1126		if (ret)
   1127			goto out;
   1128
   1129		if (!drm_lease_held(file_priv, crtc->cursor->base.id)) {
   1130			ret = -EACCES;
   1131			goto out;
   1132		}
   1133
   1134		ret = drm_mode_cursor_universal(crtc, req, file_priv, &ctx);
   1135		goto out;
   1136	}
   1137
   1138	if (req->flags & DRM_MODE_CURSOR_BO) {
   1139		if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
   1140			ret = -ENXIO;
   1141			goto out;
   1142		}
   1143		/* Turns off the cursor if handle is 0 */
   1144		if (crtc->funcs->cursor_set2)
   1145			ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle,
   1146						      req->width, req->height, req->hot_x, req->hot_y);
   1147		else
   1148			ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
   1149						      req->width, req->height);
   1150	}
   1151
   1152	if (req->flags & DRM_MODE_CURSOR_MOVE) {
   1153		if (crtc->funcs->cursor_move) {
   1154			ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
   1155		} else {
   1156			ret = -EFAULT;
   1157			goto out;
   1158		}
   1159	}
   1160out:
   1161	if (ret == -EDEADLK) {
   1162		ret = drm_modeset_backoff(&ctx);
   1163		if (!ret)
   1164			goto retry;
   1165	}
   1166
   1167	drm_modeset_drop_locks(&ctx);
   1168	drm_modeset_acquire_fini(&ctx);
   1169
   1170	return ret;
   1171
   1172}
   1173
   1174
   1175int drm_mode_cursor_ioctl(struct drm_device *dev,
   1176			  void *data, struct drm_file *file_priv)
   1177{
   1178	struct drm_mode_cursor *req = data;
   1179	struct drm_mode_cursor2 new_req;
   1180
   1181	memcpy(&new_req, req, sizeof(struct drm_mode_cursor));
   1182	new_req.hot_x = new_req.hot_y = 0;
   1183
   1184	return drm_mode_cursor_common(dev, &new_req, file_priv);
   1185}
   1186
   1187/*
   1188 * Set the cursor configuration based on user request. This implements the 2nd
   1189 * version of the cursor ioctl, which allows userspace to additionally specify
   1190 * the hotspot of the pointer.
   1191 */
   1192int drm_mode_cursor2_ioctl(struct drm_device *dev,
   1193			   void *data, struct drm_file *file_priv)
   1194{
   1195	struct drm_mode_cursor2 *req = data;
   1196
   1197	return drm_mode_cursor_common(dev, req, file_priv);
   1198}
   1199
   1200int drm_mode_page_flip_ioctl(struct drm_device *dev,
   1201			     void *data, struct drm_file *file_priv)
   1202{
   1203	struct drm_mode_crtc_page_flip_target *page_flip = data;
   1204	struct drm_crtc *crtc;
   1205	struct drm_plane *plane;
   1206	struct drm_framebuffer *fb = NULL, *old_fb;
   1207	struct drm_pending_vblank_event *e = NULL;
   1208	u32 target_vblank = page_flip->sequence;
   1209	struct drm_modeset_acquire_ctx ctx;
   1210	int ret = -EINVAL;
   1211
   1212	if (!drm_core_check_feature(dev, DRIVER_MODESET))
   1213		return -EOPNOTSUPP;
   1214
   1215	if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS)
   1216		return -EINVAL;
   1217
   1218	if (page_flip->sequence != 0 && !(page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET))
   1219		return -EINVAL;
   1220
   1221	/* Only one of the DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags
   1222	 * can be specified
   1223	 */
   1224	if ((page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) == DRM_MODE_PAGE_FLIP_TARGET)
   1225		return -EINVAL;
   1226
   1227	if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
   1228		return -EINVAL;
   1229
   1230	crtc = drm_crtc_find(dev, file_priv, page_flip->crtc_id);
   1231	if (!crtc)
   1232		return -ENOENT;
   1233
   1234	plane = crtc->primary;
   1235
   1236	if (!drm_lease_held(file_priv, plane->base.id))
   1237		return -EACCES;
   1238
   1239	if (crtc->funcs->page_flip_target) {
   1240		u32 current_vblank;
   1241		int r;
   1242
   1243		r = drm_crtc_vblank_get(crtc);
   1244		if (r)
   1245			return r;
   1246
   1247		current_vblank = (u32)drm_crtc_vblank_count(crtc);
   1248
   1249		switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) {
   1250		case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE:
   1251			if ((int)(target_vblank - current_vblank) > 1) {
   1252				DRM_DEBUG("Invalid absolute flip target %u, "
   1253					  "must be <= %u\n", target_vblank,
   1254					  current_vblank + 1);
   1255				drm_crtc_vblank_put(crtc);
   1256				return -EINVAL;
   1257			}
   1258			break;
   1259		case DRM_MODE_PAGE_FLIP_TARGET_RELATIVE:
   1260			if (target_vblank != 0 && target_vblank != 1) {
   1261				DRM_DEBUG("Invalid relative flip target %u, "
   1262					  "must be 0 or 1\n", target_vblank);
   1263				drm_crtc_vblank_put(crtc);
   1264				return -EINVAL;
   1265			}
   1266			target_vblank += current_vblank;
   1267			break;
   1268		default:
   1269			target_vblank = current_vblank +
   1270				!(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC);
   1271			break;
   1272		}
   1273	} else if (crtc->funcs->page_flip == NULL ||
   1274		   (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) {
   1275		return -EINVAL;
   1276	}
   1277
   1278	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
   1279retry:
   1280	ret = drm_modeset_lock(&crtc->mutex, &ctx);
   1281	if (ret)
   1282		goto out;
   1283	ret = drm_modeset_lock(&plane->mutex, &ctx);
   1284	if (ret)
   1285		goto out;
   1286
   1287	if (plane->state)
   1288		old_fb = plane->state->fb;
   1289	else
   1290		old_fb = plane->fb;
   1291
   1292	if (old_fb == NULL) {
   1293		/* The framebuffer is currently unbound, presumably
   1294		 * due to a hotplug event, that userspace has not
   1295		 * yet discovered.
   1296		 */
   1297		ret = -EBUSY;
   1298		goto out;
   1299	}
   1300
   1301	fb = drm_framebuffer_lookup(dev, file_priv, page_flip->fb_id);
   1302	if (!fb) {
   1303		ret = -ENOENT;
   1304		goto out;
   1305	}
   1306
   1307	if (plane->state) {
   1308		const struct drm_plane_state *state = plane->state;
   1309
   1310		ret = drm_framebuffer_check_src_coords(state->src_x,
   1311						       state->src_y,
   1312						       state->src_w,
   1313						       state->src_h,
   1314						       fb);
   1315	} else {
   1316		ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y,
   1317					      &crtc->mode, fb);
   1318	}
   1319	if (ret)
   1320		goto out;
   1321
   1322	/*
   1323	 * Only check the FOURCC format code, excluding modifiers. This is
   1324	 * enough for all legacy drivers. Atomic drivers have their own
   1325	 * checks in their ->atomic_check implementation, which will
   1326	 * return -EINVAL if any hw or driver constraint is violated due
   1327	 * to modifier changes.
   1328	 */
   1329	if (old_fb->format->format != fb->format->format) {
   1330		DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
   1331		ret = -EINVAL;
   1332		goto out;
   1333	}
   1334
   1335	if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
   1336		e = kzalloc(sizeof *e, GFP_KERNEL);
   1337		if (!e) {
   1338			ret = -ENOMEM;
   1339			goto out;
   1340		}
   1341
   1342		e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
   1343		e->event.base.length = sizeof(e->event);
   1344		e->event.vbl.user_data = page_flip->user_data;
   1345		e->event.vbl.crtc_id = crtc->base.id;
   1346
   1347		ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
   1348		if (ret) {
   1349			kfree(e);
   1350			e = NULL;
   1351			goto out;
   1352		}
   1353	}
   1354
   1355	plane->old_fb = plane->fb;
   1356	if (crtc->funcs->page_flip_target)
   1357		ret = crtc->funcs->page_flip_target(crtc, fb, e,
   1358						    page_flip->flags,
   1359						    target_vblank,
   1360						    &ctx);
   1361	else
   1362		ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags,
   1363					     &ctx);
   1364	if (ret) {
   1365		if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
   1366			drm_event_cancel_free(dev, &e->base);
   1367		/* Keep the old fb, don't unref it. */
   1368		plane->old_fb = NULL;
   1369	} else {
   1370		if (!plane->state) {
   1371			plane->fb = fb;
   1372			drm_framebuffer_get(fb);
   1373		}
   1374	}
   1375
   1376out:
   1377	if (fb)
   1378		drm_framebuffer_put(fb);
   1379	if (plane->old_fb)
   1380		drm_framebuffer_put(plane->old_fb);
   1381	plane->old_fb = NULL;
   1382
   1383	if (ret == -EDEADLK) {
   1384		ret = drm_modeset_backoff(&ctx);
   1385		if (!ret)
   1386			goto retry;
   1387	}
   1388
   1389	drm_modeset_drop_locks(&ctx);
   1390	drm_modeset_acquire_fini(&ctx);
   1391
   1392	if (ret && crtc->funcs->page_flip_target)
   1393		drm_crtc_vblank_put(crtc);
   1394
   1395	return ret;
   1396}
   1397
   1398/**
   1399 * DOC: damage tracking
   1400 *
   1401 * FB_DAMAGE_CLIPS is an optional plane property which provides a means to
   1402 * specify a list of damage rectangles on a plane in framebuffer coordinates of
   1403 * the framebuffer attached to the plane. In current context damage is the area
   1404 * of plane framebuffer that has changed since last plane update (also called
   1405 * page-flip), irrespective of whether currently attached framebuffer is same as
   1406 * framebuffer attached during last plane update or not.
   1407 *
   1408 * FB_DAMAGE_CLIPS is a hint to kernel which could be helpful for some drivers
   1409 * to optimize internally especially for virtual devices where each framebuffer
   1410 * change needs to be transmitted over network, usb, etc.
   1411 *
   1412 * Since FB_DAMAGE_CLIPS is a hint so it is an optional property. User-space can
   1413 * ignore damage clips property and in that case driver will do a full plane
   1414 * update. In case damage clips are provided then it is guaranteed that the area
   1415 * inside damage clips will be updated to plane. For efficiency driver can do
   1416 * full update or can update more than specified in damage clips. Since driver
   1417 * is free to read more, user-space must always render the entire visible
   1418 * framebuffer. Otherwise there can be corruptions. Also, if a user-space
   1419 * provides damage clips which doesn't encompass the actual damage to
   1420 * framebuffer (since last plane update) can result in incorrect rendering.
   1421 *
   1422 * FB_DAMAGE_CLIPS is a blob property with the layout of blob data is simply an
   1423 * array of &drm_mode_rect. Unlike plane &drm_plane_state.src coordinates,
   1424 * damage clips are not in 16.16 fixed point. Similar to plane src in
   1425 * framebuffer, damage clips cannot be negative. In damage clip, x1/y1 are
   1426 * inclusive and x2/y2 are exclusive. While kernel does not error for overlapped
   1427 * damage clips, it is strongly discouraged.
   1428 *
   1429 * Drivers that are interested in damage interface for plane should enable
   1430 * FB_DAMAGE_CLIPS property by calling drm_plane_enable_fb_damage_clips().
   1431 * Drivers implementing damage can use drm_atomic_helper_damage_iter_init() and
   1432 * drm_atomic_helper_damage_iter_next() helper iterator function to get damage
   1433 * rectangles clipped to &drm_plane_state.src.
   1434 */
   1435
   1436/**
   1437 * drm_plane_enable_fb_damage_clips - Enables plane fb damage clips property.
   1438 * @plane: Plane on which to enable damage clips property.
   1439 *
   1440 * This function lets driver to enable the damage clips property on a plane.
   1441 */
   1442void drm_plane_enable_fb_damage_clips(struct drm_plane *plane)
   1443{
   1444	struct drm_device *dev = plane->dev;
   1445	struct drm_mode_config *config = &dev->mode_config;
   1446
   1447	drm_object_attach_property(&plane->base, config->prop_fb_damage_clips,
   1448				   0);
   1449}
   1450EXPORT_SYMBOL(drm_plane_enable_fb_damage_clips);
   1451
   1452/**
   1453 * drm_plane_get_damage_clips_count - Returns damage clips count.
   1454 * @state: Plane state.
   1455 *
   1456 * Simple helper to get the number of &drm_mode_rect clips set by user-space
   1457 * during plane update.
   1458 *
   1459 * Return: Number of clips in plane fb_damage_clips blob property.
   1460 */
   1461unsigned int
   1462drm_plane_get_damage_clips_count(const struct drm_plane_state *state)
   1463{
   1464	return (state && state->fb_damage_clips) ?
   1465		state->fb_damage_clips->length/sizeof(struct drm_mode_rect) : 0;
   1466}
   1467EXPORT_SYMBOL(drm_plane_get_damage_clips_count);
   1468
   1469struct drm_mode_rect *
   1470__drm_plane_get_damage_clips(const struct drm_plane_state *state)
   1471{
   1472	return (struct drm_mode_rect *)((state && state->fb_damage_clips) ?
   1473					state->fb_damage_clips->data : NULL);
   1474}
   1475
   1476/**
   1477 * drm_plane_get_damage_clips - Returns damage clips.
   1478 * @state: Plane state.
   1479 *
   1480 * Note that this function returns uapi type &drm_mode_rect. Drivers might want
   1481 * to use the helper functions drm_atomic_helper_damage_iter_init() and
   1482 * drm_atomic_helper_damage_iter_next() or drm_atomic_helper_damage_merged() if
   1483 * the driver can only handle a single damage region at most.
   1484 *
   1485 * Return: Damage clips in plane fb_damage_clips blob property.
   1486 */
   1487struct drm_mode_rect *
   1488drm_plane_get_damage_clips(const struct drm_plane_state *state)
   1489{
   1490	struct drm_device *dev = state->plane->dev;
   1491	struct drm_mode_config *config = &dev->mode_config;
   1492
   1493	/* check that drm_plane_enable_fb_damage_clips() was called */
   1494	if (!drm_mode_obj_find_prop_id(&state->plane->base,
   1495				       config->prop_fb_damage_clips->base.id))
   1496		drm_warn_once(dev, "drm_plane_enable_fb_damage_clips() not called\n");
   1497
   1498	return __drm_plane_get_damage_clips(state);
   1499}
   1500EXPORT_SYMBOL(drm_plane_get_damage_clips);
   1501
   1502struct drm_property *
   1503drm_create_scaling_filter_prop(struct drm_device *dev,
   1504			       unsigned int supported_filters)
   1505{
   1506	struct drm_property *prop;
   1507	static const struct drm_prop_enum_list props[] = {
   1508		{ DRM_SCALING_FILTER_DEFAULT, "Default" },
   1509		{ DRM_SCALING_FILTER_NEAREST_NEIGHBOR, "Nearest Neighbor" },
   1510	};
   1511	unsigned int valid_mode_mask = BIT(DRM_SCALING_FILTER_DEFAULT) |
   1512				       BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR);
   1513	int i;
   1514
   1515	if (WARN_ON((supported_filters & ~valid_mode_mask) ||
   1516		    ((supported_filters & BIT(DRM_SCALING_FILTER_DEFAULT)) == 0)))
   1517		return ERR_PTR(-EINVAL);
   1518
   1519	prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
   1520				   "SCALING_FILTER",
   1521				   hweight32(supported_filters));
   1522	if (!prop)
   1523		return ERR_PTR(-ENOMEM);
   1524
   1525	for (i = 0; i < ARRAY_SIZE(props); i++) {
   1526		int ret;
   1527
   1528		if (!(BIT(props[i].type) & supported_filters))
   1529			continue;
   1530
   1531		ret = drm_property_add_enum(prop, props[i].type,
   1532					    props[i].name);
   1533
   1534		if (ret) {
   1535			drm_property_destroy(dev, prop);
   1536
   1537			return ERR_PTR(ret);
   1538		}
   1539	}
   1540
   1541	return prop;
   1542}
   1543
   1544/**
   1545 * drm_plane_create_scaling_filter_property - create a new scaling filter
   1546 * property
   1547 *
   1548 * @plane: drm plane
   1549 * @supported_filters: bitmask of supported scaling filters, must include
   1550 *		       BIT(DRM_SCALING_FILTER_DEFAULT).
   1551 *
   1552 * This function lets driver to enable the scaling filter property on a given
   1553 * plane.
   1554 *
   1555 * RETURNS:
   1556 * Zero for success or -errno
   1557 */
   1558int drm_plane_create_scaling_filter_property(struct drm_plane *plane,
   1559					     unsigned int supported_filters)
   1560{
   1561	struct drm_property *prop =
   1562		drm_create_scaling_filter_prop(plane->dev, supported_filters);
   1563
   1564	if (IS_ERR(prop))
   1565		return PTR_ERR(prop);
   1566
   1567	drm_object_attach_property(&plane->base, prop,
   1568				   DRM_SCALING_FILTER_DEFAULT);
   1569	plane->scaling_filter_property = prop;
   1570
   1571	return 0;
   1572}
   1573EXPORT_SYMBOL(drm_plane_create_scaling_filter_property);