Rev 5060 | Rev 6084 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5060 | Rev 5271 | ||
---|---|---|---|
Line 25... | Line 25... | ||
25 | 25 | ||
26 | #include |
26 | #include |
27 | #include |
27 | #include |
28 | #include |
28 | #include |
- | 29 | #include |
|
29 | #include |
30 | #include |
- | 31 | #include |
|
Line 30... | Line 32... | ||
30 | #include |
32 | #include |
Line -... | Line 33... | ||
- | 33 | ||
- | 34 | #define SUBPIXEL_MASK 0xffff |
|
- | 35 | ||
- | 36 | /** |
|
- | 37 | * DOC: overview |
|
- | 38 | * |
|
- | 39 | * This helper library has two parts. The first part has support to implement |
|
- | 40 | * primary plane support on top of the normal CRTC configuration interface. |
|
- | 41 | * Since the legacy ->set_config interface ties the primary plane together with |
|
- | 42 | * the CRTC state this does not allow userspace to disable the primary plane |
|
- | 43 | * itself. To avoid too much duplicated code use |
|
- | 44 | * drm_plane_helper_check_update() which can be used to enforce the same |
|
- | 45 | * restrictions as primary planes had thus. The default primary plane only |
|
- | 46 | * expose XRBG8888 and ARGB8888 as valid pixel formats for the attached |
|
- | 47 | * framebuffer. |
|
- | 48 | * |
|
- | 49 | * Drivers are highly recommended to implement proper support for primary |
|
- | 50 | * planes, and newly merged drivers must not rely upon these transitional |
|
- | 51 | * helpers. |
|
- | 52 | * |
|
- | 53 | * The second part also implements transitional helpers which allow drivers to |
|
- | 54 | * gradually switch to the atomic helper infrastructure for plane updates. Once |
|
- | 55 | * that switch is complete drivers shouldn't use these any longer, instead using |
|
- | 56 | * the proper legacy implementations for update and disable plane hooks provided |
|
- | 57 | * by the atomic helpers. |
|
- | 58 | * |
|
31 | 59 | * Again drivers are strongly urged to switch to the new interfaces. |
|
32 | #define SUBPIXEL_MASK 0xffff |
60 | */ |
33 | 61 | ||
34 | /* |
62 | /* |
35 | * This is the minimal list of formats that seem to be safe for modeset use |
63 | * This is the minimal list of formats that seem to be safe for modeset use |
Line 125... | Line 153... | ||
125 | if (hscale < 0 || vscale < 0) { |
153 | if (hscale < 0 || vscale < 0) { |
126 | DRM_DEBUG_KMS("Invalid scaling of plane\n"); |
154 | DRM_DEBUG_KMS("Invalid scaling of plane\n"); |
127 | return -ERANGE; |
155 | return -ERANGE; |
128 | } |
156 | } |
Line -... | Line 157... | ||
- | 157 | ||
- | 158 | if (!fb) { |
|
- | 159 | *visible = false; |
|
- | 160 | return 0; |
|
- | 161 | } |
|
129 | 162 | ||
130 | *visible = drm_rect_clip_scaled(src, dest, clip, hscale, vscale); |
163 | *visible = drm_rect_clip_scaled(src, dest, clip, hscale, vscale); |
131 | if (!*visible) |
164 | if (!*visible) |
132 | /* |
165 | /* |
133 | * Plane isn't visible; some drivers can handle this |
166 | * Plane isn't visible; some drivers can handle this |
Line 367... | Line 400... | ||
367 | 400 | ||
368 | primary = drm_primary_helper_create_plane(dev, NULL, 0); |
401 | primary = drm_primary_helper_create_plane(dev, NULL, 0); |
369 | return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs); |
402 | return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs); |
370 | } |
403 | } |
- | 404 | EXPORT_SYMBOL(drm_crtc_init); |
|
- | 405 | ||
- | 406 | int drm_plane_helper_commit(struct drm_plane *plane, |
|
- | 407 | struct drm_plane_state *plane_state, |
|
- | 408 | struct drm_framebuffer *old_fb) |
|
- | 409 | { |
|
- | 410 | struct drm_plane_helper_funcs *plane_funcs; |
|
- | 411 | struct drm_crtc *crtc[2]; |
|
- | 412 | struct drm_crtc_helper_funcs *crtc_funcs[2]; |
|
- | 413 | int i, ret = 0; |
|
- | 414 | ||
- | 415 | plane_funcs = plane->helper_private; |
|
- | 416 | ||
- | 417 | /* Since this is a transitional helper we can't assume that plane->state |
|
- | 418 | * is always valid. Hence we need to use plane->crtc instead of |
|
- | 419 | * plane->state->crtc as the old crtc. */ |
|
- | 420 | crtc[0] = plane->crtc; |
|
- | 421 | crtc[1] = crtc[0] != plane_state->crtc ? plane_state->crtc : NULL; |
|
- | 422 | ||
- | 423 | for (i = 0; i < 2; i++) |
|
- | 424 | crtc_funcs[i] = crtc[i] ? crtc[i]->helper_private : NULL; |
|
- | 425 | ||
- | 426 | if (plane_funcs->atomic_check) { |
|
- | 427 | ret = plane_funcs->atomic_check(plane, plane_state); |
|
- | 428 | if (ret) |
|
- | 429 | goto out; |
|
- | 430 | } |
|
- | 431 | ||
- | 432 | if (plane_funcs->prepare_fb && plane_state->fb) { |
|
- | 433 | ret = plane_funcs->prepare_fb(plane, plane_state->fb); |
|
- | 434 | if (ret) |
|
- | 435 | goto out; |
|
- | 436 | } |
|
- | 437 | ||
- | 438 | /* Point of no return, commit sw state. */ |
|
- | 439 | swap(plane->state, plane_state); |
|
- | 440 | ||
- | 441 | for (i = 0; i < 2; i++) { |
|
- | 442 | if (crtc_funcs[i] && crtc_funcs[i]->atomic_begin) |
|
- | 443 | crtc_funcs[i]->atomic_begin(crtc[i]); |
|
- | 444 | } |
|
- | 445 | ||
- | 446 | plane_funcs->atomic_update(plane, plane_state); |
|
- | 447 | ||
- | 448 | for (i = 0; i < 2; i++) { |
|
- | 449 | if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush) |
|
- | 450 | crtc_funcs[i]->atomic_flush(crtc[i]); |
|
- | 451 | } |
|
- | 452 | ||
- | 453 | for (i = 0; i < 2; i++) { |
|
- | 454 | if (!crtc[i]) |
|
- | 455 | continue; |
|
- | 456 | ||
- | 457 | /* There's no other way to figure out whether the crtc is running. */ |
|
- | 458 | ret = drm_crtc_vblank_get(crtc[i]); |
|
- | 459 | if (ret == 0) { |
|
- | 460 | drm_crtc_wait_one_vblank(crtc[i]); |
|
- | 461 | drm_crtc_vblank_put(crtc[i]); |
|
- | 462 | } |
|
- | 463 | ||
- | 464 | ret = 0; |
|
- | 465 | } |
|
- | 466 | ||
- | 467 | if (plane_funcs->cleanup_fb && old_fb) |
|
- | 468 | plane_funcs->cleanup_fb(plane, old_fb); |
|
- | 469 | out: |
|
- | 470 | if (plane_state) { |
|
- | 471 | if (plane->funcs->atomic_destroy_state) |
|
- | 472 | plane->funcs->atomic_destroy_state(plane, plane_state); |
|
- | 473 | else |
|
- | 474 | drm_atomic_helper_plane_destroy_state(plane, plane_state); |
|
- | 475 | } |
|
- | 476 | ||
- | 477 | return ret; |
|
- | 478 | } |
|
- | 479 | ||
- | 480 | /** |
|
- | 481 | * drm_plane_helper_update() - Helper for primary plane update |
|
- | 482 | * @plane: plane object to update |
|
- | 483 | * @crtc: owning CRTC of owning plane |
|
- | 484 | * @fb: framebuffer to flip onto plane |
|
- | 485 | * @crtc_x: x offset of primary plane on crtc |
|
- | 486 | * @crtc_y: y offset of primary plane on crtc |
|
- | 487 | * @crtc_w: width of primary plane rectangle on crtc |
|
- | 488 | * @crtc_h: height of primary plane rectangle on crtc |
|
- | 489 | * @src_x: x offset of @fb for panning |
|
- | 490 | * @src_y: y offset of @fb for panning |
|
- | 491 | * @src_w: width of source rectangle in @fb |
|
- | 492 | * @src_h: height of source rectangle in @fb |
|
- | 493 | * |
|
- | 494 | * Provides a default plane update handler using the atomic plane update |
|
- | 495 | * functions. It is fully left to the driver to check plane constraints and |
|
- | 496 | * handle corner-cases like a fully occluded or otherwise invisible plane. |
|
- | 497 | * |
|
- | 498 | * This is useful for piecewise transitioning of a driver to the atomic helpers. |
|
- | 499 | * |
|
- | 500 | * RETURNS: |
|
- | 501 | * Zero on success, error code on failure |
|
- | 502 | */ |
|
- | 503 | int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, |
|
- | 504 | struct drm_framebuffer *fb, |
|
- | 505 | int crtc_x, int crtc_y, |
|
- | 506 | unsigned int crtc_w, unsigned int crtc_h, |
|
- | 507 | uint32_t src_x, uint32_t src_y, |
|
- | 508 | uint32_t src_w, uint32_t src_h) |
|
- | 509 | { |
|
- | 510 | struct drm_plane_state *plane_state; |
|
- | 511 | ||
- | 512 | if (plane->funcs->atomic_duplicate_state) |
|
- | 513 | plane_state = plane->funcs->atomic_duplicate_state(plane); |
|
- | 514 | else if (plane->state) |
|
- | 515 | plane_state = drm_atomic_helper_plane_duplicate_state(plane); |
|
- | 516 | else |
|
- | 517 | plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); |
|
- | 518 | if (!plane_state) |
|
- | 519 | return -ENOMEM; |
|
- | 520 | ||
- | 521 | plane_state->crtc = crtc; |
|
- | 522 | drm_atomic_set_fb_for_plane(plane_state, fb); |
|
- | 523 | plane_state->crtc_x = crtc_x; |
|
- | 524 | plane_state->crtc_y = crtc_y; |
|
- | 525 | plane_state->crtc_h = crtc_h; |
|
- | 526 | plane_state->crtc_w = crtc_w; |
|
- | 527 | plane_state->src_x = src_x; |
|
- | 528 | plane_state->src_y = src_y; |
|
- | 529 | plane_state->src_h = src_h; |
|
- | 530 | plane_state->src_w = src_w; |
|
- | 531 | ||
- | 532 | return drm_plane_helper_commit(plane, plane_state, plane->fb); |
|
- | 533 | } |
|
- | 534 | EXPORT_SYMBOL(drm_plane_helper_update); |
|
- | 535 | ||
- | 536 | /** |
|
- | 537 | * drm_plane_helper_disable() - Helper for primary plane disable |
|
- | 538 | * @plane: plane to disable |
|
- | 539 | * |
|
- | 540 | * Provides a default plane disable handler using the atomic plane update |
|
- | 541 | * functions. It is fully left to the driver to check plane constraints and |
|
- | 542 | * handle corner-cases like a fully occluded or otherwise invisible plane. |
|
- | 543 | * |
|
- | 544 | * This is useful for piecewise transitioning of a driver to the atomic helpers. |
|
- | 545 | * |
|
- | 546 | * RETURNS: |
|
- | 547 | * Zero on success, error code on failure |
|
- | 548 | */ |
|
- | 549 | int drm_plane_helper_disable(struct drm_plane *plane) |
|
- | 550 | { |
|
- | 551 | struct drm_plane_state *plane_state; |
|
- | 552 | ||
- | 553 | /* crtc helpers love to call disable functions for already disabled hw |
|
- | 554 | * functions. So cope with that. */ |
|
- | 555 | if (!plane->crtc) |
|
- | 556 | return 0; |
|
- | 557 | ||
- | 558 | if (plane->funcs->atomic_duplicate_state) |
|
- | 559 | plane_state = plane->funcs->atomic_duplicate_state(plane); |
|
- | 560 | else if (plane->state) |
|
- | 561 | plane_state = drm_atomic_helper_plane_duplicate_state(plane); |
|
- | 562 | else |
|
- | 563 | plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); |
|
- | 564 | if (!plane_state) |
|
- | 565 | return -ENOMEM; |
|
- | 566 | ||
- | 567 | plane_state->crtc = NULL; |
|
- | 568 | drm_atomic_set_fb_for_plane(plane_state, NULL); |
|
- | 569 | ||
- | 570 | return drm_plane_helper_commit(plane, plane_state, plane->fb); |
|
- | 571 | } |