| .. | .. |
|---|
| 34 | 34 | #include <linux/slab.h> |
|---|
| 35 | 35 | #include <linux/export.h> |
|---|
| 36 | 36 | #include <linux/dma-fence.h> |
|---|
| 37 | | -#include <drm/drmP.h> |
|---|
| 37 | +#include <linux/uaccess.h> |
|---|
| 38 | 38 | #include <drm/drm_crtc.h> |
|---|
| 39 | 39 | #include <drm/drm_edid.h> |
|---|
| 40 | 40 | #include <drm/drm_fourcc.h> |
|---|
| .. | .. |
|---|
| 42 | 42 | #include <drm/drm_atomic.h> |
|---|
| 43 | 43 | #include <drm/drm_auth.h> |
|---|
| 44 | 44 | #include <drm/drm_debugfs_crc.h> |
|---|
| 45 | +#include <drm/drm_drv.h> |
|---|
| 46 | +#include <drm/drm_print.h> |
|---|
| 47 | +#include <drm/drm_file.h> |
|---|
| 45 | 48 | |
|---|
| 46 | 49 | #include "drm_crtc_internal.h" |
|---|
| 47 | 50 | #include "drm_internal.h" |
|---|
| .. | .. |
|---|
| 90 | 93 | } |
|---|
| 91 | 94 | EXPORT_SYMBOL(drm_crtc_from_index); |
|---|
| 92 | 95 | |
|---|
| 93 | | -/** |
|---|
| 94 | | - * drm_crtc_force_disable - Forcibly turn off a CRTC |
|---|
| 95 | | - * @crtc: CRTC to turn off |
|---|
| 96 | | - * |
|---|
| 97 | | - * Note: This should only be used by non-atomic legacy drivers. |
|---|
| 98 | | - * |
|---|
| 99 | | - * Returns: |
|---|
| 100 | | - * Zero on success, error code on failure. |
|---|
| 101 | | - */ |
|---|
| 102 | 96 | int drm_crtc_force_disable(struct drm_crtc *crtc) |
|---|
| 103 | 97 | { |
|---|
| 104 | 98 | struct drm_mode_set set = { |
|---|
| .. | .. |
|---|
| 109 | 103 | |
|---|
| 110 | 104 | return drm_mode_set_config_internal(&set); |
|---|
| 111 | 105 | } |
|---|
| 112 | | -EXPORT_SYMBOL(drm_crtc_force_disable); |
|---|
| 113 | | - |
|---|
| 114 | | -/** |
|---|
| 115 | | - * drm_crtc_force_disable_all - Forcibly turn off all enabled CRTCs |
|---|
| 116 | | - * @dev: DRM device whose CRTCs to turn off |
|---|
| 117 | | - * |
|---|
| 118 | | - * Drivers may want to call this on unload to ensure that all displays are |
|---|
| 119 | | - * unlit and the GPU is in a consistent, low power state. Takes modeset locks. |
|---|
| 120 | | - * |
|---|
| 121 | | - * Note: This should only be used by non-atomic legacy drivers. For an atomic |
|---|
| 122 | | - * version look at drm_atomic_helper_shutdown(). |
|---|
| 123 | | - * |
|---|
| 124 | | - * Returns: |
|---|
| 125 | | - * Zero on success, error code on failure. |
|---|
| 126 | | - */ |
|---|
| 127 | | -int drm_crtc_force_disable_all(struct drm_device *dev) |
|---|
| 128 | | -{ |
|---|
| 129 | | - struct drm_crtc *crtc; |
|---|
| 130 | | - int ret = 0; |
|---|
| 131 | | - |
|---|
| 132 | | - drm_modeset_lock_all(dev); |
|---|
| 133 | | - drm_for_each_crtc(crtc, dev) |
|---|
| 134 | | - if (crtc->enabled) { |
|---|
| 135 | | - ret = drm_crtc_force_disable(crtc); |
|---|
| 136 | | - if (ret) |
|---|
| 137 | | - goto out; |
|---|
| 138 | | - } |
|---|
| 139 | | -out: |
|---|
| 140 | | - drm_modeset_unlock_all(dev); |
|---|
| 141 | | - return ret; |
|---|
| 142 | | -} |
|---|
| 143 | | -EXPORT_SYMBOL(drm_crtc_force_disable_all); |
|---|
| 144 | 106 | |
|---|
| 145 | 107 | static unsigned int drm_num_crtcs(struct drm_device *dev) |
|---|
| 146 | 108 | { |
|---|
| .. | .. |
|---|
| 160 | 122 | int ret = 0; |
|---|
| 161 | 123 | |
|---|
| 162 | 124 | drm_for_each_crtc(crtc, dev) { |
|---|
| 163 | | - if (drm_debugfs_crtc_add(crtc)) |
|---|
| 164 | | - DRM_ERROR("Failed to initialize debugfs entry for CRTC '%s'.\n", |
|---|
| 165 | | - crtc->name); |
|---|
| 125 | + drm_debugfs_crtc_add(crtc); |
|---|
| 166 | 126 | |
|---|
| 167 | 127 | if (crtc->funcs->late_register) |
|---|
| 168 | 128 | ret = crtc->funcs->late_register(crtc); |
|---|
| .. | .. |
|---|
| 243 | 203 | |
|---|
| 244 | 204 | return fence; |
|---|
| 245 | 205 | } |
|---|
| 206 | + |
|---|
| 207 | +/** |
|---|
| 208 | + * DOC: standard CRTC properties |
|---|
| 209 | + * |
|---|
| 210 | + * DRM CRTCs have a few standardized properties: |
|---|
| 211 | + * |
|---|
| 212 | + * ACTIVE: |
|---|
| 213 | + * Atomic property for setting the power state of the CRTC. When set to 1 |
|---|
| 214 | + * the CRTC will actively display content. When set to 0 the CRTC will be |
|---|
| 215 | + * powered off. There is no expectation that user-space will reset CRTC |
|---|
| 216 | + * resources like the mode and planes when setting ACTIVE to 0. |
|---|
| 217 | + * |
|---|
| 218 | + * User-space can rely on an ACTIVE change to 1 to never fail an atomic |
|---|
| 219 | + * test as long as no other property has changed. If a change to ACTIVE |
|---|
| 220 | + * fails an atomic test, this is a driver bug. For this reason setting |
|---|
| 221 | + * ACTIVE to 0 must not release internal resources (like reserved memory |
|---|
| 222 | + * bandwidth or clock generators). |
|---|
| 223 | + * |
|---|
| 224 | + * Note that the legacy DPMS property on connectors is internally routed |
|---|
| 225 | + * to control this property for atomic drivers. |
|---|
| 226 | + * MODE_ID: |
|---|
| 227 | + * Atomic property for setting the CRTC display timings. The value is the |
|---|
| 228 | + * ID of a blob containing the DRM mode info. To disable the CRTC, |
|---|
| 229 | + * user-space must set this property to 0. |
|---|
| 230 | + * |
|---|
| 231 | + * Setting MODE_ID to 0 will release reserved resources for the CRTC. |
|---|
| 232 | + */ |
|---|
| 246 | 233 | |
|---|
| 247 | 234 | /** |
|---|
| 248 | 235 | * drm_crtc_init_with_planes - Initialise a new CRTC object with |
|---|
| .. | .. |
|---|
| 337 | 324 | drm_object_attach_property(&crtc->base, config->prop_mode_id, 0); |
|---|
| 338 | 325 | drm_object_attach_property(&crtc->base, |
|---|
| 339 | 326 | config->prop_out_fence_ptr, 0); |
|---|
| 327 | + drm_object_attach_property(&crtc->base, |
|---|
| 328 | + config->prop_vrr_enabled, 0); |
|---|
| 340 | 329 | } |
|---|
| 341 | 330 | |
|---|
| 342 | 331 | return 0; |
|---|
| .. | .. |
|---|
| 402 | 391 | struct drm_plane *plane; |
|---|
| 403 | 392 | |
|---|
| 404 | 393 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
|---|
| 405 | | - return -EINVAL; |
|---|
| 394 | + return -EOPNOTSUPP; |
|---|
| 406 | 395 | |
|---|
| 407 | 396 | crtc = drm_crtc_find(dev, file_priv, crtc_resp->crtc_id); |
|---|
| 408 | 397 | if (!crtc) |
|---|
| .. | .. |
|---|
| 567 | 556 | struct drm_mode_crtc *crtc_req = data; |
|---|
| 568 | 557 | struct drm_crtc *crtc; |
|---|
| 569 | 558 | struct drm_plane *plane; |
|---|
| 570 | | - struct drm_connector **connector_set, *connector; |
|---|
| 571 | | - struct drm_framebuffer *fb; |
|---|
| 572 | | - struct drm_display_mode *mode; |
|---|
| 559 | + struct drm_connector **connector_set = NULL, *connector; |
|---|
| 560 | + struct drm_framebuffer *fb = NULL; |
|---|
| 561 | + struct drm_display_mode *mode = NULL; |
|---|
| 573 | 562 | struct drm_mode_set set; |
|---|
| 574 | 563 | uint32_t __user *set_connectors_ptr; |
|---|
| 575 | 564 | struct drm_modeset_acquire_ctx ctx; |
|---|
| .. | .. |
|---|
| 577 | 566 | int i; |
|---|
| 578 | 567 | |
|---|
| 579 | 568 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
|---|
| 580 | | - return -EINVAL; |
|---|
| 569 | + return -EOPNOTSUPP; |
|---|
| 581 | 570 | |
|---|
| 582 | 571 | /* |
|---|
| 583 | 572 | * Universal plane src offsets are only 16.16, prevent havoc for |
|---|
| .. | .. |
|---|
| 599 | 588 | if (crtc_req->mode_valid && !drm_lease_held(file_priv, plane->base.id)) |
|---|
| 600 | 589 | return -EACCES; |
|---|
| 601 | 590 | |
|---|
| 602 | | - mutex_lock(&crtc->dev->mode_config.mutex); |
|---|
| 603 | | - drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); |
|---|
| 604 | | -retry: |
|---|
| 605 | | - connector_set = NULL; |
|---|
| 606 | | - fb = NULL; |
|---|
| 607 | | - mode = NULL; |
|---|
| 608 | | - |
|---|
| 609 | | - ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx); |
|---|
| 610 | | - if (ret) |
|---|
| 611 | | - goto out; |
|---|
| 591 | + DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, |
|---|
| 592 | + DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret); |
|---|
| 612 | 593 | |
|---|
| 613 | 594 | if (crtc_req->mode_valid) { |
|---|
| 614 | 595 | /* If we have a mode we need a framebuffer. */ |
|---|
| .. | .. |
|---|
| 674 | 655 | fb->modifier); |
|---|
| 675 | 656 | if (ret) { |
|---|
| 676 | 657 | struct drm_format_name_buf format_name; |
|---|
| 658 | + |
|---|
| 677 | 659 | DRM_DEBUG_KMS("Invalid pixel format %s, modifier 0x%llx\n", |
|---|
| 678 | 660 | drm_get_format_name(fb->format->format, |
|---|
| 679 | 661 | &format_name), |
|---|
| .. | .. |
|---|
| 767 | 749 | } |
|---|
| 768 | 750 | kfree(connector_set); |
|---|
| 769 | 751 | drm_mode_destroy(dev, mode); |
|---|
| 770 | | - if (ret == -EDEADLK) { |
|---|
| 771 | | - ret = drm_modeset_backoff(&ctx); |
|---|
| 772 | | - if (!ret) |
|---|
| 773 | | - goto retry; |
|---|
| 774 | | - } |
|---|
| 775 | | - drm_modeset_drop_locks(&ctx); |
|---|
| 776 | | - drm_modeset_acquire_fini(&ctx); |
|---|
| 777 | | - mutex_unlock(&crtc->dev->mode_config.mutex); |
|---|
| 752 | + |
|---|
| 753 | + /* In case we need to retry... */ |
|---|
| 754 | + connector_set = NULL; |
|---|
| 755 | + fb = NULL; |
|---|
| 756 | + mode = NULL; |
|---|
| 757 | + |
|---|
| 758 | + DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); |
|---|
| 778 | 759 | |
|---|
| 779 | 760 | return ret; |
|---|
| 780 | 761 | } |
|---|