| .. | .. |
|---|
| 20 | 20 | * OF THIS SOFTWARE. |
|---|
| 21 | 21 | */ |
|---|
| 22 | 22 | |
|---|
| 23 | | -#include <drm/drmP.h> |
|---|
| 23 | +#include <linux/slab.h> |
|---|
| 24 | +#include <linux/uaccess.h> |
|---|
| 25 | + |
|---|
| 24 | 26 | #include <drm/drm_plane.h> |
|---|
| 27 | +#include <drm/drm_drv.h> |
|---|
| 28 | +#include <drm/drm_print.h> |
|---|
| 29 | +#include <drm/drm_framebuffer.h> |
|---|
| 30 | +#include <drm/drm_file.h> |
|---|
| 31 | +#include <drm/drm_crtc.h> |
|---|
| 32 | +#include <drm/drm_fourcc.h> |
|---|
| 33 | +#include <drm/drm_vblank.h> |
|---|
| 25 | 34 | |
|---|
| 26 | 35 | #include "drm_crtc_internal.h" |
|---|
| 27 | 36 | |
|---|
| .. | .. |
|---|
| 177 | 186 | if (WARN_ON(config->num_total_plane >= 32)) |
|---|
| 178 | 187 | return -EINVAL; |
|---|
| 179 | 188 | |
|---|
| 189 | + /* |
|---|
| 190 | + * First driver to need more than 64 formats needs to fix this. Each |
|---|
| 191 | + * format is encoded as a bit and the current code only supports a u64. |
|---|
| 192 | + */ |
|---|
| 193 | + if (WARN_ON(format_count > 64)) |
|---|
| 194 | + return -EINVAL; |
|---|
| 195 | + |
|---|
| 180 | 196 | WARN_ON(drm_drv_uses_atomic_modeset(dev) && |
|---|
| 181 | 197 | (!funcs->atomic_destroy_state || |
|---|
| 182 | 198 | !funcs->atomic_duplicate_state)); |
|---|
| .. | .. |
|---|
| 198 | 214 | return -ENOMEM; |
|---|
| 199 | 215 | } |
|---|
| 200 | 216 | |
|---|
| 201 | | - /* |
|---|
| 202 | | - * First driver to need more than 64 formats needs to fix this. Each |
|---|
| 203 | | - * format is encoded as a bit and the current code only supports a u64. |
|---|
| 204 | | - */ |
|---|
| 205 | | - if (WARN_ON(format_count > 64)) |
|---|
| 206 | | - return -EINVAL; |
|---|
| 207 | | - |
|---|
| 208 | 217 | if (format_modifiers) { |
|---|
| 209 | 218 | const uint64_t *temp_modifiers = format_modifiers; |
|---|
| 219 | + |
|---|
| 210 | 220 | while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID) |
|---|
| 211 | 221 | format_modifier_count++; |
|---|
| 212 | 222 | } |
|---|
| .. | .. |
|---|
| 280 | 290 | |
|---|
| 281 | 291 | int drm_plane_register_all(struct drm_device *dev) |
|---|
| 282 | 292 | { |
|---|
| 293 | + unsigned int num_planes = 0; |
|---|
| 294 | + unsigned int num_zpos = 0; |
|---|
| 283 | 295 | struct drm_plane *plane; |
|---|
| 284 | 296 | int ret = 0; |
|---|
| 285 | 297 | |
|---|
| .. | .. |
|---|
| 288 | 300 | ret = plane->funcs->late_register(plane); |
|---|
| 289 | 301 | if (ret) |
|---|
| 290 | 302 | return ret; |
|---|
| 303 | + |
|---|
| 304 | + if (plane->zpos_property) |
|---|
| 305 | + num_zpos++; |
|---|
| 306 | + num_planes++; |
|---|
| 291 | 307 | } |
|---|
| 308 | + |
|---|
| 309 | + drm_WARN(dev, num_zpos && num_planes != num_zpos, |
|---|
| 310 | + "Mixing planes with and without zpos property is invalid\n"); |
|---|
| 292 | 311 | |
|---|
| 293 | 312 | return 0; |
|---|
| 294 | 313 | } |
|---|
| .. | .. |
|---|
| 466 | 485 | struct drm_file *file_priv) |
|---|
| 467 | 486 | { |
|---|
| 468 | 487 | struct drm_mode_get_plane_res *plane_resp = data; |
|---|
| 469 | | - struct drm_mode_config *config; |
|---|
| 470 | 488 | struct drm_plane *plane; |
|---|
| 471 | 489 | uint32_t __user *plane_ptr; |
|---|
| 472 | 490 | int count = 0; |
|---|
| 473 | 491 | |
|---|
| 474 | 492 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
|---|
| 475 | | - return -EINVAL; |
|---|
| 493 | + return -EOPNOTSUPP; |
|---|
| 476 | 494 | |
|---|
| 477 | | - config = &dev->mode_config; |
|---|
| 478 | 495 | plane_ptr = u64_to_user_ptr(plane_resp->plane_id_ptr); |
|---|
| 479 | 496 | |
|---|
| 480 | 497 | /* |
|---|
| .. | .. |
|---|
| 510 | 527 | uint32_t __user *format_ptr; |
|---|
| 511 | 528 | |
|---|
| 512 | 529 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
|---|
| 513 | | - return -EINVAL; |
|---|
| 530 | + return -EOPNOTSUPP; |
|---|
| 514 | 531 | |
|---|
| 515 | 532 | plane = drm_plane_find(dev, file_priv, plane_resp->plane_id); |
|---|
| 516 | 533 | if (!plane) |
|---|
| .. | .. |
|---|
| 632 | 649 | return 0; |
|---|
| 633 | 650 | } |
|---|
| 634 | 651 | |
|---|
| 652 | +/** |
|---|
| 653 | + * drm_any_plane_has_format - Check whether any plane supports this format and modifier combination |
|---|
| 654 | + * @dev: DRM device |
|---|
| 655 | + * @format: pixel format (DRM_FORMAT_*) |
|---|
| 656 | + * @modifier: data layout modifier |
|---|
| 657 | + * |
|---|
| 658 | + * Returns: |
|---|
| 659 | + * Whether at least one plane supports the specified format and modifier combination. |
|---|
| 660 | + */ |
|---|
| 661 | +bool drm_any_plane_has_format(struct drm_device *dev, |
|---|
| 662 | + u32 format, u64 modifier) |
|---|
| 663 | +{ |
|---|
| 664 | + struct drm_plane *plane; |
|---|
| 665 | + |
|---|
| 666 | + drm_for_each_plane(plane, dev) { |
|---|
| 667 | + if (drm_plane_check_pixel_format(plane, format, modifier) == 0) |
|---|
| 668 | + return true; |
|---|
| 669 | + } |
|---|
| 670 | + |
|---|
| 671 | + return false; |
|---|
| 672 | +} |
|---|
| 673 | +EXPORT_SYMBOL(drm_any_plane_has_format); |
|---|
| 674 | + |
|---|
| 635 | 675 | /* |
|---|
| 636 | 676 | * __setplane_internal - setplane handler for internal callers |
|---|
| 637 | 677 | * |
|---|
| .. | .. |
|---|
| 740 | 780 | struct drm_modeset_acquire_ctx ctx; |
|---|
| 741 | 781 | int ret; |
|---|
| 742 | 782 | |
|---|
| 743 | | - drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); |
|---|
| 744 | | -retry: |
|---|
| 745 | | - ret = drm_modeset_lock_all_ctx(plane->dev, &ctx); |
|---|
| 746 | | - if (ret) |
|---|
| 747 | | - goto fail; |
|---|
| 783 | + DRM_MODESET_LOCK_ALL_BEGIN(plane->dev, ctx, |
|---|
| 784 | + DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret); |
|---|
| 748 | 785 | |
|---|
| 749 | 786 | if (drm_drv_uses_atomic_modeset(plane->dev)) |
|---|
| 750 | 787 | ret = __setplane_atomic(plane, crtc, fb, |
|---|
| .. | .. |
|---|
| 755 | 792 | crtc_x, crtc_y, crtc_w, crtc_h, |
|---|
| 756 | 793 | src_x, src_y, src_w, src_h, &ctx); |
|---|
| 757 | 794 | |
|---|
| 758 | | -fail: |
|---|
| 759 | | - if (ret == -EDEADLK) { |
|---|
| 760 | | - ret = drm_modeset_backoff(&ctx); |
|---|
| 761 | | - if (!ret) |
|---|
| 762 | | - goto retry; |
|---|
| 763 | | - } |
|---|
| 764 | | - drm_modeset_drop_locks(&ctx); |
|---|
| 765 | | - drm_modeset_acquire_fini(&ctx); |
|---|
| 795 | + DRM_MODESET_LOCK_ALL_END(plane->dev, ctx, ret); |
|---|
| 766 | 796 | |
|---|
| 767 | 797 | return ret; |
|---|
| 768 | 798 | } |
|---|
| .. | .. |
|---|
| 777 | 807 | int ret; |
|---|
| 778 | 808 | |
|---|
| 779 | 809 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
|---|
| 780 | | - return -EINVAL; |
|---|
| 810 | + return -EOPNOTSUPP; |
|---|
| 781 | 811 | |
|---|
| 782 | 812 | /* |
|---|
| 783 | 813 | * First, find the plane, crtc, and fb objects. If not available, |
|---|
| .. | .. |
|---|
| 915 | 945 | int ret = 0; |
|---|
| 916 | 946 | |
|---|
| 917 | 947 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
|---|
| 918 | | - return -EINVAL; |
|---|
| 948 | + return -EOPNOTSUPP; |
|---|
| 919 | 949 | |
|---|
| 920 | 950 | if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags)) |
|---|
| 921 | 951 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 1024 | 1054 | int ret = -EINVAL; |
|---|
| 1025 | 1055 | |
|---|
| 1026 | 1056 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
|---|
| 1027 | | - return -EINVAL; |
|---|
| 1057 | + return -EOPNOTSUPP; |
|---|
| 1028 | 1058 | |
|---|
| 1029 | 1059 | if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS) |
|---|
| 1030 | 1060 | return -EINVAL; |
|---|