File Index
Files and directories
Sign in
FILE

drm_plane.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/drm_plane.c C
   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/export.h>
  24#include <linux/slab.h>
  25#include <linux/uaccess.h>
  26
  27#include <drm/drm_plane.h>
  28#include <drm/drm_drv.h>
  29#include <drm/drm_print.h>
  30#include <drm/drm_framebuffer.h>
  31#include <drm/drm_file.h>
  32#include <drm/drm_crtc.h>
  33#include <drm/drm_fourcc.h>
  34#include <drm/drm_managed.h>
  35#include <drm/drm_vblank.h>
  36
  37#include "drm_crtc_internal.h"
  38
  39/**
  40 * DOC: overview
  41 *
  42 * A plane represents an image source that can be blended with or overlaid on
  43 * top of a CRTC during the scanout process. Planes take their input data from a
  44 * &drm_framebuffer object. The plane itself specifies the cropping and scaling
  45 * of that image, and where it is placed on the visible area of a display
  46 * pipeline, represented by &drm_crtc. A plane can also have additional
  47 * properties that specify how the pixels are positioned and blended, like
  48 * rotation or Z-position. All these properties are stored in &drm_plane_state.
  49 *
  50 * Unless explicitly specified (via CRTC property or otherwise), the active area
  51 * of a CRTC will be black by default. This means portions of the active area
  52 * which are not covered by a plane will be black, and alpha blending of any
  53 * planes with the CRTC background will blend with black at the lowest zpos.
  54 *
  55 * To create a plane, a KMS drivers allocates and zeroes an instances of
  56 * &struct drm_plane (possibly as part of a larger structure) and registers it
  57 * with a call to drm_universal_plane_init().
  58 *
  59 * Each plane has a type, see enum drm_plane_type. A plane can be compatible
  60 * with multiple CRTCs, see &drm_plane.possible_crtcs.
  61 *
  62 * Each CRTC must have a unique primary plane userspace can attach to enable
  63 * the CRTC. In other words, userspace must be able to attach a different
  64 * primary plane to each CRTC at the same time. Primary planes can still be
  65 * compatible with multiple CRTCs. There must be exactly as many primary planes
  66 * as there are CRTCs.
  67 *
  68 * Legacy uAPI doesn't expose the primary and cursor planes directly. DRM core
  69 * relies on the driver to set the primary and optionally the cursor plane used
  70 * for legacy IOCTLs. This is done by calling drm_crtc_init_with_planes(). All
  71 * drivers must provide one primary plane per CRTC to avoid surprising legacy
  72 * userspace too much.
  73 */
  74
  75/**
  76 * DOC: standard plane properties
  77 *
  78 * DRM planes have a few standardized properties:
  79 *
  80 * type:
  81 *     Immutable property describing the type of the plane.
  82 *
  83 *     For user-space which has enabled the &DRM_CLIENT_CAP_ATOMIC capability,
  84 *     the plane type is just a hint and is mostly superseded by atomic
  85 *     test-only commits. The type hint can still be used to come up more
  86 *     easily with a plane configuration accepted by the driver.
  87 *
  88 *     The value of this property can be one of the following:
  89 *
  90 *     "Primary":
  91 *         To light up a CRTC, attaching a primary plane is the most likely to
  92 *         work if it covers the whole CRTC and doesn't have scaling or
  93 *         cropping set up.
  94 *
  95 *         Drivers may support more features for the primary plane, user-space
  96 *         can find out with test-only atomic commits.
  97 *
  98 *         Some primary planes are implicitly used by the kernel in the legacy
  99 *         IOCTLs &DRM_IOCTL_MODE_SETCRTC and &DRM_IOCTL_MODE_PAGE_FLIP.
 100 *         Therefore user-space must not mix explicit usage of any primary
 101 *         plane (e.g. through an atomic commit) with these legacy IOCTLs.
 102 *
 103 *     "Cursor":
 104 *         To enable this plane, using a framebuffer configured without scaling
 105 *         or cropping and with the following properties is the most likely to
 106 *         work:
 107 *
 108 *         - If the driver provides the capabilities &DRM_CAP_CURSOR_WIDTH and
 109 *           &DRM_CAP_CURSOR_HEIGHT, create the framebuffer with this size.
 110 *           Otherwise, create a framebuffer with the size 64x64.
 111 *         - If the driver doesn't support modifiers, create a framebuffer with
 112 *           a linear layout. Otherwise, use the IN_FORMATS plane property.
 113 *
 114 *         Drivers may support more features for the cursor plane, user-space
 115 *         can find out with test-only atomic commits.
 116 *
 117 *         Some cursor planes are implicitly used by the kernel in the legacy
 118 *         IOCTLs &DRM_IOCTL_MODE_CURSOR and &DRM_IOCTL_MODE_CURSOR2.
 119 *         Therefore user-space must not mix explicit usage of any cursor
 120 *         plane (e.g. through an atomic commit) with these legacy IOCTLs.
 121 *
 122 *         Some drivers may support cursors even if no cursor plane is exposed.
 123 *         In this case, the legacy cursor IOCTLs can be used to configure the
 124 *         cursor.
 125 *
 126 *     "Overlay":
 127 *         Neither primary nor cursor.
 128 *
 129 *         Overlay planes are the only planes exposed when the
 130 *         &DRM_CLIENT_CAP_UNIVERSAL_PLANES capability is disabled.
 131 *
 132 * IN_FORMATS:
 133 *     Blob property which contains the set of buffer format and modifier
 134 *     pairs supported by this plane. The blob is a struct
 135 *     drm_format_modifier_blob. Without this property the plane doesn't
 136 *     support buffers with modifiers. Userspace cannot change this property.
 137 *
 138 *     Note that userspace can check the &DRM_CAP_ADDFB2_MODIFIERS driver
 139 *     capability for general modifier support. If this flag is set then every
 140 *     plane will have the IN_FORMATS property, even when it only supports
 141 *     DRM_FORMAT_MOD_LINEAR. Before linux kernel release v5.1 there have been
 142 *     various bugs in this area with inconsistencies between the capability
 143 *     flag and per-plane properties.
 144 *
 145 * IN_FORMATS_ASYNC:
 146 *     Blob property which contains the set of buffer format and modifier
 147 *     pairs supported by this plane for asynchronous flips. The blob is a struct
 148 *     drm_format_modifier_blob. Userspace cannot change this property. This is an
 149 *     optional property and if not present then user should expect a failure in
 150 *     atomic ioctl when the modifier/format is not supported by that plane under
 151 *     asynchronous flip.
 152 *
 153 * SIZE_HINTS:
 154 *     Blob property which contains the set of recommended plane size
 155 *     which can used for simple "cursor like" use cases (eg. no scaling).
 156 *     Using these hints frees userspace from extensive probing of
 157 *     supported plane sizes through atomic/setcursor ioctls.
 158 *
 159 *     The blob contains an array of struct drm_plane_size_hint, in
 160 *     order of preference. For optimal usage userspace should pick
 161 *     the first size that satisfies its own requirements.
 162 *
 163 *     Drivers should only attach this property to planes that
 164 *     support a very limited set of sizes.
 165 *
 166 *     Note that property value 0 (ie. no blob) is reserved for potential
 167 *     future use. Current userspace is expected to ignore the property
 168 *     if the value is 0, and fall back to some other means (eg.
 169 *     &DRM_CAP_CURSOR_WIDTH and &DRM_CAP_CURSOR_HEIGHT) to determine
 170 *     the appropriate plane size to use.
 171 */
 172
 173static unsigned int drm_num_planes(struct drm_device *dev)
 174{
 175	unsigned int num = 0;
 176	struct drm_plane *tmp;
 177
 178	drm_for_each_plane(tmp, dev) {
 179		num++;
 180	}
 181
 182	return num;
 183}
 184
 185static inline u32 *
 186formats_ptr(struct drm_format_modifier_blob *blob)
 187{
 188	return (u32 *)(((char *)blob) + blob->formats_offset);
 189}
 190
 191static inline struct drm_format_modifier *
 192modifiers_ptr(struct drm_format_modifier_blob *blob)
 193{
 194	return (struct drm_format_modifier *)(((char *)blob) + blob->modifiers_offset);
 195}
 196
 197static struct drm_property_blob *create_in_format_blob(struct drm_device *dev,
 198						       struct drm_plane *plane,
 199						       bool (*format_mod_supported)
 200						       (struct drm_plane *plane,
 201							u32 format,
 202							u64 modifier))
 203{
 204	struct drm_property_blob *blob;
 205	struct drm_format_modifier *mod;
 206	size_t blob_size, formats_size, modifiers_size;
 207	struct drm_format_modifier_blob *blob_data;
 208	unsigned int i, j;
 209
 210	formats_size = sizeof(__u32) * plane->format_count;
 211	if (WARN_ON(!formats_size)) {
 212		/* 0 formats are never expected */
 213		return ERR_PTR(-EINVAL);
 214	}
 215
 216	modifiers_size =
 217		sizeof(struct drm_format_modifier) * plane->modifier_count;
 218
 219	blob_size = sizeof(struct drm_format_modifier_blob);
 220	/* Modifiers offset is a pointer to a struct with a 64 bit field so it
 221	 * should be naturally aligned to 8B.
 222	 */
 223	BUILD_BUG_ON(sizeof(struct drm_format_modifier_blob) % 8);
 224	blob_size += ALIGN(formats_size, 8);
 225	blob_size += modifiers_size;
 226
 227	blob = drm_property_create_blob(dev, blob_size, NULL);
 228	if (IS_ERR(blob))
 229		return blob;
 230
 231	blob_data = blob->data;
 232	blob_data->version = FORMAT_BLOB_CURRENT;
 233	blob_data->count_formats = plane->format_count;
 234	blob_data->formats_offset = sizeof(struct drm_format_modifier_blob);
 235	blob_data->count_modifiers = plane->modifier_count;
 236
 237	blob_data->modifiers_offset =
 238		ALIGN(blob_data->formats_offset + formats_size, 8);
 239
 240	memcpy(formats_ptr(blob_data), plane->format_types, formats_size);
 241
 242	mod = modifiers_ptr(blob_data);
 243	for (i = 0; i < plane->modifier_count; i++) {
 244		for (j = 0; j < plane->format_count; j++) {
 245			if (!format_mod_supported ||
 246			    format_mod_supported(plane,
 247						 plane->format_types[j],
 248						 plane->modifiers[i])) {
 249				mod->formats |= 1ULL << j;
 250			}
 251		}
 252
 253		mod->modifier = plane->modifiers[i];
 254		mod->offset = 0;
 255		mod->pad = 0;
 256		mod++;
 257	}
 258
 259	return blob;
 260}
 261
 262/**
 263 * DOC: hotspot properties
 264 *
 265 * HOTSPOT_X: property to set mouse hotspot x offset.
 266 * HOTSPOT_Y: property to set mouse hotspot y offset.
 267 *
 268 * When the plane is being used as a cursor image to display a mouse pointer,
 269 * the "hotspot" is the offset within the cursor image where mouse events
 270 * are expected to go.
 271 *
 272 * Positive values move the hotspot from the top-left corner of the cursor
 273 * plane towards the right and bottom.
 274 *
 275 * Most display drivers do not need this information because the
 276 * hotspot is not actually connected to anything visible on screen.
 277 * However, this is necessary for display drivers like the para-virtualized
 278 * drivers (eg qxl, vbox, virtio, vmwgfx), that are attached to a user console
 279 * with a mouse pointer.  Since these consoles are often being remoted over a
 280 * network, they would otherwise have to wait to display the pointer movement to
 281 * the user until a full network round-trip has occurred.  New mouse events have
 282 * to be sent from the user's console, over the network to the virtual input
 283 * devices, forwarded to the desktop for processing, and then the cursor plane's
 284 * position can be updated and sent back to the user's console over the network.
 285 * Instead, with the hotspot information, the console can anticipate the new
 286 * location, and draw the mouse cursor there before the confirmation comes in.
 287 * To do that correctly, the user's console must be able predict how the
 288 * desktop will process mouse events, which normally requires the desktop's
 289 * mouse topology information, ie where each CRTC sits in the mouse coordinate
 290 * space.  This is typically sent to the para-virtualized drivers using some
 291 * driver-specific method, and the driver then forwards it to the console by
 292 * way of the virtual display device or hypervisor.
 293 *
 294 * The assumption is generally made that there is only one cursor plane being
 295 * used this way at a time, and that the desktop is feeding all mouse devices
 296 * into the same global pointer.  Para-virtualized drivers that require this
 297 * should only be exposing a single cursor plane, or find some other way
 298 * to coordinate with a userspace desktop that supports multiple pointers.
 299 * If the hotspot properties are set, the cursor plane is therefore assumed to be
 300 * used only for displaying a mouse cursor image, and the position of the combined
 301 * cursor plane + offset can therefore be used for coordinating with input from a
 302 * mouse device.
 303 *
 304 * The cursor will then be drawn either at the location of the plane in the CRTC
 305 * console, or as a free-floating cursor plane on the user's console
 306 * corresponding to their desktop mouse position.
 307 *
 308 * DRM clients which would like to work correctly on drivers which expose
 309 * hotspot properties should advertise DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT.
 310 * Setting this property on drivers which do not special case
 311 * cursor planes will return EOPNOTSUPP, which can be used by userspace to
 312 * gauge requirements of the hardware/drivers they're running on. Advertising
 313 * DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT implies that the userspace client will be
 314 * correctly setting the hotspot properties.
 315 */
 316
 317/**
 318 * drm_plane_create_hotspot_properties - creates the mouse hotspot
 319 * properties and attaches them to the given cursor plane
 320 *
 321 * @plane: drm cursor plane
 322 *
 323 * This function enables the mouse hotspot property on a given
 324 * cursor plane. Look at the documentation for hotspot properties
 325 * to get a better understanding for what they're used for.
 326 *
 327 * RETURNS:
 328 * Zero for success or -errno
 329 */
 330static int drm_plane_create_hotspot_properties(struct drm_plane *plane)
 331{
 332	struct drm_property *prop_x;
 333	struct drm_property *prop_y;
 334
 335	drm_WARN_ON(plane->dev,
 336		    !drm_core_check_feature(plane->dev,
 337					    DRIVER_CURSOR_HOTSPOT));
 338
 339	prop_x = drm_property_create_signed_range(plane->dev, 0, "HOTSPOT_X",
 340						  INT_MIN, INT_MAX);
 341	if (!prop_x)
 342		return -ENOMEM;
 343
 344	prop_y = drm_property_create_signed_range(plane->dev, 0, "HOTSPOT_Y",
 345						  INT_MIN, INT_MAX);
 346	if (!prop_y) {
 347		drm_property_destroy(plane->dev, prop_x);
 348		return -ENOMEM;
 349	}
 350
 351	drm_object_attach_property(&plane->base, prop_x, 0);
 352	drm_object_attach_property(&plane->base, prop_y, 0);
 353	plane->hotspot_x_property = prop_x;
 354	plane->hotspot_y_property = prop_y;
 355
 356	return 0;
 357}
 358
 359__printf(9, 0)
 360static int __drm_universal_plane_init(struct drm_device *dev,
 361				      struct drm_plane *plane,
 362				      uint32_t possible_crtcs,
 363				      const struct drm_plane_funcs *funcs,
 364				      const uint32_t *formats,
 365				      unsigned int format_count,
 366				      const uint64_t *format_modifiers,
 367				      enum drm_plane_type type,
 368				      const char *name, va_list ap)
 369{
 370	struct drm_mode_config *config = &dev->mode_config;
 371	struct drm_property_blob *blob;
 372	static const uint64_t default_modifiers[] = {
 373		DRM_FORMAT_MOD_LINEAR,
 374	};
 375	unsigned int format_modifier_count = 0;
 376	int ret;
 377
 378	/* plane index is used with 32bit bitmasks */
 379	if (WARN_ON(config->num_total_plane >= 32))
 380		return -EINVAL;
 381
 382	/*
 383	 * First driver to need more than 64 formats needs to fix this. Each
 384	 * format is encoded as a bit and the current code only supports a u64.
 385	 */
 386	if (WARN_ON(format_count > 64))
 387		return -EINVAL;
 388
 389	WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
 390		(!funcs->atomic_destroy_state ||
 391		 !funcs->atomic_duplicate_state));
 392
 393	ret = drm_mode_object_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
 394	if (ret)
 395		return ret;
 396
 397	drm_modeset_lock_init(&plane->mutex);
 398
 399	plane->base.properties = &plane->properties;
 400	plane->dev = dev;
 401	plane->funcs = funcs;
 402	plane->format_types = kmalloc_array(format_count, sizeof(uint32_t),
 403					    GFP_KERNEL);
 404	if (!plane->format_types) {
 405		DRM_DEBUG_KMS("out of memory when allocating plane\n");
 406		drm_mode_object_unregister(dev, &plane->base);
 407		return -ENOMEM;
 408	}
 409
 410	if (format_modifiers) {
 411		const uint64_t *temp_modifiers = format_modifiers;
 412
 413		while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
 414			format_modifier_count++;
 415	} else {
 416		if (!dev->mode_config.fb_modifiers_not_supported) {
 417			format_modifiers = default_modifiers;
 418			format_modifier_count = ARRAY_SIZE(default_modifiers);
 419		}
 420	}
 421
 422	/* autoset the cap and check for consistency across all planes */
 423	drm_WARN_ON(dev, config->fb_modifiers_not_supported &&
 424				format_modifier_count);
 425
 426	plane->modifier_count = format_modifier_count;
 427	plane->modifiers = kmalloc_array(format_modifier_count,
 428					 sizeof(*plane->modifiers),
 429					 GFP_KERNEL);
 430
 431	if (format_modifier_count && !plane->modifiers) {
 432		DRM_DEBUG_KMS("out of memory when allocating plane\n");
 433		kfree(plane->format_types);
 434		drm_mode_object_unregister(dev, &plane->base);
 435		return -ENOMEM;
 436	}
 437
 438	if (name) {
 439		plane->name = kvasprintf(GFP_KERNEL, name, ap);
 440	} else {
 441		plane->name = kasprintf(GFP_KERNEL, "plane-%d",
 442					drm_num_planes(dev));
 443	}
 444	if (!plane->name) {
 445		kfree(plane->format_types);
 446		kfree(plane->modifiers);
 447		drm_mode_object_unregister(dev, &plane->base);
 448		return -ENOMEM;
 449	}
 450
 451	memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
 452	plane->format_count = format_count;
 453	memcpy(plane->modifiers, format_modifiers,
 454	       format_modifier_count * sizeof(format_modifiers[0]));
 455	plane->possible_crtcs = possible_crtcs;
 456	plane->type = type;
 457
 458	list_add_tail(&plane->head, &config->plane_list);
 459	plane->index = config->num_total_plane++;
 460
 461	drm_object_attach_property(&plane->base,
 462				   config->plane_type_property,
 463				   plane->type);
 464
 465	if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
 466		drm_object_attach_property(&plane->base, config->prop_fb_id, 0);
 467		drm_object_attach_property(&plane->base, config->prop_in_fence_fd, -1);
 468		drm_object_attach_property(&plane->base, config->prop_crtc_id, 0);
 469		drm_object_attach_property(&plane->base, config->prop_crtc_x, 0);
 470		drm_object_attach_property(&plane->base, config->prop_crtc_y, 0);
 471		drm_object_attach_property(&plane->base, config->prop_crtc_w, 0);
 472		drm_object_attach_property(&plane->base, config->prop_crtc_h, 0);
 473		drm_object_attach_property(&plane->base, config->prop_src_x, 0);
 474		drm_object_attach_property(&plane->base, config->prop_src_y, 0);
 475		drm_object_attach_property(&plane->base, config->prop_src_w, 0);
 476		drm_object_attach_property(&plane->base, config->prop_src_h, 0);
 477	}
 478	if (drm_core_check_feature(dev, DRIVER_CURSOR_HOTSPOT) &&
 479	    type == DRM_PLANE_TYPE_CURSOR) {
 480		drm_plane_create_hotspot_properties(plane);
 481	}
 482
 483	if (format_modifier_count) {
 484		blob = create_in_format_blob(dev, plane,
 485					     plane->funcs->format_mod_supported);
 486		if (!IS_ERR(blob))
 487			drm_object_attach_property(&plane->base,
 488						   config->modifiers_property,
 489						   blob->base.id);
 490	}
 491
 492	if (plane->funcs->format_mod_supported_async) {
 493		blob = create_in_format_blob(dev, plane,
 494					     plane->funcs->format_mod_supported_async);
 495		if (!IS_ERR(blob))
 496			drm_object_attach_property(&plane->base,
 497						   config->async_modifiers_property,
 498						   blob->base.id);
 499	}
 500
 501
 502	return 0;
 503}
 504
 505/**
 506 * drm_universal_plane_init - Initialize a new universal plane object
 507 * @dev: DRM device
 508 * @plane: plane object to init
 509 * @possible_crtcs: bitmask of possible CRTCs
 510 * @funcs: callbacks for the new plane
 511 * @formats: array of supported formats (DRM_FORMAT\_\*)
 512 * @format_count: number of elements in @formats
 513 * @format_modifiers: array of struct drm_format modifiers terminated by
 514 *                    DRM_FORMAT_MOD_INVALID
 515 * @type: type of plane (overlay, primary, cursor)
 516 * @name: printf style format string for the plane name, or NULL for default name
 517 *
 518 * Initializes a plane object of type @type. The &drm_plane_funcs.destroy hook
 519 * should call drm_plane_cleanup() and kfree() the plane structure. The plane
 520 * structure should not be allocated with devm_kzalloc().
 521 *
 522 * Note: consider using drmm_universal_plane_alloc() instead of
 523 * drm_universal_plane_init() to let the DRM managed resource infrastructure
 524 * take care of cleanup and deallocation.
 525 *
 526 * Drivers that only support the DRM_FORMAT_MOD_LINEAR modifier support may set
 527 * @format_modifiers to NULL. The plane will advertise the linear modifier.
 528 *
 529 * Returns:
 530 * Zero on success, error code on failure.
 531 */
 532int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 533			     uint32_t possible_crtcs,
 534			     const struct drm_plane_funcs *funcs,
 535			     const uint32_t *formats, unsigned int format_count,
 536			     const uint64_t *format_modifiers,
 537			     enum drm_plane_type type,
 538			     const char *name, ...)
 539{
 540	va_list ap;
 541	int ret;
 542
 543	WARN_ON(!funcs->destroy);
 544
 545	va_start(ap, name);
 546	ret = __drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
 547					 formats, format_count, format_modifiers,
 548					 type, name, ap);
 549	va_end(ap);
 550	return ret;
 551}
 552EXPORT_SYMBOL(drm_universal_plane_init);
 553
 554static void drmm_universal_plane_alloc_release(struct drm_device *dev, void *ptr)
 555{
 556	struct drm_plane *plane = ptr;
 557
 558	if (WARN_ON(!plane->dev))
 559		return;
 560
 561	drm_plane_cleanup(plane);
 562}
 563
 564void *__drmm_universal_plane_alloc(struct drm_device *dev, size_t size,
 565				   size_t offset, uint32_t possible_crtcs,
 566				   const struct drm_plane_funcs *funcs,
 567				   const uint32_t *formats, unsigned int format_count,
 568				   const uint64_t *format_modifiers,
 569				   enum drm_plane_type type,
 570				   const char *name, ...)
 571{
 572	void *container;
 573	struct drm_plane *plane;
 574	va_list ap;
 575	int ret;
 576
 577	if (WARN_ON(!funcs || funcs->destroy))
 578		return ERR_PTR(-EINVAL);
 579
 580	container = drmm_kzalloc(dev, size, GFP_KERNEL);
 581	if (!container)
 582		return ERR_PTR(-ENOMEM);
 583
 584	plane = container + offset;
 585
 586	va_start(ap, name);
 587	ret = __drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
 588					 formats, format_count, format_modifiers,
 589					 type, name, ap);
 590	va_end(ap);
 591	if (ret)
 592		return ERR_PTR(ret);
 593
 594	ret = drmm_add_action_or_reset(dev, drmm_universal_plane_alloc_release,
 595				       plane);
 596	if (ret)
 597		return ERR_PTR(ret);
 598
 599	return container;
 600}
 601EXPORT_SYMBOL(__drmm_universal_plane_alloc);
 602
 603void *__drm_universal_plane_alloc(struct drm_device *dev, size_t size,
 604				  size_t offset, uint32_t possible_crtcs,
 605				  const struct drm_plane_funcs *funcs,
 606				  const uint32_t *formats, unsigned int format_count,
 607				  const uint64_t *format_modifiers,
 608				  enum drm_plane_type type,
 609				  const char *name, ...)
 610{
 611	void *container;
 612	struct drm_plane *plane;
 613	va_list ap;
 614	int ret;
 615
 616	if (drm_WARN_ON(dev, !funcs))
 617		return ERR_PTR(-EINVAL);
 618
 619	container = kzalloc(size, GFP_KERNEL);
 620	if (!container)
 621		return ERR_PTR(-ENOMEM);
 622
 623	plane = container + offset;
 624
 625	va_start(ap, name);
 626	ret = __drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
 627					 formats, format_count, format_modifiers,
 628					 type, name, ap);
 629	va_end(ap);
 630	if (ret)
 631		goto err_kfree;
 632
 633	return container;
 634
 635err_kfree:
 636	kfree(container);
 637	return ERR_PTR(ret);
 638}
 639EXPORT_SYMBOL(__drm_universal_plane_alloc);
 640
 641int drm_plane_register_all(struct drm_device *dev)
 642{
 643	unsigned int num_planes = 0;
 644	unsigned int num_zpos = 0;
 645	struct drm_plane *plane;
 646	int ret = 0;
 647
 648	drm_for_each_plane(plane, dev) {
 649		if (plane->funcs->late_register)
 650			ret = plane->funcs->late_register(plane);
 651		if (ret)
 652			return ret;
 653
 654		if (plane->zpos_property)
 655			num_zpos++;
 656		num_planes++;
 657	}
 658
 659	drm_WARN(dev, num_zpos && num_planes != num_zpos,
 660		 "Mixing planes with and without zpos property is invalid\n");
 661
 662	return 0;
 663}
 664
 665void drm_plane_unregister_all(struct drm_device *dev)
 666{
 667	struct drm_plane *plane;
 668
 669	drm_for_each_plane(plane, dev) {
 670		if (plane->funcs->early_unregister)
 671			plane->funcs->early_unregister(plane);
 672	}
 673}
 674
 675/**
 676 * drm_plane_cleanup - Clean up the core plane usage
 677 * @plane: plane to cleanup
 678 *
 679 * This function cleans up @plane and removes it from the DRM mode setting
 680 * core. Note that the function does *not* free the plane structure itself,
 681 * this is the responsibility of the caller.
 682 */
 683void drm_plane_cleanup(struct drm_plane *plane)
 684{
 685	struct drm_device *dev = plane->dev;
 686
 687	drm_modeset_lock_fini(&plane->mutex);
 688
 689	kfree(plane->format_types);
 690	kfree(plane->modifiers);
 691	drm_mode_object_unregister(dev, &plane->base);
 692
 693	BUG_ON(list_empty(&plane->head));
 694
 695	/* Note that the plane_list is considered to be static; should we
 696	 * remove the drm_plane at runtime we would have to decrement all
 697	 * the indices on the drm_plane after us in the plane_list.
 698	 */
 699
 700	list_del(&plane->head);
 701	dev->mode_config.num_total_plane--;
 702
 703	WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
 704	if (plane->state && plane->funcs->atomic_destroy_state)
 705		plane->funcs->atomic_destroy_state(plane, plane->state);
 706
 707	kfree(plane->name);
 708
 709	memset(plane, 0, sizeof(*plane));
 710}
 711EXPORT_SYMBOL(drm_plane_cleanup);
 712
 713/**
 714 * drm_plane_from_index - find the registered plane at an index
 715 * @dev: DRM device
 716 * @idx: index of registered plane to find for
 717 *
 718 * Given a plane index, return the registered plane from DRM device's
 719 * list of planes with matching index. This is the inverse of drm_plane_index().
 720 */
 721struct drm_plane *
 722drm_plane_from_index(struct drm_device *dev, int idx)
 723{
 724	struct drm_plane *plane;
 725
 726	drm_for_each_plane(plane, dev)
 727		if (idx == plane->index)
 728			return plane;
 729
 730	return NULL;
 731}
 732EXPORT_SYMBOL(drm_plane_from_index);
 733
 734/**
 735 * drm_plane_force_disable - Forcibly disable a plane
 736 * @plane: plane to disable
 737 *
 738 * Forces the plane to be disabled.
 739 *
 740 * Used when the plane's current framebuffer is destroyed,
 741 * and when restoring fbdev mode.
 742 *
 743 * Note that this function is not suitable for atomic drivers, since it doesn't
 744 * wire through the lock acquisition context properly and hence can't handle
 745 * retries or driver private locks. You probably want to use
 746 * drm_atomic_helper_disable_plane() or
 747 * drm_atomic_helper_disable_planes_on_crtc() instead.
 748 */
 749void drm_plane_force_disable(struct drm_plane *plane)
 750{
 751	int ret;
 752
 753	if (!plane->fb)
 754		return;
 755
 756	WARN_ON(drm_drv_uses_atomic_modeset(plane->dev));
 757
 758	plane->old_fb = plane->fb;
 759	ret = plane->funcs->disable_plane(plane, NULL);
 760	if (ret) {
 761		DRM_ERROR("failed to disable plane with busy fb\n");
 762		plane->old_fb = NULL;
 763		return;
 764	}
 765	/* disconnect the plane from the fb and crtc: */
 766	drm_framebuffer_put(plane->old_fb);
 767	plane->old_fb = NULL;
 768	plane->fb = NULL;
 769	plane->crtc = NULL;
 770}
 771EXPORT_SYMBOL(drm_plane_force_disable);
 772
 773/**
 774 * drm_mode_plane_set_obj_prop - set the value of a property
 775 * @plane: drm plane object to set property value for
 776 * @property: property to set
 777 * @value: value the property should be set to
 778 *
 779 * This functions sets a given property on a given plane object. This function
 780 * calls the driver's ->set_property callback and changes the software state of
 781 * the property if the callback succeeds.
 782 *
 783 * Returns:
 784 * Zero on success, error code on failure.
 785 */
 786int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
 787				struct drm_property *property,
 788				uint64_t value)
 789{
 790	int ret = -EINVAL;
 791	struct drm_mode_object *obj = &plane->base;
 792
 793	if (plane->funcs->set_property)
 794		ret = plane->funcs->set_property(plane, property, value);
 795	if (!ret)
 796		drm_object_property_set_value(obj, property, value);
 797
 798	return ret;
 799}
 800EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
 801
 802int drm_mode_getplane_res(struct drm_device *dev, void *data,
 803			  struct drm_file *file_priv)
 804{
 805	struct drm_mode_get_plane_res *plane_resp = data;
 806	struct drm_plane *plane;
 807	uint32_t __user *plane_ptr;
 808	int count = 0;
 809
 810	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 811		return -EOPNOTSUPP;
 812
 813	plane_ptr = u64_to_user_ptr(plane_resp->plane_id_ptr);
 814
 815	/*
 816	 * This ioctl is called twice, once to determine how much space is
 817	 * needed, and the 2nd time to fill it.
 818	 */
 819	drm_for_each_plane(plane, dev) {
 820		/*
 821		 * Unless userspace set the 'universal planes'
 822		 * capability bit, only advertise overlays.
 823		 */
 824		if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
 825		    !file_priv->universal_planes)
 826			continue;
 827
 828		/*
 829		 * If we're running on a virtualized driver then,
 830		 * unless userspace advertizes support for the
 831		 * virtualized cursor plane, disable cursor planes
 832		 * because they'll be broken due to missing cursor
 833		 * hotspot info.
 834		 */
 835		if (plane->type == DRM_PLANE_TYPE_CURSOR &&
 836		    drm_core_check_feature(dev, DRIVER_CURSOR_HOTSPOT) &&
 837		    file_priv->atomic &&
 838		    !file_priv->supports_virtualized_cursor_plane)
 839			continue;
 840
 841		if (drm_lease_held(file_priv, plane->base.id)) {
 842			if (count < plane_resp->count_planes &&
 843			    put_user(plane->base.id, plane_ptr + count))
 844				return -EFAULT;
 845			count++;
 846		}
 847	}
 848	plane_resp->count_planes = count;
 849
 850	return 0;
 851}
 852
 853int drm_mode_getplane(struct drm_device *dev, void *data,
 854		      struct drm_file *file_priv)
 855{
 856	struct drm_mode_get_plane *plane_resp = data;
 857	struct drm_plane *plane;
 858	uint32_t __user *format_ptr;
 859
 860	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 861		return -EOPNOTSUPP;
 862
 863	plane = drm_plane_find(dev, file_priv, plane_resp->plane_id);
 864	if (!plane)
 865		return -ENOENT;
 866
 867	drm_modeset_lock(&plane->mutex, NULL);
 868	if (plane->state && plane->state->crtc && drm_lease_held(file_priv, plane->state->crtc->base.id))
 869		plane_resp->crtc_id = plane->state->crtc->base.id;
 870	else if (!plane->state && plane->crtc && drm_lease_held(file_priv, plane->crtc->base.id))
 871		plane_resp->crtc_id = plane->crtc->base.id;
 872	else
 873		plane_resp->crtc_id = 0;
 874
 875	if (plane->state && plane->state->fb)
 876		plane_resp->fb_id = plane->state->fb->base.id;
 877	else if (!plane->state && plane->fb)
 878		plane_resp->fb_id = plane->fb->base.id;
 879	else
 880		plane_resp->fb_id = 0;
 881	drm_modeset_unlock(&plane->mutex);
 882
 883	plane_resp->plane_id = plane->base.id;
 884	plane_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
 885							    plane->possible_crtcs);
 886
 887	plane_resp->gamma_size = 0;
 888
 889	/*
 890	 * This ioctl is called twice, once to determine how much space is
 891	 * needed, and the 2nd time to fill it.
 892	 */
 893	if (plane->format_count &&
 894	    (plane_resp->count_format_types >= plane->format_count)) {
 895		format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
 896		if (copy_to_user(format_ptr,
 897				 plane->format_types,
 898				 sizeof(uint32_t) * plane->format_count)) {
 899			return -EFAULT;
 900		}
 901	}
 902	plane_resp->count_format_types = plane->format_count;
 903
 904	return 0;
 905}
 906
 907/**
 908 * drm_plane_has_format - Check whether the plane supports this format and modifier combination
 909 * @plane: drm plane
 910 * @format: pixel format (DRM_FORMAT_*)
 911 * @modifier: data layout modifier
 912 *
 913 * Returns:
 914 * Whether the plane supports the specified format and modifier combination.
 915 */
 916bool drm_plane_has_format(struct drm_plane *plane,
 917			  u32 format, u64 modifier)
 918{
 919	unsigned int i;
 920
 921	for (i = 0; i < plane->format_count; i++) {
 922		if (format == plane->format_types[i])
 923			break;
 924	}
 925	if (i == plane->format_count)
 926		return false;
 927
 928	if (plane->funcs->format_mod_supported) {
 929		if (!plane->funcs->format_mod_supported(plane, format, modifier))
 930			return false;
 931	} else {
 932		if (!plane->modifier_count)
 933			return true;
 934
 935		for (i = 0; i < plane->modifier_count; i++) {
 936			if (modifier == plane->modifiers[i])
 937				break;
 938		}
 939		if (i == plane->modifier_count)
 940			return false;
 941	}
 942
 943	return true;
 944}
 945EXPORT_SYMBOL(drm_plane_has_format);
 946
 947static int __setplane_check(struct drm_plane *plane,
 948			    struct drm_crtc *crtc,
 949			    struct drm_framebuffer *fb,
 950			    int32_t crtc_x, int32_t crtc_y,
 951			    uint32_t crtc_w, uint32_t crtc_h,
 952			    uint32_t src_x, uint32_t src_y,
 953			    uint32_t src_w, uint32_t src_h)
 954{
 955	int ret;
 956
 957	/* Check whether this plane is usable on this CRTC */
 958	if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
 959		DRM_DEBUG_KMS("Invalid crtc for plane\n");
 960		return -EINVAL;
 961	}
 962
 963	/* Check whether this plane supports the fb pixel format. */
 964	if (!drm_plane_has_format(plane, fb->format->format, fb->modifier)) {
 965		DRM_DEBUG_KMS("Invalid pixel format %p4cc, modifier 0x%llx\n",
 966			      &fb->format->format, fb->modifier);
 967		return -EINVAL;
 968	}
 969
 970	/* Give drivers some help against integer overflows */
 971	if (crtc_w > INT_MAX ||
 972	    crtc_x > INT_MAX - (int32_t) crtc_w ||
 973	    crtc_h > INT_MAX ||
 974	    crtc_y > INT_MAX - (int32_t) crtc_h) {
 975		DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
 976			      crtc_w, crtc_h, crtc_x, crtc_y);
 977		return -ERANGE;
 978	}
 979
 980	ret = drm_framebuffer_check_src_coords(src_x, src_y, src_w, src_h, fb);
 981	if (ret)
 982		return ret;
 983
 984	return 0;
 985}
 986
 987/**
 988 * drm_any_plane_has_format - Check whether any plane supports this format and modifier combination
 989 * @dev: DRM device
 990 * @format: pixel format (DRM_FORMAT_*)
 991 * @modifier: data layout modifier
 992 *
 993 * Returns:
 994 * Whether at least one plane supports the specified format and modifier combination.
 995 */
 996bool drm_any_plane_has_format(struct drm_device *dev,
 997			      u32 format, u64 modifier)
 998{
 999	struct drm_plane *plane;
1000
1001	drm_for_each_plane(plane, dev) {
1002		if (drm_plane_has_format(plane, format, modifier))
1003			return true;
1004	}
1005
1006	return false;
1007}
1008EXPORT_SYMBOL(drm_any_plane_has_format);
1009
1010/*
1011 * __setplane_internal - setplane handler for internal callers
1012 *
1013 * This function will take a reference on the new fb for the plane
1014 * on success.
1015 *
1016 * src_{x,y,w,h} are provided in 16.16 fixed point format
1017 */
1018static int __setplane_internal(struct drm_plane *plane,
1019			       struct drm_crtc *crtc,
1020			       struct drm_framebuffer *fb,
1021			       int32_t crtc_x, int32_t crtc_y,
1022			       uint32_t crtc_w, uint32_t crtc_h,
1023			       /* src_{x,y,w,h} values are 16.16 fixed point */
1024			       uint32_t src_x, uint32_t src_y,
1025			       uint32_t src_w, uint32_t src_h,
1026			       struct drm_modeset_acquire_ctx *ctx)
1027{
1028	int ret = 0;
1029
1030	WARN_ON(drm_drv_uses_atomic_modeset(plane->dev));
1031
1032	/* No fb means shut it down */
1033	if (!fb) {
1034		plane->old_fb = plane->fb;
1035		ret = plane->funcs->disable_plane(plane, ctx);
1036		if (!ret) {
1037			plane->crtc = NULL;
1038			plane->fb = NULL;
1039		} else {
1040			plane->old_fb = NULL;
1041		}
1042		goto out;
1043	}
1044
1045	ret = __setplane_check(plane, crtc, fb,
1046			       crtc_x, crtc_y, crtc_w, crtc_h,
1047			       src_x, src_y, src_w, src_h);
1048	if (ret)
1049		goto out;
1050
1051	plane->old_fb = plane->fb;
1052	ret = plane->funcs->update_plane(plane, crtc, fb,
1053					 crtc_x, crtc_y, crtc_w, crtc_h,
1054					 src_x, src_y, src_w, src_h, ctx);
1055	if (!ret) {
1056		plane->crtc = crtc;
1057		plane->fb = fb;
1058		drm_framebuffer_get(plane->fb);
1059	} else {
1060		plane->old_fb = NULL;
1061	}
1062
1063out:
1064	if (plane->old_fb)
1065		drm_framebuffer_put(plane->old_fb);
1066	plane->old_fb = NULL;
1067
1068	return ret;
1069}
1070
1071static int __setplane_atomic(struct drm_plane *plane,
1072			     struct drm_crtc *crtc,
1073			     struct drm_framebuffer *fb,
1074			     int32_t crtc_x, int32_t crtc_y,
1075			     uint32_t crtc_w, uint32_t crtc_h,
1076			     uint32_t src_x, uint32_t src_y,
1077			     uint32_t src_w, uint32_t src_h,
1078			     struct drm_modeset_acquire_ctx *ctx)
1079{
1080	int ret;
1081
1082	WARN_ON(!drm_drv_uses_atomic_modeset(plane->dev));
1083
1084	/* No fb means shut it down */
1085	if (!fb)
1086		return plane->funcs->disable_plane(plane, ctx);
1087
1088	/*
1089	 * FIXME: This is redundant with drm_atomic_plane_check(),
1090	 * but the legacy cursor/"async" .update_plane() tricks
1091	 * don't call that so we still need this here. Should remove
1092	 * this when all .update_plane() implementations have been
1093	 * fixed to call drm_atomic_plane_check().
1094	 */
1095	ret = __setplane_check(plane, crtc, fb,
1096			       crtc_x, crtc_y, crtc_w, crtc_h,
1097			       src_x, src_y, src_w, src_h);
1098	if (ret)
1099		return ret;
1100
1101	return plane->funcs->update_plane(plane, crtc, fb,
1102					  crtc_x, crtc_y, crtc_w, crtc_h,
1103					  src_x, src_y, src_w, src_h, ctx);
1104}
1105
1106static int setplane_internal(struct drm_plane *plane,
1107			     struct drm_crtc *crtc,
1108			     struct drm_framebuffer *fb,
1109			     int32_t crtc_x, int32_t crtc_y,
1110			     uint32_t crtc_w, uint32_t crtc_h,
1111			     /* src_{x,y,w,h} values are 16.16 fixed point */
1112			     uint32_t src_x, uint32_t src_y,
1113			     uint32_t src_w, uint32_t src_h)
1114{
1115	struct drm_modeset_acquire_ctx ctx;
1116	int ret;
1117
1118	DRM_MODESET_LOCK_ALL_BEGIN(plane->dev, ctx,
1119				   DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
1120
1121	if (drm_drv_uses_atomic_modeset(plane->dev))
1122		ret = __setplane_atomic(plane, crtc, fb,
1123					crtc_x, crtc_y, crtc_w, crtc_h,
1124					src_x, src_y, src_w, src_h, &ctx);
1125	else
1126		ret = __setplane_internal(plane, crtc, fb,
1127					  crtc_x, crtc_y, crtc_w, crtc_h,
1128					  src_x, src_y, src_w, src_h, &ctx);
1129
1130	DRM_MODESET_LOCK_ALL_END(plane->dev, ctx, ret);
1131
1132	return ret;
1133}
1134
1135int drm_mode_setplane(struct drm_device *dev, void *data,
1136		      struct drm_file *file_priv)
1137{
1138	struct drm_mode_set_plane *plane_req = data;
1139	struct drm_plane *plane;
1140	struct drm_crtc *crtc = NULL;
1141	struct drm_framebuffer *fb = NULL;
1142	int ret;
1143
1144	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1145		return -EOPNOTSUPP;
1146
1147	/*
1148	 * First, find the plane, crtc, and fb objects.  If not available,
1149	 * we don't bother to call the driver.
1150	 */
1151	plane = drm_plane_find(dev, file_priv, plane_req->plane_id);
1152	if (!plane) {
1153		DRM_DEBUG_KMS("Unknown plane ID %d\n",
1154			      plane_req->plane_id);
1155		return -ENOENT;
1156	}
1157
1158	if (plane_req->fb_id) {
1159		fb = drm_framebuffer_lookup(dev, file_priv, plane_req->fb_id);
1160		if (!fb) {
1161			DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
1162				      plane_req->fb_id);
1163			return -ENOENT;
1164		}
1165
1166		crtc = drm_crtc_find(dev, file_priv, plane_req->crtc_id);
1167		if (!crtc) {
1168			drm_framebuffer_put(fb);
1169			DRM_DEBUG_KMS("Unknown crtc ID %d\n",
1170				      plane_req->crtc_id);
1171			return -ENOENT;
1172		}
1173	}
1174
1175	ret = setplane_internal(plane, crtc, fb,
1176				plane_req->crtc_x, plane_req->crtc_y,
1177				plane_req->crtc_w, plane_req->crtc_h,
1178				plane_req->src_x, plane_req->src_y,
1179				plane_req->src_w, plane_req->src_h);
1180
1181	if (fb)
1182		drm_framebuffer_put(fb);
1183
1184	return ret;
1185}
1186
1187static int drm_mode_cursor_universal(struct drm_crtc *crtc,
1188				     struct drm_mode_cursor2 *req,
1189				     struct drm_file *file_priv,
1190				     struct drm_modeset_acquire_ctx *ctx)
1191{
1192	struct drm_device *dev = crtc->dev;
1193	struct drm_plane *plane = crtc->cursor;
1194	struct drm_framebuffer *fb = NULL;
1195	struct drm_mode_fb_cmd2 fbreq = {
1196		.width = req->width,
1197		.height = req->height,
1198		.pixel_format = DRM_FORMAT_ARGB8888,
1199		.pitches = { req->width * 4 },
1200		.handles = { req->handle },
1201	};
1202	int32_t crtc_x, crtc_y;
1203	uint32_t crtc_w = 0, crtc_h = 0;
1204	uint32_t src_w = 0, src_h = 0;
1205	int ret = 0;
1206
1207	BUG_ON(!plane);
1208	WARN_ON(plane->crtc != crtc && plane->crtc != NULL);
1209
1210	/*
1211	 * Obtain fb we'll be using (either new or existing) and take an extra
1212	 * reference to it if fb != null.  setplane will take care of dropping
1213	 * the reference if the plane update fails.
1214	 */
1215	if (req->flags & DRM_MODE_CURSOR_BO) {
1216		if (req->handle) {
1217			fb = drm_internal_framebuffer_create(dev, &fbreq, file_priv);
1218			if (IS_ERR(fb)) {
1219				DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
1220				return PTR_ERR(fb);
1221			}
1222
1223			if (plane->hotspot_x_property && plane->state)
1224				plane->state->hotspot_x = req->hot_x;
1225			if (plane->hotspot_y_property && plane->state)
1226				plane->state->hotspot_y = req->hot_y;
1227		} else {
1228			fb = NULL;
1229		}
1230	} else {
1231		if (plane->state)
1232			fb = plane->state->fb;
1233		else
1234			fb = plane->fb;
1235
1236		if (fb)
1237			drm_framebuffer_get(fb);
1238	}
1239
1240	if (req->flags & DRM_MODE_CURSOR_MOVE) {
1241		crtc_x = req->x;
1242		crtc_y = req->y;
1243	} else {
1244		crtc_x = crtc->cursor_x;
1245		crtc_y = crtc->cursor_y;
1246	}
1247
1248	if (fb) {
1249		crtc_w = fb->width;
1250		crtc_h = fb->height;
1251		src_w = fb->width << 16;
1252		src_h = fb->height << 16;
1253	}
1254
1255	if (drm_drv_uses_atomic_modeset(dev))
1256		ret = __setplane_atomic(plane, crtc, fb,
1257					crtc_x, crtc_y, crtc_w, crtc_h,
1258					0, 0, src_w, src_h, ctx);
1259	else
1260		ret = __setplane_internal(plane, crtc, fb,
1261					  crtc_x, crtc_y, crtc_w, crtc_h,
1262					  0, 0, src_w, src_h, ctx);
1263
1264	if (fb)
1265		drm_framebuffer_put(fb);
1266
1267	/* Update successful; save new cursor position, if necessary */
1268	if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
1269		crtc->cursor_x = req->x;
1270		crtc->cursor_y = req->y;
1271	}
1272
1273	return ret;
1274}
1275
1276static int drm_mode_cursor_common(struct drm_device *dev,
1277				  struct drm_mode_cursor2 *req,
1278				  struct drm_file *file_priv)
1279{
1280	struct drm_crtc *crtc;
1281	struct drm_modeset_acquire_ctx ctx;
1282	int ret = 0;
1283
1284	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1285		return -EOPNOTSUPP;
1286
1287	if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
1288		return -EINVAL;
1289
1290	crtc = drm_crtc_find(dev, file_priv, req->crtc_id);
1291	if (!crtc) {
1292		DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
1293		return -ENOENT;
1294	}
1295
1296	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
1297retry:
1298	ret = drm_modeset_lock(&crtc->mutex, &ctx);
1299	if (ret)
1300		goto out;
1301	/*
1302	 * If this crtc has a universal cursor plane, call that plane's update
1303	 * handler rather than using legacy cursor handlers.
1304	 */
1305	if (crtc->cursor) {
1306		ret = drm_modeset_lock(&crtc->cursor->mutex, &ctx);
1307		if (ret)
1308			goto out;
1309
1310		if (!drm_lease_held(file_priv, crtc->cursor->base.id)) {
1311			ret = -EACCES;
1312			goto out;
1313		}
1314
1315		ret = drm_mode_cursor_universal(crtc, req, file_priv, &ctx);
1316		goto out;
1317	}
1318
1319	if (req->flags & DRM_MODE_CURSOR_BO) {
1320		if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
1321			ret = -ENXIO;
1322			goto out;
1323		}
1324		/* Turns off the cursor if handle is 0 */
1325		if (crtc->funcs->cursor_set2)
1326			ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle,
1327						      req->width, req->height, req->hot_x, req->hot_y);
1328		else
1329			ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
1330						      req->width, req->height);
1331	}
1332
1333	if (req->flags & DRM_MODE_CURSOR_MOVE) {
1334		if (crtc->funcs->cursor_move) {
1335			ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
1336		} else {
1337			ret = -EFAULT;
1338			goto out;
1339		}
1340	}
1341out:
1342	if (ret == -EDEADLK) {
1343		ret = drm_modeset_backoff(&ctx);
1344		if (!ret)
1345			goto retry;
1346	}
1347
1348	drm_modeset_drop_locks(&ctx);
1349	drm_modeset_acquire_fini(&ctx);
1350
1351	return ret;
1352
1353}
1354
1355
1356int drm_mode_cursor_ioctl(struct drm_device *dev,
1357			  void *data, struct drm_file *file_priv)
1358{
1359	struct drm_mode_cursor *req = data;
1360	struct drm_mode_cursor2 new_req;
1361
1362	memcpy(&new_req, req, sizeof(struct drm_mode_cursor));
1363	new_req.hot_x = new_req.hot_y = 0;
1364
1365	return drm_mode_cursor_common(dev, &new_req, file_priv);
1366}
1367
1368/*
1369 * Set the cursor configuration based on user request. This implements the 2nd
1370 * version of the cursor ioctl, which allows userspace to additionally specify
1371 * the hotspot of the pointer.
1372 */
1373int drm_mode_cursor2_ioctl(struct drm_device *dev,
1374			   void *data, struct drm_file *file_priv)
1375{
1376	struct drm_mode_cursor2 *req = data;
1377
1378	return drm_mode_cursor_common(dev, req, file_priv);
1379}
1380
1381int drm_mode_page_flip_ioctl(struct drm_device *dev,
1382			     void *data, struct drm_file *file_priv)
1383{
1384	struct drm_mode_crtc_page_flip_target *page_flip = data;
1385	struct drm_crtc *crtc;
1386	struct drm_plane *plane;
1387	struct drm_framebuffer *fb = NULL, *old_fb;
1388	struct drm_pending_vblank_event *e = NULL;
1389	u32 target_vblank = page_flip->sequence;
1390	struct drm_modeset_acquire_ctx ctx;
1391	int ret = -EINVAL;
1392
1393	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1394		return -EOPNOTSUPP;
1395
1396	if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS)
1397		return -EINVAL;
1398
1399	if (page_flip->sequence != 0 && !(page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET))
1400		return -EINVAL;
1401
1402	/* Only one of the DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags
1403	 * can be specified
1404	 */
1405	if ((page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) == DRM_MODE_PAGE_FLIP_TARGET)
1406		return -EINVAL;
1407
1408	if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
1409		return -EINVAL;
1410
1411	crtc = drm_crtc_find(dev, file_priv, page_flip->crtc_id);
1412	if (!crtc)
1413		return -ENOENT;
1414
1415	plane = crtc->primary;
1416
1417	if (!drm_lease_held(file_priv, plane->base.id))
1418		return -EACCES;
1419
1420	if (crtc->funcs->page_flip_target) {
1421		u32 current_vblank;
1422		int r;
1423
1424		r = drm_crtc_vblank_get(crtc);
1425		if (r)
1426			return r;
1427
1428		current_vblank = (u32)drm_crtc_vblank_count(crtc);
1429
1430		switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) {
1431		case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE:
1432			if ((int)(target_vblank - current_vblank) > 1) {
1433				DRM_DEBUG("Invalid absolute flip target %u, "
1434					  "must be <= %u\n", target_vblank,
1435					  current_vblank + 1);
1436				drm_crtc_vblank_put(crtc);
1437				return -EINVAL;
1438			}
1439			break;
1440		case DRM_MODE_PAGE_FLIP_TARGET_RELATIVE:
1441			if (target_vblank != 0 && target_vblank != 1) {
1442				DRM_DEBUG("Invalid relative flip target %u, "
1443					  "must be 0 or 1\n", target_vblank);
1444				drm_crtc_vblank_put(crtc);
1445				return -EINVAL;
1446			}
1447			target_vblank += current_vblank;
1448			break;
1449		default:
1450			target_vblank = current_vblank +
1451				!(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC);
1452			break;
1453		}
1454	} else if (crtc->funcs->page_flip == NULL ||
1455		   (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) {
1456		return -EINVAL;
1457	}
1458
1459	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
1460retry:
1461	ret = drm_modeset_lock(&crtc->mutex, &ctx);
1462	if (ret)
1463		goto out;
1464	ret = drm_modeset_lock(&plane->mutex, &ctx);
1465	if (ret)
1466		goto out;
1467
1468	if (plane->state)
1469		old_fb = plane->state->fb;
1470	else
1471		old_fb = plane->fb;
1472
1473	if (old_fb == NULL) {
1474		/* The framebuffer is currently unbound, presumably
1475		 * due to a hotplug event, that userspace has not
1476		 * yet discovered.
1477		 */
1478		ret = -EBUSY;
1479		goto out;
1480	}
1481
1482	fb = drm_framebuffer_lookup(dev, file_priv, page_flip->fb_id);
1483	if (!fb) {
1484		ret = -ENOENT;
1485		goto out;
1486	}
1487
1488	if (plane->state) {
1489		const struct drm_plane_state *state = plane->state;
1490
1491		ret = drm_framebuffer_check_src_coords(state->src_x,
1492						       state->src_y,
1493						       state->src_w,
1494						       state->src_h,
1495						       fb);
1496	} else {
1497		ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y,
1498					      &crtc->mode, fb);
1499	}
1500	if (ret)
1501		goto out;
1502
1503	/*
1504	 * Only check the FOURCC format code, excluding modifiers. This is
1505	 * enough for all legacy drivers. Atomic drivers have their own
1506	 * checks in their ->atomic_check implementation, which will
1507	 * return -EINVAL if any hw or driver constraint is violated due
1508	 * to modifier changes.
1509	 */
1510	if (old_fb->format->format != fb->format->format) {
1511		DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
1512		ret = -EINVAL;
1513		goto out;
1514	}
1515
1516	if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
1517		e = kzalloc(sizeof *e, GFP_KERNEL);
1518		if (!e) {
1519			ret = -ENOMEM;
1520			goto out;
1521		}
1522
1523		e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
1524		e->event.base.length = sizeof(e->event);
1525		e->event.vbl.user_data = page_flip->user_data;
1526		e->event.vbl.crtc_id = crtc->base.id;
1527
1528		ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
1529		if (ret) {
1530			kfree(e);
1531			e = NULL;
1532			goto out;
1533		}
1534	}
1535
1536	plane->old_fb = plane->fb;
1537	if (crtc->funcs->page_flip_target)
1538		ret = crtc->funcs->page_flip_target(crtc, fb, e,
1539						    page_flip->flags,
1540						    target_vblank,
1541						    &ctx);
1542	else
1543		ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags,
1544					     &ctx);
1545	if (ret) {
1546		if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
1547			drm_event_cancel_free(dev, &e->base);
1548		/* Keep the old fb, don't unref it. */
1549		plane->old_fb = NULL;
1550	} else {
1551		if (!plane->state) {
1552			plane->fb = fb;
1553			drm_framebuffer_get(fb);
1554		}
1555	}
1556
1557out:
1558	if (fb)
1559		drm_framebuffer_put(fb);
1560	fb = NULL;
1561	if (plane->old_fb)
1562		drm_framebuffer_put(plane->old_fb);
1563	plane->old_fb = NULL;
1564
1565	if (ret == -EDEADLK) {
1566		ret = drm_modeset_backoff(&ctx);
1567		if (!ret)
1568			goto retry;
1569	}
1570
1571	drm_modeset_drop_locks(&ctx);
1572	drm_modeset_acquire_fini(&ctx);
1573
1574	if (ret && crtc->funcs->page_flip_target)
1575		drm_crtc_vblank_put(crtc);
1576
1577	return ret;
1578}
1579
1580/**
1581 * DOC: damage tracking
1582 *
1583 * FB_DAMAGE_CLIPS is an optional plane property which provides a means to
1584 * specify a list of damage rectangles on a plane in framebuffer coordinates of
1585 * the framebuffer attached to the plane. In current context damage is the area
1586 * of plane framebuffer that has changed since last plane update (also called
1587 * page-flip), irrespective of whether currently attached framebuffer is same as
1588 * framebuffer attached during last plane update or not.
1589 *
1590 * FB_DAMAGE_CLIPS is a hint to kernel which could be helpful for some drivers
1591 * to optimize internally especially for virtual devices where each framebuffer
1592 * change needs to be transmitted over network, usb, etc.
1593 *
1594 * Since FB_DAMAGE_CLIPS is a hint so it is an optional property. User-space can
1595 * ignore damage clips property and in that case driver will do a full plane
1596 * update. In case damage clips are provided then it is guaranteed that the area
1597 * inside damage clips will be updated to plane. For efficiency driver can do
1598 * full update or can update more than specified in damage clips. Since driver
1599 * is free to read more, user-space must always render the entire visible
1600 * framebuffer. Otherwise there can be corruptions. Also, if a user-space
1601 * provides damage clips which doesn't encompass the actual damage to
1602 * framebuffer (since last plane update) can result in incorrect rendering.
1603 *
1604 * FB_DAMAGE_CLIPS is a blob property with the layout of blob data is simply an
1605 * array of &drm_mode_rect. Unlike plane &drm_plane_state.src coordinates,
1606 * damage clips are not in 16.16 fixed point. Similar to plane src in
1607 * framebuffer, damage clips cannot be negative. In damage clip, x1/y1 are
1608 * inclusive and x2/y2 are exclusive. While kernel does not error for overlapped
1609 * damage clips, it is strongly discouraged.
1610 *
1611 * Drivers that are interested in damage interface for plane should enable
1612 * FB_DAMAGE_CLIPS property by calling drm_plane_enable_fb_damage_clips().
1613 * Drivers implementing damage can use drm_atomic_helper_damage_iter_init() and
1614 * drm_atomic_helper_damage_iter_next() helper iterator function to get damage
1615 * rectangles clipped to &drm_plane_state.src.
1616 *
1617 * Note that there are two types of damage handling: frame damage and buffer
1618 * damage, the type of damage handling implemented depends on a driver's upload
1619 * target. Drivers implementing a per-plane or per-CRTC upload target need to
1620 * handle frame damage, while drivers implementing a per-buffer upload target
1621 * need to handle buffer damage.
1622 *
1623 * The existing damage helpers only support the frame damage type, there is no
1624 * buffer age support or similar damage accumulation algorithm implemented yet.
1625 *
1626 * Only drivers handling frame damage can use the mentioned damage helpers to
1627 * iterate over the damaged regions. Drivers that handle buffer damage, must set
1628 * &drm_plane_state.ignore_damage_clips for drm_atomic_helper_damage_iter_init()
1629 * to know that damage clips should be ignored and return &drm_plane_state.src
1630 * as the damage rectangle, to force a full plane update.
1631 *
1632 * Drivers with a per-buffer upload target could compare the &drm_plane_state.fb
1633 * of the old and new plane states to determine if the framebuffer attached to a
1634 * plane has changed or not since the last plane update. If &drm_plane_state.fb
1635 * has changed, then &drm_plane_state.ignore_damage_clips must be set to true.
1636 *
1637 * That is because drivers with a per-plane upload target, expect the backing
1638 * storage buffer to not change for a given plane. If the upload buffer changes
1639 * between page flips, the new upload buffer has to be updated as a whole. This
1640 * can be improved in the future if support for frame damage is added to the DRM
1641 * damage helpers, similarly to how user-space already handle this case as it is
1642 * explained in the following documents:
1643 *
1644 *     https://registry.khronos.org/EGL/extensions/KHR/EGL_KHR_swap_buffers_with_damage.txt
1645 *     https://emersion.fr/blog/2019/intro-to-damage-tracking/
1646 */
1647
1648/**
1649 * drm_plane_enable_fb_damage_clips - Enables plane fb damage clips property.
1650 * @plane: Plane on which to enable damage clips property.
1651 *
1652 * This function lets driver to enable the damage clips property on a plane.
1653 */
1654void drm_plane_enable_fb_damage_clips(struct drm_plane *plane)
1655{
1656	struct drm_device *dev = plane->dev;
1657	struct drm_mode_config *config = &dev->mode_config;
1658
1659	drm_object_attach_property(&plane->base, config->prop_fb_damage_clips,
1660				   0);
1661}
1662EXPORT_SYMBOL(drm_plane_enable_fb_damage_clips);
1663
1664/**
1665 * drm_plane_get_damage_clips_count - Returns damage clips count.
1666 * @state: Plane state.
1667 *
1668 * Simple helper to get the number of &drm_mode_rect clips set by user-space
1669 * during plane update.
1670 *
1671 * Return: Number of clips in plane fb_damage_clips blob property.
1672 */
1673unsigned int
1674drm_plane_get_damage_clips_count(const struct drm_plane_state *state)
1675{
1676	return (state && state->fb_damage_clips) ?
1677		state->fb_damage_clips->length/sizeof(struct drm_mode_rect) : 0;
1678}
1679EXPORT_SYMBOL(drm_plane_get_damage_clips_count);
1680
1681struct drm_mode_rect *
1682__drm_plane_get_damage_clips(const struct drm_plane_state *state)
1683{
1684	return (struct drm_mode_rect *)((state && state->fb_damage_clips) ?
1685					state->fb_damage_clips->data : NULL);
1686}
1687
1688/**
1689 * drm_plane_get_damage_clips - Returns damage clips.
1690 * @state: Plane state.
1691 *
1692 * Note that this function returns uapi type &drm_mode_rect. Drivers might want
1693 * to use the helper functions drm_atomic_helper_damage_iter_init() and
1694 * drm_atomic_helper_damage_iter_next() or drm_atomic_helper_damage_merged() if
1695 * the driver can only handle a single damage region at most.
1696 *
1697 * Return: Damage clips in plane fb_damage_clips blob property.
1698 */
1699struct drm_mode_rect *
1700drm_plane_get_damage_clips(const struct drm_plane_state *state)
1701{
1702	struct drm_device *dev = state->plane->dev;
1703	struct drm_mode_config *config = &dev->mode_config;
1704
1705	/* check that drm_plane_enable_fb_damage_clips() was called */
1706	if (!drm_mode_obj_find_prop_id(&state->plane->base,
1707				       config->prop_fb_damage_clips->base.id))
1708		drm_warn_once(dev, "drm_plane_enable_fb_damage_clips() not called\n");
1709
1710	return __drm_plane_get_damage_clips(state);
1711}
1712EXPORT_SYMBOL(drm_plane_get_damage_clips);
1713
1714struct drm_property *
1715drm_create_scaling_filter_prop(struct drm_device *dev,
1716			       unsigned int supported_filters)
1717{
1718	struct drm_property *prop;
1719	static const struct drm_prop_enum_list props[] = {
1720		{ DRM_SCALING_FILTER_DEFAULT, "Default" },
1721		{ DRM_SCALING_FILTER_NEAREST_NEIGHBOR, "Nearest Neighbor" },
1722	};
1723	unsigned int valid_mode_mask = BIT(DRM_SCALING_FILTER_DEFAULT) |
1724				       BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR);
1725	int i;
1726
1727	if (WARN_ON((supported_filters & ~valid_mode_mask) ||
1728		    ((supported_filters & BIT(DRM_SCALING_FILTER_DEFAULT)) == 0)))
1729		return ERR_PTR(-EINVAL);
1730
1731	prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
1732				   "SCALING_FILTER",
1733				   hweight32(supported_filters));
1734	if (!prop)
1735		return ERR_PTR(-ENOMEM);
1736
1737	for (i = 0; i < ARRAY_SIZE(props); i++) {
1738		int ret;
1739
1740		if (!(BIT(props[i].type) & supported_filters))
1741			continue;
1742
1743		ret = drm_property_add_enum(prop, props[i].type,
1744					    props[i].name);
1745
1746		if (ret) {
1747			drm_property_destroy(dev, prop);
1748
1749			return ERR_PTR(ret);
1750		}
1751	}
1752
1753	return prop;
1754}
1755
1756/**
1757 * drm_plane_create_scaling_filter_property - create a new scaling filter
1758 * property
1759 *
1760 * @plane: drm plane
1761 * @supported_filters: bitmask of supported scaling filters, must include
1762 *		       BIT(DRM_SCALING_FILTER_DEFAULT).
1763 *
1764 * This function lets driver to enable the scaling filter property on a given
1765 * plane.
1766 *
1767 * RETURNS:
1768 * Zero for success or -errno
1769 */
1770int drm_plane_create_scaling_filter_property(struct drm_plane *plane,
1771					     unsigned int supported_filters)
1772{
1773	struct drm_property *prop =
1774		drm_create_scaling_filter_prop(plane->dev, supported_filters);
1775
1776	if (IS_ERR(prop))
1777		return PTR_ERR(prop);
1778
1779	drm_object_attach_property(&plane->base, prop,
1780				   DRM_SCALING_FILTER_DEFAULT);
1781	plane->scaling_filter_property = prop;
1782
1783	return 0;
1784}
1785EXPORT_SYMBOL(drm_plane_create_scaling_filter_property);
1786
1787/**
1788 * drm_plane_add_size_hints_property - create a size hints property
1789 *
1790 * @plane: drm plane
1791 * @hints: size hints
1792 * @num_hints: number of size hints
1793 *
1794 * Create a size hints property for the plane.
1795 *
1796 * RETURNS:
1797 * Zero for success or -errno
1798 */
1799int drm_plane_add_size_hints_property(struct drm_plane *plane,
1800				      const struct drm_plane_size_hint *hints,
1801				      int num_hints)
1802{
1803	struct drm_device *dev = plane->dev;
1804	struct drm_mode_config *config = &dev->mode_config;
1805	struct drm_property_blob *blob;
1806
1807	/* extending to other plane types needs actual thought */
1808	if (drm_WARN_ON(dev, plane->type != DRM_PLANE_TYPE_CURSOR))
1809		return -EINVAL;
1810
1811	blob = drm_property_create_blob(dev,
1812					array_size(sizeof(hints[0]), num_hints),
1813					hints);
1814	if (IS_ERR(blob))
1815		return PTR_ERR(blob);
1816
1817	drm_object_attach_property(&plane->base, config->size_hints_property,
1818				   blob->base.id);
1819
1820	return 0;
1821}
1822EXPORT_SYMBOL(drm_plane_add_size_hints_property);
1823
1824/**
1825 * drm_plane_create_color_pipeline_property - create a new color pipeline
1826 * property
1827 *
1828 * @plane: drm plane
1829 * @pipelines: list of pipelines
1830 * @num_pipelines: number of pipelines
1831 *
1832 * Create the COLOR_PIPELINE plane property to specific color pipelines on
1833 * the plane.
1834 *
1835 * RETURNS:
1836 * Zero for success or -errno
1837 */
1838int drm_plane_create_color_pipeline_property(struct drm_plane *plane,
1839					     const struct drm_prop_enum_list *pipelines,
1840					     int num_pipelines)
1841{
1842	struct drm_prop_enum_list *all_pipelines;
1843	struct drm_property *prop;
1844	int len = 0;
1845	int i;
1846
1847	all_pipelines = kcalloc(num_pipelines + 1,
1848				sizeof(*all_pipelines),
1849				GFP_KERNEL);
1850
1851	if (!all_pipelines) {
1852		drm_err(plane->dev, "failed to allocate color pipeline\n");
1853		return -ENOMEM;
1854	}
1855
1856	/* Create default Bypass color pipeline */
1857	all_pipelines[len].type = 0;
1858	all_pipelines[len].name = "Bypass";
1859	len++;
1860
1861	/* Add all other color pipelines */
1862	for (i = 0; i < num_pipelines; i++, len++) {
1863		all_pipelines[len].type = pipelines[i].type;
1864		all_pipelines[len].name = pipelines[i].name;
1865	}
1866
1867	prop = drm_property_create_enum(plane->dev, DRM_MODE_PROP_ATOMIC,
1868					"COLOR_PIPELINE",
1869					all_pipelines, len);
1870	if (!prop) {
1871		kfree(all_pipelines);
1872		return -ENOMEM;
1873	}
1874
1875	drm_object_attach_property(&plane->base, prop, 0);
1876	plane->color_pipeline_property = prop;
1877
1878	kfree(all_pipelines);
1879	return 0;
1880}
1881EXPORT_SYMBOL(drm_plane_create_color_pipeline_property);
~/ Read-only file preview.