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 <drm/drmP.h> 24 #include <drm/drm_plane.h> 25 26 #include "drm_crtc_internal.h" 27 28 /** 29 * DOC: overview 30 * 31 * A plane represents an image source that can be blended with or overlayed on 32 * top of a CRTC during the scanout process. Planes take their input data from a 33 * &drm_framebuffer object. The plane itself specifies the cropping and scaling 34 * of that image, and where it is placed on the visible are of a display 35 * pipeline, represented by &drm_crtc. A plane can also have additional 36 * properties that specify how the pixels are positioned and blended, like 37 * rotation or Z-position. All these properties are stored in &drm_plane_state. 38 * 39 * To create a plane, a KMS drivers allocates and zeroes an instances of 40 * &struct drm_plane (possibly as part of a larger structure) and registers it 41 * with a call to drm_universal_plane_init(). 42 * 43 * Cursor and overlay planes are optional. All drivers should provide one 44 * primary plane per CRTC to avoid surprising userspace too much. See enum 45 * drm_plane_type for a more in-depth discussion of these special uapi-relevant 46 * plane types. Special planes are associated with their CRTC by calling 47 * drm_crtc_init_with_planes(). 48 * 49 * The type of a plane is exposed in the immutable "type" enumeration property, 50 * which has one of the following values: "Overlay", "Primary", "Cursor". 51 */ 52 53 static unsigned int drm_num_planes(struct drm_device *dev) 54 { 55 unsigned int num = 0; 56 struct drm_plane *tmp; 57 58 drm_for_each_plane(tmp, dev) { 59 num++; 60 } 61 62 return num; 63 } 64 65 /** 66 * drm_universal_plane_init - Initialize a new universal plane object 67 * @dev: DRM device 68 * @plane: plane object to init 69 * @possible_crtcs: bitmask of possible CRTCs 70 * @funcs: callbacks for the new plane 71 * @formats: array of supported formats (DRM_FORMAT\_\*) 72 * @format_count: number of elements in @formats 73 * @type: type of plane (overlay, primary, cursor) 74 * @name: printf style format string for the plane name, or NULL for default name 75 * 76 * Initializes a plane object of type @type. 77 * 78 * Returns: 79 * Zero on success, error code on failure. 80 */ 81 int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, 82 uint32_t possible_crtcs, 83 const struct drm_plane_funcs *funcs, 84 const uint32_t *formats, unsigned int format_count, 85 enum drm_plane_type type, 86 const char *name, ...) 87 { 88 struct drm_mode_config *config = &dev->mode_config; 89 int ret; 90 91 ret = drm_mode_object_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE); 92 if (ret) 93 return ret; 94 95 drm_modeset_lock_init(&plane->mutex); 96 97 plane->base.properties = &plane->properties; 98 plane->dev = dev; 99 plane->funcs = funcs; 100 plane->format_types = kmalloc_array(format_count, sizeof(uint32_t), 101 GFP_KERNEL); 102 if (!plane->format_types) { 103 DRM_DEBUG_KMS("out of memory when allocating plane\n"); 104 drm_mode_object_unregister(dev, &plane->base); 105 return -ENOMEM; 106 } 107 108 if (name) { 109 va_list ap; 110 111 va_start(ap, name); 112 plane->name = kvasprintf(GFP_KERNEL, name, ap); 113 va_end(ap); 114 } else { 115 plane->name = kasprintf(GFP_KERNEL, "plane-%d", 116 drm_num_planes(dev)); 117 } 118 if (!plane->name) { 119 kfree(plane->format_types); 120 drm_mode_object_unregister(dev, &plane->base); 121 return -ENOMEM; 122 } 123 124 memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); 125 plane->format_count = format_count; 126 plane->possible_crtcs = possible_crtcs; 127 plane->type = type; 128 129 list_add_tail(&plane->head, &config->plane_list); 130 plane->index = config->num_total_plane++; 131 if (plane->type == DRM_PLANE_TYPE_OVERLAY) 132 config->num_overlay_plane++; 133 134 drm_object_attach_property(&plane->base, 135 config->plane_type_property, 136 plane->type); 137 138 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { 139 drm_object_attach_property(&plane->base, config->prop_fb_id, 0); 140 drm_object_attach_property(&plane->base, config->prop_in_fence_fd, -1); 141 drm_object_attach_property(&plane->base, config->prop_crtc_id, 0); 142 drm_object_attach_property(&plane->base, config->prop_crtc_x, 0); 143 drm_object_attach_property(&plane->base, config->prop_crtc_y, 0); 144 drm_object_attach_property(&plane->base, config->prop_crtc_w, 0); 145 drm_object_attach_property(&plane->base, config->prop_crtc_h, 0); 146 drm_object_attach_property(&plane->base, config->prop_src_x, 0); 147 drm_object_attach_property(&plane->base, config->prop_src_y, 0); 148 drm_object_attach_property(&plane->base, config->prop_src_w, 0); 149 drm_object_attach_property(&plane->base, config->prop_src_h, 0); 150 } 151 152 return 0; 153 } 154 EXPORT_SYMBOL(drm_universal_plane_init); 155 156 int drm_plane_register_all(struct drm_device *dev) 157 { 158 struct drm_plane *plane; 159 int ret = 0; 160 161 drm_for_each_plane(plane, dev) { 162 if (plane->funcs->late_register) 163 ret = plane->funcs->late_register(plane); 164 if (ret) 165 return ret; 166 } 167 168 return 0; 169 } 170 171 void drm_plane_unregister_all(struct drm_device *dev) 172 { 173 struct drm_plane *plane; 174 175 drm_for_each_plane(plane, dev) { 176 if (plane->funcs->early_unregister) 177 plane->funcs->early_unregister(plane); 178 } 179 } 180 181 /** 182 * drm_plane_init - Initialize a legacy plane 183 * @dev: DRM device 184 * @plane: plane object to init 185 * @possible_crtcs: bitmask of possible CRTCs 186 * @funcs: callbacks for the new plane 187 * @formats: array of supported formats (DRM_FORMAT\_\*) 188 * @format_count: number of elements in @formats 189 * @is_primary: plane type (primary vs overlay) 190 * 191 * Legacy API to initialize a DRM plane. 192 * 193 * New drivers should call drm_universal_plane_init() instead. 194 * 195 * Returns: 196 * Zero on success, error code on failure. 197 */ 198 int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, 199 uint32_t possible_crtcs, 200 const struct drm_plane_funcs *funcs, 201 const uint32_t *formats, unsigned int format_count, 202 bool is_primary) 203 { 204 enum drm_plane_type type; 205 206 type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; 207 return drm_universal_plane_init(dev, plane, possible_crtcs, funcs, 208 formats, format_count, type, NULL); 209 } 210 EXPORT_SYMBOL(drm_plane_init); 211 212 /** 213 * drm_plane_cleanup - Clean up the core plane usage 214 * @plane: plane to cleanup 215 * 216 * This function cleans up @plane and removes it from the DRM mode setting 217 * core. Note that the function does *not* free the plane structure itself, 218 * this is the responsibility of the caller. 219 */ 220 void drm_plane_cleanup(struct drm_plane *plane) 221 { 222 struct drm_device *dev = plane->dev; 223 224 drm_modeset_lock_fini(&plane->mutex); 225 226 kfree(plane->format_types); 227 drm_mode_object_unregister(dev, &plane->base); 228 229 BUG_ON(list_empty(&plane->head)); 230 231 /* Note that the plane_list is considered to be static; should we 232 * remove the drm_plane at runtime we would have to decrement all 233 * the indices on the drm_plane after us in the plane_list. 234 */ 235 236 list_del(&plane->head); 237 dev->mode_config.num_total_plane--; 238 if (plane->type == DRM_PLANE_TYPE_OVERLAY) 239 dev->mode_config.num_overlay_plane--; 240 241 WARN_ON(plane->state && !plane->funcs->atomic_destroy_state); 242 if (plane->state && plane->funcs->atomic_destroy_state) 243 plane->funcs->atomic_destroy_state(plane, plane->state); 244 245 kfree(plane->name); 246 247 memset(plane, 0, sizeof(*plane)); 248 } 249 EXPORT_SYMBOL(drm_plane_cleanup); 250 251 /** 252 * drm_plane_from_index - find the registered plane at an index 253 * @dev: DRM device 254 * @idx: index of registered plane to find for 255 * 256 * Given a plane index, return the registered plane from DRM device's 257 * list of planes with matching index. This is the inverse of drm_plane_index(). 258 */ 259 struct drm_plane * 260 drm_plane_from_index(struct drm_device *dev, int idx) 261 { 262 struct drm_plane *plane; 263 264 drm_for_each_plane(plane, dev) 265 if (idx == plane->index) 266 return plane; 267 268 return NULL; 269 } 270 EXPORT_SYMBOL(drm_plane_from_index); 271 272 /** 273 * drm_plane_force_disable - Forcibly disable a plane 274 * @plane: plane to disable 275 * 276 * Forces the plane to be disabled. 277 * 278 * Used when the plane's current framebuffer is destroyed, 279 * and when restoring fbdev mode. 280 * 281 * Note that this function is not suitable for atomic drivers, since it doesn't 282 * wire through the lock acquisition context properly and hence can't handle 283 * retries or driver private locks. You probably want to use 284 * drm_atomic_helper_disable_plane() or 285 * drm_atomic_helper_disable_planes_on_crtc() instead. 286 */ 287 void drm_plane_force_disable(struct drm_plane *plane) 288 { 289 int ret; 290 291 if (!plane->fb) 292 return; 293 294 WARN_ON(drm_drv_uses_atomic_modeset(plane->dev)); 295 296 plane->old_fb = plane->fb; 297 ret = plane->funcs->disable_plane(plane, NULL); 298 if (ret) { 299 DRM_ERROR("failed to disable plane with busy fb\n"); 300 plane->old_fb = NULL; 301 return; 302 } 303 /* disconnect the plane from the fb and crtc: */ 304 drm_framebuffer_put(plane->old_fb); 305 plane->old_fb = NULL; 306 plane->fb = NULL; 307 plane->crtc = NULL; 308 } 309 EXPORT_SYMBOL(drm_plane_force_disable); 310 311 /** 312 * drm_mode_plane_set_obj_prop - set the value of a property 313 * @plane: drm plane object to set property value for 314 * @property: property to set 315 * @value: value the property should be set to 316 * 317 * This functions sets a given property on a given plane object. This function 318 * calls the driver's ->set_property callback and changes the software state of 319 * the property if the callback succeeds. 320 * 321 * Returns: 322 * Zero on success, error code on failure. 323 */ 324 int drm_mode_plane_set_obj_prop(struct drm_plane *plane, 325 struct drm_property *property, 326 uint64_t value) 327 { 328 int ret = -EINVAL; 329 struct drm_mode_object *obj = &plane->base; 330 331 if (plane->funcs->set_property) 332 ret = plane->funcs->set_property(plane, property, value); 333 if (!ret) 334 drm_object_property_set_value(obj, property, value); 335 336 return ret; 337 } 338 EXPORT_SYMBOL(drm_mode_plane_set_obj_prop); 339 340 int drm_mode_getplane_res(struct drm_device *dev, void *data, 341 struct drm_file *file_priv) 342 { 343 struct drm_mode_get_plane_res *plane_resp = data; 344 struct drm_mode_config *config; 345 struct drm_plane *plane; 346 uint32_t __user *plane_ptr; 347 int copied = 0; 348 unsigned num_planes; 349 350 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 351 return -EINVAL; 352 353 config = &dev->mode_config; 354 355 if (file_priv->universal_planes) 356 num_planes = config->num_total_plane; 357 else 358 num_planes = config->num_overlay_plane; 359 360 /* 361 * This ioctl is called twice, once to determine how much space is 362 * needed, and the 2nd time to fill it. 363 */ 364 if (num_planes && 365 (plane_resp->count_planes >= num_planes)) { 366 plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; 367 368 /* Plane lists are invariant, no locking needed. */ 369 drm_for_each_plane(plane, dev) { 370 /* 371 * Unless userspace set the 'universal planes' 372 * capability bit, only advertise overlays. 373 */ 374 if (plane->type != DRM_PLANE_TYPE_OVERLAY && 375 !file_priv->universal_planes) 376 continue; 377 378 if (put_user(plane->base.id, plane_ptr + copied)) 379 return -EFAULT; 380 copied++; 381 } 382 } 383 plane_resp->count_planes = num_planes; 384 385 return 0; 386 } 387 388 int drm_mode_getplane(struct drm_device *dev, void *data, 389 struct drm_file *file_priv) 390 { 391 struct drm_mode_get_plane *plane_resp = data; 392 struct drm_plane *plane; 393 uint32_t __user *format_ptr; 394 395 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 396 return -EINVAL; 397 398 plane = drm_plane_find(dev, plane_resp->plane_id); 399 if (!plane) 400 return -ENOENT; 401 402 drm_modeset_lock(&plane->mutex, NULL); 403 if (plane->state && plane->state->crtc) 404 plane_resp->crtc_id = plane->state->crtc->base.id; 405 else if (!plane->state && plane->crtc) 406 plane_resp->crtc_id = plane->crtc->base.id; 407 else 408 plane_resp->crtc_id = 0; 409 410 if (plane->state && plane->state->fb) 411 plane_resp->fb_id = plane->state->fb->base.id; 412 else if (!plane->state && plane->fb) 413 plane_resp->fb_id = plane->fb->base.id; 414 else 415 plane_resp->fb_id = 0; 416 drm_modeset_unlock(&plane->mutex); 417 418 plane_resp->plane_id = plane->base.id; 419 plane_resp->possible_crtcs = plane->possible_crtcs; 420 plane_resp->gamma_size = 0; 421 422 /* 423 * This ioctl is called twice, once to determine how much space is 424 * needed, and the 2nd time to fill it. 425 */ 426 if (plane->format_count && 427 (plane_resp->count_format_types >= plane->format_count)) { 428 format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr; 429 if (copy_to_user(format_ptr, 430 plane->format_types, 431 sizeof(uint32_t) * plane->format_count)) { 432 return -EFAULT; 433 } 434 } 435 plane_resp->count_format_types = plane->format_count; 436 437 return 0; 438 } 439 440 int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format) 441 { 442 unsigned int i; 443 444 for (i = 0; i < plane->format_count; i++) { 445 if (format == plane->format_types[i]) 446 return 0; 447 } 448 449 return -EINVAL; 450 } 451 452 /* 453 * setplane_internal - setplane handler for internal callers 454 * 455 * Note that we assume an extra reference has already been taken on fb. If the 456 * update fails, this reference will be dropped before return; if it succeeds, 457 * the previous framebuffer (if any) will be unreferenced instead. 458 * 459 * src_{x,y,w,h} are provided in 16.16 fixed point format 460 */ 461 static int __setplane_internal(struct drm_plane *plane, 462 struct drm_crtc *crtc, 463 struct drm_framebuffer *fb, 464 int32_t crtc_x, int32_t crtc_y, 465 uint32_t crtc_w, uint32_t crtc_h, 466 /* src_{x,y,w,h} values are 16.16 fixed point */ 467 uint32_t src_x, uint32_t src_y, 468 uint32_t src_w, uint32_t src_h, 469 struct drm_modeset_acquire_ctx *ctx) 470 { 471 int ret = 0; 472 473 /* No fb means shut it down */ 474 if (!fb) { 475 plane->old_fb = plane->fb; 476 ret = plane->funcs->disable_plane(plane, ctx); 477 if (!ret) { 478 plane->crtc = NULL; 479 plane->fb = NULL; 480 } else { 481 plane->old_fb = NULL; 482 } 483 goto out; 484 } 485 486 /* Check whether this plane is usable on this CRTC */ 487 if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) { 488 DRM_DEBUG_KMS("Invalid crtc for plane\n"); 489 ret = -EINVAL; 490 goto out; 491 } 492 493 /* Check whether this plane supports the fb pixel format. */ 494 ret = drm_plane_check_pixel_format(plane, fb->format->format); 495 if (ret) { 496 struct drm_format_name_buf format_name; 497 DRM_DEBUG_KMS("Invalid pixel format %s\n", 498 drm_get_format_name(fb->format->format, 499 &format_name)); 500 goto out; 501 } 502 503 /* Give drivers some help against integer overflows */ 504 if (crtc_w > INT_MAX || 505 crtc_x > INT_MAX - (int32_t) crtc_w || 506 crtc_h > INT_MAX || 507 crtc_y > INT_MAX - (int32_t) crtc_h) { 508 DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", 509 crtc_w, crtc_h, crtc_x, crtc_y); 510 ret = -ERANGE; 511 goto out; 512 } 513 514 ret = drm_framebuffer_check_src_coords(src_x, src_y, src_w, src_h, fb); 515 if (ret) 516 goto out; 517 518 plane->old_fb = plane->fb; 519 ret = plane->funcs->update_plane(plane, crtc, fb, 520 crtc_x, crtc_y, crtc_w, crtc_h, 521 src_x, src_y, src_w, src_h, ctx); 522 if (!ret) { 523 plane->crtc = crtc; 524 plane->fb = fb; 525 fb = NULL; 526 } else { 527 plane->old_fb = NULL; 528 } 529 530 out: 531 if (fb) 532 drm_framebuffer_put(fb); 533 if (plane->old_fb) 534 drm_framebuffer_put(plane->old_fb); 535 plane->old_fb = NULL; 536 537 return ret; 538 } 539 540 static int setplane_internal(struct drm_plane *plane, 541 struct drm_crtc *crtc, 542 struct drm_framebuffer *fb, 543 int32_t crtc_x, int32_t crtc_y, 544 uint32_t crtc_w, uint32_t crtc_h, 545 /* src_{x,y,w,h} values are 16.16 fixed point */ 546 uint32_t src_x, uint32_t src_y, 547 uint32_t src_w, uint32_t src_h) 548 { 549 struct drm_modeset_acquire_ctx ctx; 550 int ret; 551 552 drm_modeset_acquire_init(&ctx, 0); 553 retry: 554 ret = drm_modeset_lock_all_ctx(plane->dev, &ctx); 555 if (ret) 556 goto fail; 557 ret = __setplane_internal(plane, crtc, fb, 558 crtc_x, crtc_y, crtc_w, crtc_h, 559 src_x, src_y, src_w, src_h, &ctx); 560 561 fail: 562 if (ret == -EDEADLK) { 563 drm_modeset_backoff(&ctx); 564 goto retry; 565 } 566 drm_modeset_drop_locks(&ctx); 567 drm_modeset_acquire_fini(&ctx); 568 569 return ret; 570 } 571 572 int drm_mode_setplane(struct drm_device *dev, void *data, 573 struct drm_file *file_priv) 574 { 575 struct drm_mode_set_plane *plane_req = data; 576 struct drm_plane *plane; 577 struct drm_crtc *crtc = NULL; 578 struct drm_framebuffer *fb = NULL; 579 580 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 581 return -EINVAL; 582 583 /* 584 * First, find the plane, crtc, and fb objects. If not available, 585 * we don't bother to call the driver. 586 */ 587 plane = drm_plane_find(dev, plane_req->plane_id); 588 if (!plane) { 589 DRM_DEBUG_KMS("Unknown plane ID %d\n", 590 plane_req->plane_id); 591 return -ENOENT; 592 } 593 594 if (plane_req->fb_id) { 595 fb = drm_framebuffer_lookup(dev, plane_req->fb_id); 596 if (!fb) { 597 DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", 598 plane_req->fb_id); 599 return -ENOENT; 600 } 601 602 crtc = drm_crtc_find(dev, plane_req->crtc_id); 603 if (!crtc) { 604 DRM_DEBUG_KMS("Unknown crtc ID %d\n", 605 plane_req->crtc_id); 606 return -ENOENT; 607 } 608 } 609 610 /* 611 * setplane_internal will take care of deref'ing either the old or new 612 * framebuffer depending on success. 613 */ 614 return setplane_internal(plane, crtc, fb, 615 plane_req->crtc_x, plane_req->crtc_y, 616 plane_req->crtc_w, plane_req->crtc_h, 617 plane_req->src_x, plane_req->src_y, 618 plane_req->src_w, plane_req->src_h); 619 } 620 621 static int drm_mode_cursor_universal(struct drm_crtc *crtc, 622 struct drm_mode_cursor2 *req, 623 struct drm_file *file_priv, 624 struct drm_modeset_acquire_ctx *ctx) 625 { 626 struct drm_device *dev = crtc->dev; 627 struct drm_framebuffer *fb = NULL; 628 struct drm_mode_fb_cmd2 fbreq = { 629 .width = req->width, 630 .height = req->height, 631 .pixel_format = DRM_FORMAT_ARGB8888, 632 .pitches = { req->width * 4 }, 633 .handles = { req->handle }, 634 }; 635 int32_t crtc_x, crtc_y; 636 uint32_t crtc_w = 0, crtc_h = 0; 637 uint32_t src_w = 0, src_h = 0; 638 int ret = 0; 639 640 BUG_ON(!crtc->cursor); 641 WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL); 642 643 /* 644 * Obtain fb we'll be using (either new or existing) and take an extra 645 * reference to it if fb != null. setplane will take care of dropping 646 * the reference if the plane update fails. 647 */ 648 if (req->flags & DRM_MODE_CURSOR_BO) { 649 if (req->handle) { 650 fb = drm_internal_framebuffer_create(dev, &fbreq, file_priv); 651 if (IS_ERR(fb)) { 652 DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n"); 653 return PTR_ERR(fb); 654 } 655 fb->hot_x = req->hot_x; 656 fb->hot_y = req->hot_y; 657 } else { 658 fb = NULL; 659 } 660 } else { 661 fb = crtc->cursor->fb; 662 if (fb) 663 drm_framebuffer_get(fb); 664 } 665 666 if (req->flags & DRM_MODE_CURSOR_MOVE) { 667 crtc_x = req->x; 668 crtc_y = req->y; 669 } else { 670 crtc_x = crtc->cursor_x; 671 crtc_y = crtc->cursor_y; 672 } 673 674 if (fb) { 675 crtc_w = fb->width; 676 crtc_h = fb->height; 677 src_w = fb->width << 16; 678 src_h = fb->height << 16; 679 } 680 681 /* 682 * setplane_internal will take care of deref'ing either the old or new 683 * framebuffer depending on success. 684 */ 685 ret = __setplane_internal(crtc->cursor, crtc, fb, 686 crtc_x, crtc_y, crtc_w, crtc_h, 687 0, 0, src_w, src_h, ctx); 688 689 /* Update successful; save new cursor position, if necessary */ 690 if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) { 691 crtc->cursor_x = req->x; 692 crtc->cursor_y = req->y; 693 } 694 695 return ret; 696 } 697 698 static int drm_mode_cursor_common(struct drm_device *dev, 699 struct drm_mode_cursor2 *req, 700 struct drm_file *file_priv) 701 { 702 struct drm_crtc *crtc; 703 struct drm_modeset_acquire_ctx ctx; 704 int ret = 0; 705 706 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 707 return -EINVAL; 708 709 if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags)) 710 return -EINVAL; 711 712 crtc = drm_crtc_find(dev, req->crtc_id); 713 if (!crtc) { 714 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id); 715 return -ENOENT; 716 } 717 718 drm_modeset_acquire_init(&ctx, 0); 719 retry: 720 ret = drm_modeset_lock(&crtc->mutex, &ctx); 721 if (ret) 722 goto out; 723 /* 724 * If this crtc has a universal cursor plane, call that plane's update 725 * handler rather than using legacy cursor handlers. 726 */ 727 if (crtc->cursor) { 728 ret = drm_modeset_lock(&crtc->cursor->mutex, &ctx); 729 if (ret) 730 goto out; 731 732 ret = drm_mode_cursor_universal(crtc, req, file_priv, &ctx); 733 goto out; 734 } 735 736 if (req->flags & DRM_MODE_CURSOR_BO) { 737 if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { 738 ret = -ENXIO; 739 goto out; 740 } 741 /* Turns off the cursor if handle is 0 */ 742 if (crtc->funcs->cursor_set2) 743 ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle, 744 req->width, req->height, req->hot_x, req->hot_y); 745 else 746 ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle, 747 req->width, req->height); 748 } 749 750 if (req->flags & DRM_MODE_CURSOR_MOVE) { 751 if (crtc->funcs->cursor_move) { 752 ret = crtc->funcs->cursor_move(crtc, req->x, req->y); 753 } else { 754 ret = -EFAULT; 755 goto out; 756 } 757 } 758 out: 759 if (ret == -EDEADLK) { 760 drm_modeset_backoff(&ctx); 761 goto retry; 762 } 763 764 drm_modeset_drop_locks(&ctx); 765 drm_modeset_acquire_fini(&ctx); 766 767 return ret; 768 769 } 770 771 772 int drm_mode_cursor_ioctl(struct drm_device *dev, 773 void *data, struct drm_file *file_priv) 774 { 775 struct drm_mode_cursor *req = data; 776 struct drm_mode_cursor2 new_req; 777 778 memcpy(&new_req, req, sizeof(struct drm_mode_cursor)); 779 new_req.hot_x = new_req.hot_y = 0; 780 781 return drm_mode_cursor_common(dev, &new_req, file_priv); 782 } 783 784 /* 785 * Set the cursor configuration based on user request. This implements the 2nd 786 * version of the cursor ioctl, which allows userspace to additionally specify 787 * the hotspot of the pointer. 788 */ 789 int drm_mode_cursor2_ioctl(struct drm_device *dev, 790 void *data, struct drm_file *file_priv) 791 { 792 struct drm_mode_cursor2 *req = data; 793 794 return drm_mode_cursor_common(dev, req, file_priv); 795 } 796 797 int drm_mode_page_flip_ioctl(struct drm_device *dev, 798 void *data, struct drm_file *file_priv) 799 { 800 struct drm_mode_crtc_page_flip_target *page_flip = data; 801 struct drm_crtc *crtc; 802 struct drm_framebuffer *fb = NULL; 803 struct drm_pending_vblank_event *e = NULL; 804 u32 target_vblank = page_flip->sequence; 805 struct drm_modeset_acquire_ctx ctx; 806 int ret = -EINVAL; 807 808 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 809 return -EINVAL; 810 811 if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS) 812 return -EINVAL; 813 814 if (page_flip->sequence != 0 && !(page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) 815 return -EINVAL; 816 817 /* Only one of the DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags 818 * can be specified 819 */ 820 if ((page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) == DRM_MODE_PAGE_FLIP_TARGET) 821 return -EINVAL; 822 823 if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip) 824 return -EINVAL; 825 826 crtc = drm_crtc_find(dev, page_flip->crtc_id); 827 if (!crtc) 828 return -ENOENT; 829 830 if (crtc->funcs->page_flip_target) { 831 u32 current_vblank; 832 int r; 833 834 r = drm_crtc_vblank_get(crtc); 835 if (r) 836 return r; 837 838 current_vblank = drm_crtc_vblank_count(crtc); 839 840 switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) { 841 case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE: 842 if ((int)(target_vblank - current_vblank) > 1) { 843 DRM_DEBUG("Invalid absolute flip target %u, " 844 "must be <= %u\n", target_vblank, 845 current_vblank + 1); 846 drm_crtc_vblank_put(crtc); 847 return -EINVAL; 848 } 849 break; 850 case DRM_MODE_PAGE_FLIP_TARGET_RELATIVE: 851 if (target_vblank != 0 && target_vblank != 1) { 852 DRM_DEBUG("Invalid relative flip target %u, " 853 "must be 0 or 1\n", target_vblank); 854 drm_crtc_vblank_put(crtc); 855 return -EINVAL; 856 } 857 target_vblank += current_vblank; 858 break; 859 default: 860 target_vblank = current_vblank + 861 !(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC); 862 break; 863 } 864 } else if (crtc->funcs->page_flip == NULL || 865 (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) { 866 return -EINVAL; 867 } 868 869 drm_modeset_acquire_init(&ctx, 0); 870 retry: 871 ret = drm_modeset_lock(&crtc->mutex, &ctx); 872 if (ret) 873 goto out; 874 ret = drm_modeset_lock(&crtc->primary->mutex, &ctx); 875 if (ret) 876 goto out; 877 878 if (crtc->primary->fb == NULL) { 879 /* The framebuffer is currently unbound, presumably 880 * due to a hotplug event, that userspace has not 881 * yet discovered. 882 */ 883 ret = -EBUSY; 884 goto out; 885 } 886 887 fb = drm_framebuffer_lookup(dev, page_flip->fb_id); 888 if (!fb) { 889 ret = -ENOENT; 890 goto out; 891 } 892 893 if (crtc->state) { 894 const struct drm_plane_state *state = crtc->primary->state; 895 896 ret = drm_framebuffer_check_src_coords(state->src_x, 897 state->src_y, 898 state->src_w, 899 state->src_h, 900 fb); 901 } else { 902 ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, &crtc->mode, fb); 903 } 904 if (ret) 905 goto out; 906 907 if (crtc->primary->fb->format != fb->format) { 908 DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n"); 909 ret = -EINVAL; 910 goto out; 911 } 912 913 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 914 e = kzalloc(sizeof *e, GFP_KERNEL); 915 if (!e) { 916 ret = -ENOMEM; 917 goto out; 918 } 919 e->event.base.type = DRM_EVENT_FLIP_COMPLETE; 920 e->event.base.length = sizeof(e->event); 921 e->event.user_data = page_flip->user_data; 922 ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base); 923 if (ret) { 924 kfree(e); 925 e = NULL; 926 goto out; 927 } 928 } 929 930 crtc->primary->old_fb = crtc->primary->fb; 931 if (crtc->funcs->page_flip_target) 932 ret = crtc->funcs->page_flip_target(crtc, fb, e, 933 page_flip->flags, 934 target_vblank, 935 &ctx); 936 else 937 ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags, 938 &ctx); 939 if (ret) { 940 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) 941 drm_event_cancel_free(dev, &e->base); 942 /* Keep the old fb, don't unref it. */ 943 crtc->primary->old_fb = NULL; 944 } else { 945 crtc->primary->fb = fb; 946 /* Unref only the old framebuffer. */ 947 fb = NULL; 948 } 949 950 out: 951 if (ret && crtc->funcs->page_flip_target) 952 drm_crtc_vblank_put(crtc); 953 if (fb) 954 drm_framebuffer_put(fb); 955 if (crtc->primary->old_fb) 956 drm_framebuffer_put(crtc->primary->old_fb); 957 crtc->primary->old_fb = NULL; 958 959 if (ret == -EDEADLK) { 960 drm_modeset_backoff(&ctx); 961 goto retry; 962 } 963 964 drm_modeset_drop_locks(&ctx); 965 drm_modeset_acquire_fini(&ctx); 966 967 return ret; 968 } 969