942 lines · c
1/*2 * Copyright (c) 2006-2008 Intel Corporation3 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>4 * Copyright (c) 2008 Red Hat Inc.5 *6 * DRM core CRTC related functions7 *8 * Permission to use, copy, modify, distribute, and sell this software and its9 * documentation for any purpose is hereby granted without fee, provided that10 * the above copyright notice appear in all copies and that both that copyright11 * notice and this permission notice appear in supporting documentation, and12 * that the name of the copyright holders not be used in advertising or13 * publicity pertaining to distribution of the software without specific,14 * written prior permission. The copyright holders make no representations15 * about the suitability of this software for any purpose. It is provided "as16 * is" without express or implied warranty.17 *18 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,19 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO20 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,22 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER23 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE24 * OF THIS SOFTWARE.25 *26 * Authors:27 * Keith Packard28 * Eric Anholt <eric@anholt.net>29 * Dave Airlie <airlied@linux.ie>30 * Jesse Barnes <jesse.barnes@intel.com>31 */32#include <linux/ctype.h>33#include <linux/list.h>34#include <linux/slab.h>35#include <linux/export.h>36#include <linux/dma-fence.h>37#include <linux/uaccess.h>38#include <drm/drm_blend.h>39#include <drm/drm_crtc.h>40#include <drm/drm_edid.h>41#include <drm/drm_fourcc.h>42#include <drm/drm_framebuffer.h>43#include <drm/drm_managed.h>44#include <drm/drm_modeset_lock.h>45#include <drm/drm_atomic.h>46#include <drm/drm_auth.h>47#include <drm/drm_debugfs_crc.h>48#include <drm/drm_drv.h>49#include <drm/drm_print.h>50#include <drm/drm_file.h>51 52#include "drm_crtc_internal.h"53#include "drm_internal.h"54 55/**56 * DOC: overview57 *58 * A CRTC represents the overall display pipeline. It receives pixel data from59 * &drm_plane and blends them together. The &drm_display_mode is also attached60 * to the CRTC, specifying display timings. On the output side the data is fed61 * to one or more &drm_encoder, which are then each connected to one62 * &drm_connector.63 *64 * To create a CRTC, a KMS driver allocates and zeroes an instance of65 * &struct drm_crtc (possibly as part of a larger structure) and registers it66 * with a call to drm_crtc_init_with_planes().67 *68 * The CRTC is also the entry point for legacy modeset operations (see69 * &drm_crtc_funcs.set_config), legacy plane operations (see70 * &drm_crtc_funcs.page_flip and &drm_crtc_funcs.cursor_set2), and other legacy71 * operations like &drm_crtc_funcs.gamma_set. For atomic drivers all these72 * features are controlled through &drm_property and73 * &drm_mode_config_funcs.atomic_check.74 */75 76/**77 * drm_crtc_from_index - find the registered CRTC at an index78 * @dev: DRM device79 * @idx: index of registered CRTC to find for80 *81 * Given a CRTC index, return the registered CRTC from DRM device's82 * list of CRTCs with matching index. This is the inverse of drm_crtc_index().83 * It's useful in the vblank callbacks (like &drm_driver.enable_vblank or84 * &drm_driver.disable_vblank), since that still deals with indices instead85 * of pointers to &struct drm_crtc."86 */87struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx)88{89 struct drm_crtc *crtc;90 91 drm_for_each_crtc(crtc, dev)92 if (idx == crtc->index)93 return crtc;94 95 return NULL;96}97EXPORT_SYMBOL(drm_crtc_from_index);98 99int drm_crtc_force_disable(struct drm_crtc *crtc)100{101 struct drm_mode_set set = {102 .crtc = crtc,103 };104 105 WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));106 107 return drm_mode_set_config_internal(&set);108}109 110int drm_crtc_register_all(struct drm_device *dev)111{112 struct drm_crtc *crtc;113 int ret = 0;114 115 drm_for_each_crtc(crtc, dev) {116 drm_debugfs_crtc_add(crtc);117 118 if (crtc->funcs->late_register)119 ret = crtc->funcs->late_register(crtc);120 if (ret)121 return ret;122 }123 124 return 0;125}126 127void drm_crtc_unregister_all(struct drm_device *dev)128{129 struct drm_crtc *crtc;130 131 drm_for_each_crtc(crtc, dev) {132 if (crtc->funcs->early_unregister)133 crtc->funcs->early_unregister(crtc);134 drm_debugfs_crtc_remove(crtc);135 }136}137 138static int drm_crtc_crc_init(struct drm_crtc *crtc)139{140#ifdef CONFIG_DEBUG_FS141 spin_lock_init(&crtc->crc.lock);142 init_waitqueue_head(&crtc->crc.wq);143 crtc->crc.source = kstrdup("auto", GFP_KERNEL);144 if (!crtc->crc.source)145 return -ENOMEM;146#endif147 return 0;148}149 150static void drm_crtc_crc_fini(struct drm_crtc *crtc)151{152#ifdef CONFIG_DEBUG_FS153 kfree(crtc->crc.source);154#endif155}156 157static const struct dma_fence_ops drm_crtc_fence_ops;158 159static struct drm_crtc *fence_to_crtc(struct dma_fence *fence)160{161 BUG_ON(fence->ops != &drm_crtc_fence_ops);162 return container_of(fence->lock, struct drm_crtc, fence_lock);163}164 165static const char *drm_crtc_fence_get_driver_name(struct dma_fence *fence)166{167 struct drm_crtc *crtc = fence_to_crtc(fence);168 169 return crtc->dev->driver->name;170}171 172static const char *drm_crtc_fence_get_timeline_name(struct dma_fence *fence)173{174 struct drm_crtc *crtc = fence_to_crtc(fence);175 176 return crtc->timeline_name;177}178 179static const struct dma_fence_ops drm_crtc_fence_ops = {180 .get_driver_name = drm_crtc_fence_get_driver_name,181 .get_timeline_name = drm_crtc_fence_get_timeline_name,182};183 184struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc)185{186 struct dma_fence *fence;187 188 fence = kzalloc(sizeof(*fence), GFP_KERNEL);189 if (!fence)190 return NULL;191 192 dma_fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock,193 crtc->fence_context, ++crtc->fence_seqno);194 195 return fence;196}197 198/**199 * DOC: standard CRTC properties200 *201 * DRM CRTCs have a few standardized properties:202 *203 * ACTIVE:204 * Atomic property for setting the power state of the CRTC. When set to 1205 * the CRTC will actively display content. When set to 0 the CRTC will be206 * powered off. There is no expectation that user-space will reset CRTC207 * resources like the mode and planes when setting ACTIVE to 0.208 *209 * User-space can rely on an ACTIVE change to 1 to never fail an atomic210 * test as long as no other property has changed. If a change to ACTIVE211 * fails an atomic test, this is a driver bug. For this reason setting212 * ACTIVE to 0 must not release internal resources (like reserved memory213 * bandwidth or clock generators).214 *215 * Note that the legacy DPMS property on connectors is internally routed216 * to control this property for atomic drivers.217 * MODE_ID:218 * Atomic property for setting the CRTC display timings. The value is the219 * ID of a blob containing the DRM mode info. To disable the CRTC,220 * user-space must set this property to 0.221 *222 * Setting MODE_ID to 0 will release reserved resources for the CRTC.223 * SCALING_FILTER:224 * Atomic property for setting the scaling filter for CRTC scaler225 *226 * The value of this property can be one of the following:227 *228 * Default:229 * Driver's default scaling filter230 * Nearest Neighbor:231 * Nearest Neighbor scaling filter232 */233 234__printf(6, 0)235static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,236 struct drm_plane *primary,237 struct drm_plane *cursor,238 const struct drm_crtc_funcs *funcs,239 const char *name, va_list ap)240{241 struct drm_mode_config *config = &dev->mode_config;242 int ret;243 244 WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY);245 WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR);246 247 /* crtc index is used with 32bit bitmasks */248 if (WARN_ON(config->num_crtc >= 32))249 return -EINVAL;250 251 WARN_ON(drm_drv_uses_atomic_modeset(dev) &&252 (!funcs->atomic_destroy_state ||253 !funcs->atomic_duplicate_state));254 255 crtc->dev = dev;256 crtc->funcs = funcs;257 258 INIT_LIST_HEAD(&crtc->commit_list);259 spin_lock_init(&crtc->commit_lock);260 261 drm_modeset_lock_init(&crtc->mutex);262 ret = drm_mode_object_add(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);263 if (ret)264 return ret;265 266 if (name) {267 crtc->name = kvasprintf(GFP_KERNEL, name, ap);268 } else {269 crtc->name = kasprintf(GFP_KERNEL, "crtc-%d", config->num_crtc);270 }271 if (!crtc->name) {272 drm_mode_object_unregister(dev, &crtc->base);273 return -ENOMEM;274 }275 276 crtc->fence_context = dma_fence_context_alloc(1);277 spin_lock_init(&crtc->fence_lock);278 snprintf(crtc->timeline_name, sizeof(crtc->timeline_name),279 "CRTC:%d-%s", crtc->base.id, crtc->name);280 281 crtc->base.properties = &crtc->properties;282 283 list_add_tail(&crtc->head, &config->crtc_list);284 crtc->index = config->num_crtc++;285 286 crtc->primary = primary;287 crtc->cursor = cursor;288 if (primary && !primary->possible_crtcs)289 primary->possible_crtcs = drm_crtc_mask(crtc);290 if (cursor && !cursor->possible_crtcs)291 cursor->possible_crtcs = drm_crtc_mask(crtc);292 293 ret = drm_crtc_crc_init(crtc);294 if (ret) {295 drm_mode_object_unregister(dev, &crtc->base);296 return ret;297 }298 299 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {300 drm_object_attach_property(&crtc->base, config->prop_active, 0);301 drm_object_attach_property(&crtc->base, config->prop_mode_id, 0);302 drm_object_attach_property(&crtc->base,303 config->prop_out_fence_ptr, 0);304 drm_object_attach_property(&crtc->base,305 config->prop_vrr_enabled, 0);306 }307 308 return 0;309}310 311/**312 * drm_crtc_init_with_planes - Initialise a new CRTC object with313 * specified primary and cursor planes.314 * @dev: DRM device315 * @crtc: CRTC object to init316 * @primary: Primary plane for CRTC317 * @cursor: Cursor plane for CRTC318 * @funcs: callbacks for the new CRTC319 * @name: printf style format string for the CRTC name, or NULL for default name320 *321 * Inits a new object created as base part of a driver crtc object. Drivers322 * should use this function instead of drm_crtc_init(), which is only provided323 * for backwards compatibility with drivers which do not yet support universal324 * planes). For really simple hardware which has only 1 plane look at325 * drm_simple_display_pipe_init() instead.326 * The &drm_crtc_funcs.destroy hook should call drm_crtc_cleanup() and kfree()327 * the crtc structure. The crtc structure should not be allocated with328 * devm_kzalloc().329 *330 * The @primary and @cursor planes are only relevant for legacy uAPI, see331 * &drm_crtc.primary and &drm_crtc.cursor.332 *333 * Note: consider using drmm_crtc_alloc_with_planes() or334 * drmm_crtc_init_with_planes() instead of drm_crtc_init_with_planes()335 * to let the DRM managed resource infrastructure take care of cleanup336 * and deallocation.337 *338 * Returns:339 * Zero on success, error code on failure.340 */341int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,342 struct drm_plane *primary,343 struct drm_plane *cursor,344 const struct drm_crtc_funcs *funcs,345 const char *name, ...)346{347 va_list ap;348 int ret;349 350 WARN_ON(!funcs->destroy);351 352 va_start(ap, name);353 ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,354 name, ap);355 va_end(ap);356 357 return ret;358}359EXPORT_SYMBOL(drm_crtc_init_with_planes);360 361static void drmm_crtc_init_with_planes_cleanup(struct drm_device *dev,362 void *ptr)363{364 struct drm_crtc *crtc = ptr;365 366 drm_crtc_cleanup(crtc);367}368 369__printf(6, 0)370static int __drmm_crtc_init_with_planes(struct drm_device *dev,371 struct drm_crtc *crtc,372 struct drm_plane *primary,373 struct drm_plane *cursor,374 const struct drm_crtc_funcs *funcs,375 const char *name,376 va_list args)377{378 int ret;379 380 drm_WARN_ON(dev, funcs && funcs->destroy);381 382 ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,383 name, args);384 if (ret)385 return ret;386 387 ret = drmm_add_action_or_reset(dev, drmm_crtc_init_with_planes_cleanup,388 crtc);389 if (ret)390 return ret;391 392 return 0;393}394 395/**396 * drmm_crtc_init_with_planes - Initialise a new CRTC object with397 * specified primary and cursor planes.398 * @dev: DRM device399 * @crtc: CRTC object to init400 * @primary: Primary plane for CRTC401 * @cursor: Cursor plane for CRTC402 * @funcs: callbacks for the new CRTC403 * @name: printf style format string for the CRTC name, or NULL for default name404 *405 * Inits a new object created as base part of a driver crtc object. Drivers406 * should use this function instead of drm_crtc_init(), which is only provided407 * for backwards compatibility with drivers which do not yet support universal408 * planes). For really simple hardware which has only 1 plane look at409 * drm_simple_display_pipe_init() instead.410 *411 * Cleanup is automatically handled through registering412 * drmm_crtc_cleanup() with drmm_add_action(). The crtc structure should413 * be allocated with drmm_kzalloc().414 *415 * The @drm_crtc_funcs.destroy hook must be NULL.416 *417 * The @primary and @cursor planes are only relevant for legacy uAPI, see418 * &drm_crtc.primary and &drm_crtc.cursor.419 *420 * Returns:421 * Zero on success, error code on failure.422 */423int drmm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,424 struct drm_plane *primary,425 struct drm_plane *cursor,426 const struct drm_crtc_funcs *funcs,427 const char *name, ...)428{429 va_list ap;430 int ret;431 432 va_start(ap, name);433 ret = __drmm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,434 name, ap);435 va_end(ap);436 if (ret)437 return ret;438 439 return 0;440}441EXPORT_SYMBOL(drmm_crtc_init_with_planes);442 443void *__drmm_crtc_alloc_with_planes(struct drm_device *dev,444 size_t size, size_t offset,445 struct drm_plane *primary,446 struct drm_plane *cursor,447 const struct drm_crtc_funcs *funcs,448 const char *name, ...)449{450 void *container;451 struct drm_crtc *crtc;452 va_list ap;453 int ret;454 455 if (WARN_ON(!funcs || funcs->destroy))456 return ERR_PTR(-EINVAL);457 458 container = drmm_kzalloc(dev, size, GFP_KERNEL);459 if (!container)460 return ERR_PTR(-ENOMEM);461 462 crtc = container + offset;463 464 va_start(ap, name);465 ret = __drmm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,466 name, ap);467 va_end(ap);468 if (ret)469 return ERR_PTR(ret);470 471 return container;472}473EXPORT_SYMBOL(__drmm_crtc_alloc_with_planes);474 475/**476 * drm_crtc_cleanup - Clean up the core crtc usage477 * @crtc: CRTC to cleanup478 *479 * This function cleans up @crtc and removes it from the DRM mode setting480 * core. Note that the function does *not* free the crtc structure itself,481 * this is the responsibility of the caller.482 */483void drm_crtc_cleanup(struct drm_crtc *crtc)484{485 struct drm_device *dev = crtc->dev;486 487 /* Note that the crtc_list is considered to be static; should we488 * remove the drm_crtc at runtime we would have to decrement all489 * the indices on the drm_crtc after us in the crtc_list.490 */491 492 drm_crtc_crc_fini(crtc);493 494 kfree(crtc->gamma_store);495 crtc->gamma_store = NULL;496 497 drm_modeset_lock_fini(&crtc->mutex);498 499 drm_mode_object_unregister(dev, &crtc->base);500 list_del(&crtc->head);501 dev->mode_config.num_crtc--;502 503 WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state);504 if (crtc->state && crtc->funcs->atomic_destroy_state)505 crtc->funcs->atomic_destroy_state(crtc, crtc->state);506 507 kfree(crtc->name);508 509 memset(crtc, 0, sizeof(*crtc));510}511EXPORT_SYMBOL(drm_crtc_cleanup);512 513/**514 * drm_mode_getcrtc - get CRTC configuration515 * @dev: drm device for the ioctl516 * @data: data pointer for the ioctl517 * @file_priv: drm file for the ioctl call518 *519 * Construct a CRTC configuration structure to return to the user.520 *521 * Called by the user via ioctl.522 *523 * Returns:524 * Zero on success, negative errno on failure.525 */526int drm_mode_getcrtc(struct drm_device *dev,527 void *data, struct drm_file *file_priv)528{529 struct drm_mode_crtc *crtc_resp = data;530 struct drm_crtc *crtc;531 struct drm_plane *plane;532 533 if (!drm_core_check_feature(dev, DRIVER_MODESET))534 return -EOPNOTSUPP;535 536 crtc = drm_crtc_find(dev, file_priv, crtc_resp->crtc_id);537 if (!crtc)538 return -ENOENT;539 540 plane = crtc->primary;541 542 crtc_resp->gamma_size = crtc->gamma_size;543 544 drm_modeset_lock(&plane->mutex, NULL);545 if (plane->state && plane->state->fb)546 crtc_resp->fb_id = plane->state->fb->base.id;547 else if (!plane->state && plane->fb)548 crtc_resp->fb_id = plane->fb->base.id;549 else550 crtc_resp->fb_id = 0;551 552 if (plane->state) {553 crtc_resp->x = plane->state->src_x >> 16;554 crtc_resp->y = plane->state->src_y >> 16;555 }556 drm_modeset_unlock(&plane->mutex);557 558 drm_modeset_lock(&crtc->mutex, NULL);559 if (crtc->state) {560 if (crtc->state->enable) {561 drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);562 crtc_resp->mode_valid = 1;563 } else {564 crtc_resp->mode_valid = 0;565 }566 } else {567 crtc_resp->x = crtc->x;568 crtc_resp->y = crtc->y;569 570 if (crtc->enabled) {571 drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode);572 crtc_resp->mode_valid = 1;573 574 } else {575 crtc_resp->mode_valid = 0;576 }577 }578 if (!file_priv->aspect_ratio_allowed)579 crtc_resp->mode.flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;580 drm_modeset_unlock(&crtc->mutex);581 582 return 0;583}584 585static int __drm_mode_set_config_internal(struct drm_mode_set *set,586 struct drm_modeset_acquire_ctx *ctx)587{588 struct drm_crtc *crtc = set->crtc;589 struct drm_framebuffer *fb;590 struct drm_crtc *tmp;591 int ret;592 593 WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));594 595 /*596 * NOTE: ->set_config can also disable other crtcs (if we steal all597 * connectors from it), hence we need to refcount the fbs across all598 * crtcs. Atomic modeset will have saner semantics ...599 */600 drm_for_each_crtc(tmp, crtc->dev) {601 struct drm_plane *plane = tmp->primary;602 603 plane->old_fb = plane->fb;604 }605 606 fb = set->fb;607 608 ret = crtc->funcs->set_config(set, ctx);609 if (ret == 0) {610 struct drm_plane *plane = crtc->primary;611 612 plane->crtc = fb ? crtc : NULL;613 plane->fb = fb;614 }615 616 drm_for_each_crtc(tmp, crtc->dev) {617 struct drm_plane *plane = tmp->primary;618 619 if (plane->fb)620 drm_framebuffer_get(plane->fb);621 if (plane->old_fb)622 drm_framebuffer_put(plane->old_fb);623 plane->old_fb = NULL;624 }625 626 return ret;627}628 629/**630 * drm_mode_set_config_internal - helper to call &drm_mode_config_funcs.set_config631 * @set: modeset config to set632 *633 * This is a little helper to wrap internal calls to the634 * &drm_mode_config_funcs.set_config driver interface. The only thing it adds is635 * correct refcounting dance.636 *637 * This should only be used by non-atomic legacy drivers.638 *639 * Returns:640 * Zero on success, negative errno on failure.641 */642int drm_mode_set_config_internal(struct drm_mode_set *set)643{644 WARN_ON(drm_drv_uses_atomic_modeset(set->crtc->dev));645 646 return __drm_mode_set_config_internal(set, NULL);647}648EXPORT_SYMBOL(drm_mode_set_config_internal);649 650/**651 * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the652 * CRTC viewport653 * @crtc: CRTC that framebuffer will be displayed on654 * @x: x panning655 * @y: y panning656 * @mode: mode that framebuffer will be displayed under657 * @fb: framebuffer to check size of658 */659int drm_crtc_check_viewport(const struct drm_crtc *crtc,660 int x, int y,661 const struct drm_display_mode *mode,662 const struct drm_framebuffer *fb)663 664{665 int hdisplay, vdisplay;666 667 drm_mode_get_hv_timing(mode, &hdisplay, &vdisplay);668 669 if (crtc->state &&670 drm_rotation_90_or_270(crtc->primary->state->rotation))671 swap(hdisplay, vdisplay);672 673 return drm_framebuffer_check_src_coords(x << 16, y << 16,674 hdisplay << 16, vdisplay << 16,675 fb);676}677EXPORT_SYMBOL(drm_crtc_check_viewport);678 679/**680 * drm_mode_setcrtc - set CRTC configuration681 * @dev: drm device for the ioctl682 * @data: data pointer for the ioctl683 * @file_priv: drm file for the ioctl call684 *685 * Build a new CRTC configuration based on user request.686 *687 * Called by the user via ioctl.688 *689 * Returns:690 * Zero on success, negative errno on failure.691 */692int drm_mode_setcrtc(struct drm_device *dev, void *data,693 struct drm_file *file_priv)694{695 struct drm_mode_config *config = &dev->mode_config;696 struct drm_mode_crtc *crtc_req = data;697 struct drm_crtc *crtc;698 struct drm_plane *plane;699 struct drm_connector **connector_set = NULL, *connector;700 struct drm_framebuffer *fb = NULL;701 struct drm_display_mode *mode = NULL;702 struct drm_mode_set set;703 uint32_t __user *set_connectors_ptr;704 struct drm_modeset_acquire_ctx ctx;705 int ret, i, num_connectors = 0;706 707 if (!drm_core_check_feature(dev, DRIVER_MODESET))708 return -EOPNOTSUPP;709 710 /*711 * Universal plane src offsets are only 16.16, prevent havoc for712 * drivers using universal plane code internally.713 */714 if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)715 return -ERANGE;716 717 crtc = drm_crtc_find(dev, file_priv, crtc_req->crtc_id);718 if (!crtc) {719 drm_dbg_kms(dev, "Unknown CRTC ID %d\n", crtc_req->crtc_id);720 return -ENOENT;721 }722 drm_dbg_kms(dev, "[CRTC:%d:%s]\n", crtc->base.id, crtc->name);723 724 plane = crtc->primary;725 726 /* allow disabling with the primary plane leased */727 if (crtc_req->mode_valid && !drm_lease_held(file_priv, plane->base.id))728 return -EACCES;729 730 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx,731 DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);732 733 if (crtc_req->mode_valid) {734 /* If we have a mode we need a framebuffer. */735 /* If we pass -1, set the mode with the currently bound fb */736 if (crtc_req->fb_id == -1) {737 struct drm_framebuffer *old_fb;738 739 if (plane->state)740 old_fb = plane->state->fb;741 else742 old_fb = plane->fb;743 744 if (!old_fb) {745 drm_dbg_kms(dev, "CRTC doesn't have current FB\n");746 ret = -EINVAL;747 goto out;748 }749 750 fb = old_fb;751 /* Make refcounting symmetric with the lookup path. */752 drm_framebuffer_get(fb);753 } else {754 fb = drm_framebuffer_lookup(dev, file_priv, crtc_req->fb_id);755 if (!fb) {756 drm_dbg_kms(dev, "Unknown FB ID%d\n",757 crtc_req->fb_id);758 ret = -ENOENT;759 goto out;760 }761 }762 763 mode = drm_mode_create(dev);764 if (!mode) {765 ret = -ENOMEM;766 goto out;767 }768 if (!file_priv->aspect_ratio_allowed &&769 (crtc_req->mode.flags & DRM_MODE_FLAG_PIC_AR_MASK) != DRM_MODE_FLAG_PIC_AR_NONE) {770 drm_dbg_kms(dev, "Unexpected aspect-ratio flag bits\n");771 ret = -EINVAL;772 goto out;773 }774 775 776 ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode);777 if (ret) {778 drm_dbg_kms(dev, "Invalid mode (%s, %pe): " DRM_MODE_FMT "\n",779 drm_get_mode_status_name(mode->status),780 ERR_PTR(ret), DRM_MODE_ARG(mode));781 goto out;782 }783 784 /*785 * Check whether the primary plane supports the fb pixel format.786 * Drivers not implementing the universal planes API use a787 * default formats list provided by the DRM core which doesn't788 * match real hardware capabilities. Skip the check in that789 * case.790 */791 if (!plane->format_default) {792 if (!drm_plane_has_format(plane, fb->format->format, fb->modifier)) {793 drm_dbg_kms(dev, "Invalid pixel format %p4cc, modifier 0x%llx\n",794 &fb->format->format, fb->modifier);795 ret = -EINVAL;796 goto out;797 }798 }799 800 ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,801 mode, fb);802 if (ret)803 goto out;804 805 }806 807 if (crtc_req->count_connectors == 0 && mode) {808 drm_dbg_kms(dev, "Count connectors is 0 but mode set\n");809 ret = -EINVAL;810 goto out;811 }812 813 if (crtc_req->count_connectors > 0 && (!mode || !fb)) {814 drm_dbg_kms(dev, "Count connectors is %d but no mode or fb set\n",815 crtc_req->count_connectors);816 ret = -EINVAL;817 goto out;818 }819 820 if (crtc_req->count_connectors > 0) {821 u32 out_id;822 823 /* Avoid unbounded kernel memory allocation */824 if (crtc_req->count_connectors > config->num_connector) {825 ret = -EINVAL;826 goto out;827 }828 829 connector_set = kmalloc_array(crtc_req->count_connectors,830 sizeof(struct drm_connector *),831 GFP_KERNEL);832 if (!connector_set) {833 ret = -ENOMEM;834 goto out;835 }836 837 for (i = 0; i < crtc_req->count_connectors; i++) {838 connector_set[i] = NULL;839 set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;840 if (get_user(out_id, &set_connectors_ptr[i])) {841 ret = -EFAULT;842 goto out;843 }844 845 connector = drm_connector_lookup(dev, file_priv, out_id);846 if (!connector) {847 drm_dbg_kms(dev, "Connector id %d unknown\n",848 out_id);849 ret = -ENOENT;850 goto out;851 }852 drm_dbg_kms(dev, "[CONNECTOR:%d:%s]\n",853 connector->base.id, connector->name);854 855 connector_set[i] = connector;856 num_connectors++;857 }858 }859 860 set.crtc = crtc;861 set.x = crtc_req->x;862 set.y = crtc_req->y;863 set.mode = mode;864 set.connectors = connector_set;865 set.num_connectors = num_connectors;866 set.fb = fb;867 868 if (drm_drv_uses_atomic_modeset(dev))869 ret = crtc->funcs->set_config(&set, &ctx);870 else871 ret = __drm_mode_set_config_internal(&set, &ctx);872 873out:874 if (fb)875 drm_framebuffer_put(fb);876 877 if (connector_set) {878 for (i = 0; i < num_connectors; i++) {879 if (connector_set[i])880 drm_connector_put(connector_set[i]);881 }882 }883 kfree(connector_set);884 drm_mode_destroy(dev, mode);885 886 /* In case we need to retry... */887 connector_set = NULL;888 fb = NULL;889 mode = NULL;890 num_connectors = 0;891 892 DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);893 894 return ret;895}896 897int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,898 struct drm_property *property,899 uint64_t value)900{901 int ret = -EINVAL;902 struct drm_crtc *crtc = obj_to_crtc(obj);903 904 if (crtc->funcs->set_property)905 ret = crtc->funcs->set_property(crtc, property, value);906 if (!ret)907 drm_object_property_set_value(obj, property, value);908 909 return ret;910}911 912/**913 * drm_crtc_create_scaling_filter_property - create a new scaling filter914 * property915 *916 * @crtc: drm CRTC917 * @supported_filters: bitmask of supported scaling filters, must include918 * BIT(DRM_SCALING_FILTER_DEFAULT).919 *920 * This function lets driver to enable the scaling filter property on a given921 * CRTC.922 *923 * RETURNS:924 * Zero for success or -errno925 */926int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc,927 unsigned int supported_filters)928{929 struct drm_property *prop =930 drm_create_scaling_filter_prop(crtc->dev, supported_filters);931 932 if (IS_ERR(prop))933 return PTR_ERR(prop);934 935 drm_object_attach_property(&crtc->base, prop,936 DRM_SCALING_FILTER_DEFAULT);937 crtc->scaling_filter_property = prop;938 939 return 0;940}941EXPORT_SYMBOL(drm_crtc_create_scaling_filter_property);942