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