| .. | .. | 
|---|
| 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; | 
|---|