Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2006-2008 Intel Corporation
0003  * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
0004  * Copyright (c) 2008 Red Hat Inc.
0005  *
0006  * DRM core CRTC related functions
0007  *
0008  * Permission to use, copy, modify, distribute, and sell this software and its
0009  * documentation for any purpose is hereby granted without fee, provided that
0010  * the above copyright notice appear in all copies and that both that copyright
0011  * notice and this permission notice appear in supporting documentation, and
0012  * that the name of the copyright holders not be used in advertising or
0013  * publicity pertaining to distribution of the software without specific,
0014  * written prior permission.  The copyright holders make no representations
0015  * about the suitability of this software for any purpose.  It is provided "as
0016  * is" without express or implied warranty.
0017  *
0018  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
0019  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
0020  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
0021  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
0022  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
0023  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
0024  * OF THIS SOFTWARE.
0025  *
0026  * Authors:
0027  *      Keith Packard
0028  *  Eric Anholt <eric@anholt.net>
0029  *      Dave Airlie <airlied@linux.ie>
0030  *      Jesse Barnes <jesse.barnes@intel.com>
0031  */
0032 #include <linux/ctype.h>
0033 #include <linux/list.h>
0034 #include <linux/slab.h>
0035 #include <linux/export.h>
0036 #include <linux/dma-fence.h>
0037 #include <linux/uaccess.h>
0038 #include <drm/drm_blend.h>
0039 #include <drm/drm_crtc.h>
0040 #include <drm/drm_edid.h>
0041 #include <drm/drm_fourcc.h>
0042 #include <drm/drm_framebuffer.h>
0043 #include <drm/drm_managed.h>
0044 #include <drm/drm_modeset_lock.h>
0045 #include <drm/drm_atomic.h>
0046 #include <drm/drm_auth.h>
0047 #include <drm/drm_debugfs_crc.h>
0048 #include <drm/drm_drv.h>
0049 #include <drm/drm_print.h>
0050 #include <drm/drm_file.h>
0051 
0052 #include "drm_crtc_internal.h"
0053 #include "drm_internal.h"
0054 
0055 /**
0056  * DOC: overview
0057  *
0058  * A CRTC represents the overall display pipeline. It receives pixel data from
0059  * &drm_plane and blends them together. The &drm_display_mode is also attached
0060  * to the CRTC, specifying display timings. On the output side the data is fed
0061  * to one or more &drm_encoder, which are then each connected to one
0062  * &drm_connector.
0063  *
0064  * To create a CRTC, a KMS drivers allocates and zeroes an instances of
0065  * &struct drm_crtc (possibly as part of a larger structure) and registers it
0066  * with a call to drm_crtc_init_with_planes().
0067  *
0068  * The CRTC is also the entry point for legacy modeset operations, see
0069  * &drm_crtc_funcs.set_config, legacy plane operations, see
0070  * &drm_crtc_funcs.page_flip and &drm_crtc_funcs.cursor_set2, and other legacy
0071  * operations like &drm_crtc_funcs.gamma_set. For atomic drivers all these
0072  * features are controlled through &drm_property and
0073  * &drm_mode_config_funcs.atomic_check.
0074  */
0075 
0076 /**
0077  * drm_crtc_from_index - find the registered CRTC at an index
0078  * @dev: DRM device
0079  * @idx: index of registered CRTC to find for
0080  *
0081  * Given a CRTC index, return the registered CRTC from DRM device's
0082  * list of CRTCs with matching index. This is the inverse of drm_crtc_index().
0083  * It's useful in the vblank callbacks (like &drm_driver.enable_vblank or
0084  * &drm_driver.disable_vblank), since that still deals with indices instead
0085  * of pointers to &struct drm_crtc."
0086  */
0087 struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx)
0088 {
0089     struct drm_crtc *crtc;
0090 
0091     drm_for_each_crtc(crtc, dev)
0092         if (idx == crtc->index)
0093             return crtc;
0094 
0095     return NULL;
0096 }
0097 EXPORT_SYMBOL(drm_crtc_from_index);
0098 
0099 int drm_crtc_force_disable(struct drm_crtc *crtc)
0100 {
0101     struct drm_mode_set set = {
0102         .crtc = crtc,
0103     };
0104 
0105     WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
0106 
0107     return drm_mode_set_config_internal(&set);
0108 }
0109 
0110 static unsigned int drm_num_crtcs(struct drm_device *dev)
0111 {
0112     unsigned int num = 0;
0113     struct drm_crtc *tmp;
0114 
0115     drm_for_each_crtc(tmp, dev) {
0116         num++;
0117     }
0118 
0119     return num;
0120 }
0121 
0122 int drm_crtc_register_all(struct drm_device *dev)
0123 {
0124     struct drm_crtc *crtc;
0125     int ret = 0;
0126 
0127     drm_for_each_crtc(crtc, dev) {
0128         drm_debugfs_crtc_add(crtc);
0129 
0130         if (crtc->funcs->late_register)
0131             ret = crtc->funcs->late_register(crtc);
0132         if (ret)
0133             return ret;
0134     }
0135 
0136     return 0;
0137 }
0138 
0139 void drm_crtc_unregister_all(struct drm_device *dev)
0140 {
0141     struct drm_crtc *crtc;
0142 
0143     drm_for_each_crtc(crtc, dev) {
0144         if (crtc->funcs->early_unregister)
0145             crtc->funcs->early_unregister(crtc);
0146         drm_debugfs_crtc_remove(crtc);
0147     }
0148 }
0149 
0150 static int drm_crtc_crc_init(struct drm_crtc *crtc)
0151 {
0152 #ifdef CONFIG_DEBUG_FS
0153     spin_lock_init(&crtc->crc.lock);
0154     init_waitqueue_head(&crtc->crc.wq);
0155     crtc->crc.source = kstrdup("auto", GFP_KERNEL);
0156     if (!crtc->crc.source)
0157         return -ENOMEM;
0158 #endif
0159     return 0;
0160 }
0161 
0162 static void drm_crtc_crc_fini(struct drm_crtc *crtc)
0163 {
0164 #ifdef CONFIG_DEBUG_FS
0165     kfree(crtc->crc.source);
0166 #endif
0167 }
0168 
0169 static const struct dma_fence_ops drm_crtc_fence_ops;
0170 
0171 static struct drm_crtc *fence_to_crtc(struct dma_fence *fence)
0172 {
0173     BUG_ON(fence->ops != &drm_crtc_fence_ops);
0174     return container_of(fence->lock, struct drm_crtc, fence_lock);
0175 }
0176 
0177 static const char *drm_crtc_fence_get_driver_name(struct dma_fence *fence)
0178 {
0179     struct drm_crtc *crtc = fence_to_crtc(fence);
0180 
0181     return crtc->dev->driver->name;
0182 }
0183 
0184 static const char *drm_crtc_fence_get_timeline_name(struct dma_fence *fence)
0185 {
0186     struct drm_crtc *crtc = fence_to_crtc(fence);
0187 
0188     return crtc->timeline_name;
0189 }
0190 
0191 static const struct dma_fence_ops drm_crtc_fence_ops = {
0192     .get_driver_name = drm_crtc_fence_get_driver_name,
0193     .get_timeline_name = drm_crtc_fence_get_timeline_name,
0194 };
0195 
0196 struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc)
0197 {
0198     struct dma_fence *fence;
0199 
0200     fence = kzalloc(sizeof(*fence), GFP_KERNEL);
0201     if (!fence)
0202         return NULL;
0203 
0204     dma_fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock,
0205                crtc->fence_context, ++crtc->fence_seqno);
0206 
0207     return fence;
0208 }
0209 
0210 /**
0211  * DOC: standard CRTC properties
0212  *
0213  * DRM CRTCs have a few standardized properties:
0214  *
0215  * ACTIVE:
0216  *  Atomic property for setting the power state of the CRTC. When set to 1
0217  *  the CRTC will actively display content. When set to 0 the CRTC will be
0218  *  powered off. There is no expectation that user-space will reset CRTC
0219  *  resources like the mode and planes when setting ACTIVE to 0.
0220  *
0221  *  User-space can rely on an ACTIVE change to 1 to never fail an atomic
0222  *  test as long as no other property has changed. If a change to ACTIVE
0223  *  fails an atomic test, this is a driver bug. For this reason setting
0224  *  ACTIVE to 0 must not release internal resources (like reserved memory
0225  *  bandwidth or clock generators).
0226  *
0227  *  Note that the legacy DPMS property on connectors is internally routed
0228  *  to control this property for atomic drivers.
0229  * MODE_ID:
0230  *  Atomic property for setting the CRTC display timings. The value is the
0231  *  ID of a blob containing the DRM mode info. To disable the CRTC,
0232  *  user-space must set this property to 0.
0233  *
0234  *  Setting MODE_ID to 0 will release reserved resources for the CRTC.
0235  * SCALING_FILTER:
0236  *  Atomic property for setting the scaling filter for CRTC scaler
0237  *
0238  *  The value of this property can be one of the following:
0239  *
0240  *  Default:
0241  *      Driver's default scaling filter
0242  *  Nearest Neighbor:
0243  *      Nearest Neighbor scaling filter
0244  */
0245 
0246 __printf(6, 0)
0247 static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
0248                        struct drm_plane *primary,
0249                        struct drm_plane *cursor,
0250                        const struct drm_crtc_funcs *funcs,
0251                        const char *name, va_list ap)
0252 {
0253     struct drm_mode_config *config = &dev->mode_config;
0254     int ret;
0255 
0256     WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY);
0257     WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR);
0258 
0259     /* crtc index is used with 32bit bitmasks */
0260     if (WARN_ON(config->num_crtc >= 32))
0261         return -EINVAL;
0262 
0263     WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
0264         (!funcs->atomic_destroy_state ||
0265          !funcs->atomic_duplicate_state));
0266 
0267     crtc->dev = dev;
0268     crtc->funcs = funcs;
0269 
0270     INIT_LIST_HEAD(&crtc->commit_list);
0271     spin_lock_init(&crtc->commit_lock);
0272 
0273     drm_modeset_lock_init(&crtc->mutex);
0274     ret = drm_mode_object_add(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
0275     if (ret)
0276         return ret;
0277 
0278     if (name) {
0279         crtc->name = kvasprintf(GFP_KERNEL, name, ap);
0280     } else {
0281         crtc->name = kasprintf(GFP_KERNEL, "crtc-%d",
0282                        drm_num_crtcs(dev));
0283     }
0284     if (!crtc->name) {
0285         drm_mode_object_unregister(dev, &crtc->base);
0286         return -ENOMEM;
0287     }
0288 
0289     crtc->fence_context = dma_fence_context_alloc(1);
0290     spin_lock_init(&crtc->fence_lock);
0291     snprintf(crtc->timeline_name, sizeof(crtc->timeline_name),
0292          "CRTC:%d-%s", crtc->base.id, crtc->name);
0293 
0294     crtc->base.properties = &crtc->properties;
0295 
0296     list_add_tail(&crtc->head, &config->crtc_list);
0297     crtc->index = config->num_crtc++;
0298 
0299     crtc->primary = primary;
0300     crtc->cursor = cursor;
0301     if (primary && !primary->possible_crtcs)
0302         primary->possible_crtcs = drm_crtc_mask(crtc);
0303     if (cursor && !cursor->possible_crtcs)
0304         cursor->possible_crtcs = drm_crtc_mask(crtc);
0305 
0306     ret = drm_crtc_crc_init(crtc);
0307     if (ret) {
0308         drm_mode_object_unregister(dev, &crtc->base);
0309         return ret;
0310     }
0311 
0312     if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
0313         drm_object_attach_property(&crtc->base, config->prop_active, 0);
0314         drm_object_attach_property(&crtc->base, config->prop_mode_id, 0);
0315         drm_object_attach_property(&crtc->base,
0316                        config->prop_out_fence_ptr, 0);
0317         drm_object_attach_property(&crtc->base,
0318                        config->prop_vrr_enabled, 0);
0319     }
0320 
0321     return 0;
0322 }
0323 
0324 /**
0325  * drm_crtc_init_with_planes - Initialise a new CRTC object with
0326  *    specified primary and cursor planes.
0327  * @dev: DRM device
0328  * @crtc: CRTC object to init
0329  * @primary: Primary plane for CRTC
0330  * @cursor: Cursor plane for CRTC
0331  * @funcs: callbacks for the new CRTC
0332  * @name: printf style format string for the CRTC name, or NULL for default name
0333  *
0334  * Inits a new object created as base part of a driver crtc object. Drivers
0335  * should use this function instead of drm_crtc_init(), which is only provided
0336  * for backwards compatibility with drivers which do not yet support universal
0337  * planes). For really simple hardware which has only 1 plane look at
0338  * drm_simple_display_pipe_init() instead.
0339  * The &drm_crtc_funcs.destroy hook should call drm_crtc_cleanup() and kfree()
0340  * the crtc structure. The crtc structure should not be allocated with
0341  * devm_kzalloc().
0342  *
0343  * The @primary and @cursor planes are only relevant for legacy uAPI, see
0344  * &drm_crtc.primary and &drm_crtc.cursor.
0345  *
0346  * Note: consider using drmm_crtc_alloc_with_planes() instead of
0347  * drm_crtc_init_with_planes() to let the DRM managed resource infrastructure
0348  * take care of cleanup and deallocation.
0349  *
0350  * Returns:
0351  * Zero on success, error code on failure.
0352  */
0353 int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
0354                   struct drm_plane *primary,
0355                   struct drm_plane *cursor,
0356                   const struct drm_crtc_funcs *funcs,
0357                   const char *name, ...)
0358 {
0359     va_list ap;
0360     int ret;
0361 
0362     WARN_ON(!funcs->destroy);
0363 
0364     va_start(ap, name);
0365     ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
0366                       name, ap);
0367     va_end(ap);
0368 
0369     return ret;
0370 }
0371 EXPORT_SYMBOL(drm_crtc_init_with_planes);
0372 
0373 static void drmm_crtc_alloc_with_planes_cleanup(struct drm_device *dev,
0374                         void *ptr)
0375 {
0376     struct drm_crtc *crtc = ptr;
0377 
0378     drm_crtc_cleanup(crtc);
0379 }
0380 
0381 void *__drmm_crtc_alloc_with_planes(struct drm_device *dev,
0382                     size_t size, size_t offset,
0383                     struct drm_plane *primary,
0384                     struct drm_plane *cursor,
0385                     const struct drm_crtc_funcs *funcs,
0386                     const char *name, ...)
0387 {
0388     void *container;
0389     struct drm_crtc *crtc;
0390     va_list ap;
0391     int ret;
0392 
0393     if (WARN_ON(!funcs || funcs->destroy))
0394         return ERR_PTR(-EINVAL);
0395 
0396     container = drmm_kzalloc(dev, size, GFP_KERNEL);
0397     if (!container)
0398         return ERR_PTR(-ENOMEM);
0399 
0400     crtc = container + offset;
0401 
0402     va_start(ap, name);
0403     ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
0404                       name, ap);
0405     va_end(ap);
0406     if (ret)
0407         return ERR_PTR(ret);
0408 
0409     ret = drmm_add_action_or_reset(dev, drmm_crtc_alloc_with_planes_cleanup,
0410                        crtc);
0411     if (ret)
0412         return ERR_PTR(ret);
0413 
0414     return container;
0415 }
0416 EXPORT_SYMBOL(__drmm_crtc_alloc_with_planes);
0417 
0418 /**
0419  * drm_crtc_cleanup - Clean up the core crtc usage
0420  * @crtc: CRTC to cleanup
0421  *
0422  * This function cleans up @crtc and removes it from the DRM mode setting
0423  * core. Note that the function does *not* free the crtc structure itself,
0424  * this is the responsibility of the caller.
0425  */
0426 void drm_crtc_cleanup(struct drm_crtc *crtc)
0427 {
0428     struct drm_device *dev = crtc->dev;
0429 
0430     /* Note that the crtc_list is considered to be static; should we
0431      * remove the drm_crtc at runtime we would have to decrement all
0432      * the indices on the drm_crtc after us in the crtc_list.
0433      */
0434 
0435     drm_crtc_crc_fini(crtc);
0436 
0437     kfree(crtc->gamma_store);
0438     crtc->gamma_store = NULL;
0439 
0440     drm_modeset_lock_fini(&crtc->mutex);
0441 
0442     drm_mode_object_unregister(dev, &crtc->base);
0443     list_del(&crtc->head);
0444     dev->mode_config.num_crtc--;
0445 
0446     WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state);
0447     if (crtc->state && crtc->funcs->atomic_destroy_state)
0448         crtc->funcs->atomic_destroy_state(crtc, crtc->state);
0449 
0450     kfree(crtc->name);
0451 
0452     memset(crtc, 0, sizeof(*crtc));
0453 }
0454 EXPORT_SYMBOL(drm_crtc_cleanup);
0455 
0456 /**
0457  * drm_mode_getcrtc - get CRTC configuration
0458  * @dev: drm device for the ioctl
0459  * @data: data pointer for the ioctl
0460  * @file_priv: drm file for the ioctl call
0461  *
0462  * Construct a CRTC configuration structure to return to the user.
0463  *
0464  * Called by the user via ioctl.
0465  *
0466  * Returns:
0467  * Zero on success, negative errno on failure.
0468  */
0469 int drm_mode_getcrtc(struct drm_device *dev,
0470              void *data, struct drm_file *file_priv)
0471 {
0472     struct drm_mode_crtc *crtc_resp = data;
0473     struct drm_crtc *crtc;
0474     struct drm_plane *plane;
0475 
0476     if (!drm_core_check_feature(dev, DRIVER_MODESET))
0477         return -EOPNOTSUPP;
0478 
0479     crtc = drm_crtc_find(dev, file_priv, crtc_resp->crtc_id);
0480     if (!crtc)
0481         return -ENOENT;
0482 
0483     plane = crtc->primary;
0484 
0485     crtc_resp->gamma_size = crtc->gamma_size;
0486 
0487     drm_modeset_lock(&plane->mutex, NULL);
0488     if (plane->state && plane->state->fb)
0489         crtc_resp->fb_id = plane->state->fb->base.id;
0490     else if (!plane->state && plane->fb)
0491         crtc_resp->fb_id = plane->fb->base.id;
0492     else
0493         crtc_resp->fb_id = 0;
0494 
0495     if (plane->state) {
0496         crtc_resp->x = plane->state->src_x >> 16;
0497         crtc_resp->y = plane->state->src_y >> 16;
0498     }
0499     drm_modeset_unlock(&plane->mutex);
0500 
0501     drm_modeset_lock(&crtc->mutex, NULL);
0502     if (crtc->state) {
0503         if (crtc->state->enable) {
0504             drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
0505             crtc_resp->mode_valid = 1;
0506         } else {
0507             crtc_resp->mode_valid = 0;
0508         }
0509     } else {
0510         crtc_resp->x = crtc->x;
0511         crtc_resp->y = crtc->y;
0512 
0513         if (crtc->enabled) {
0514             drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode);
0515             crtc_resp->mode_valid = 1;
0516 
0517         } else {
0518             crtc_resp->mode_valid = 0;
0519         }
0520     }
0521     if (!file_priv->aspect_ratio_allowed)
0522         crtc_resp->mode.flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
0523     drm_modeset_unlock(&crtc->mutex);
0524 
0525     return 0;
0526 }
0527 
0528 static int __drm_mode_set_config_internal(struct drm_mode_set *set,
0529                       struct drm_modeset_acquire_ctx *ctx)
0530 {
0531     struct drm_crtc *crtc = set->crtc;
0532     struct drm_framebuffer *fb;
0533     struct drm_crtc *tmp;
0534     int ret;
0535 
0536     WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
0537 
0538     /*
0539      * NOTE: ->set_config can also disable other crtcs (if we steal all
0540      * connectors from it), hence we need to refcount the fbs across all
0541      * crtcs. Atomic modeset will have saner semantics ...
0542      */
0543     drm_for_each_crtc(tmp, crtc->dev) {
0544         struct drm_plane *plane = tmp->primary;
0545 
0546         plane->old_fb = plane->fb;
0547     }
0548 
0549     fb = set->fb;
0550 
0551     ret = crtc->funcs->set_config(set, ctx);
0552     if (ret == 0) {
0553         struct drm_plane *plane = crtc->primary;
0554 
0555         plane->crtc = fb ? crtc : NULL;
0556         plane->fb = fb;
0557     }
0558 
0559     drm_for_each_crtc(tmp, crtc->dev) {
0560         struct drm_plane *plane = tmp->primary;
0561 
0562         if (plane->fb)
0563             drm_framebuffer_get(plane->fb);
0564         if (plane->old_fb)
0565             drm_framebuffer_put(plane->old_fb);
0566         plane->old_fb = NULL;
0567     }
0568 
0569     return ret;
0570 }
0571 
0572 /**
0573  * drm_mode_set_config_internal - helper to call &drm_mode_config_funcs.set_config
0574  * @set: modeset config to set
0575  *
0576  * This is a little helper to wrap internal calls to the
0577  * &drm_mode_config_funcs.set_config driver interface. The only thing it adds is
0578  * correct refcounting dance.
0579  *
0580  * This should only be used by non-atomic legacy drivers.
0581  *
0582  * Returns:
0583  * Zero on success, negative errno on failure.
0584  */
0585 int drm_mode_set_config_internal(struct drm_mode_set *set)
0586 {
0587     WARN_ON(drm_drv_uses_atomic_modeset(set->crtc->dev));
0588 
0589     return __drm_mode_set_config_internal(set, NULL);
0590 }
0591 EXPORT_SYMBOL(drm_mode_set_config_internal);
0592 
0593 /**
0594  * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the
0595  *     CRTC viewport
0596  * @crtc: CRTC that framebuffer will be displayed on
0597  * @x: x panning
0598  * @y: y panning
0599  * @mode: mode that framebuffer will be displayed under
0600  * @fb: framebuffer to check size of
0601  */
0602 int drm_crtc_check_viewport(const struct drm_crtc *crtc,
0603                 int x, int y,
0604                 const struct drm_display_mode *mode,
0605                 const struct drm_framebuffer *fb)
0606 
0607 {
0608     int hdisplay, vdisplay;
0609 
0610     drm_mode_get_hv_timing(mode, &hdisplay, &vdisplay);
0611 
0612     if (crtc->state &&
0613         drm_rotation_90_or_270(crtc->primary->state->rotation))
0614         swap(hdisplay, vdisplay);
0615 
0616     return drm_framebuffer_check_src_coords(x << 16, y << 16,
0617                         hdisplay << 16, vdisplay << 16,
0618                         fb);
0619 }
0620 EXPORT_SYMBOL(drm_crtc_check_viewport);
0621 
0622 /**
0623  * drm_mode_setcrtc - set CRTC configuration
0624  * @dev: drm device for the ioctl
0625  * @data: data pointer for the ioctl
0626  * @file_priv: drm file for the ioctl call
0627  *
0628  * Build a new CRTC configuration based on user request.
0629  *
0630  * Called by the user via ioctl.
0631  *
0632  * Returns:
0633  * Zero on success, negative errno on failure.
0634  */
0635 int drm_mode_setcrtc(struct drm_device *dev, void *data,
0636              struct drm_file *file_priv)
0637 {
0638     struct drm_mode_config *config = &dev->mode_config;
0639     struct drm_mode_crtc *crtc_req = data;
0640     struct drm_crtc *crtc;
0641     struct drm_plane *plane;
0642     struct drm_connector **connector_set = NULL, *connector;
0643     struct drm_framebuffer *fb = NULL;
0644     struct drm_display_mode *mode = NULL;
0645     struct drm_mode_set set;
0646     uint32_t __user *set_connectors_ptr;
0647     struct drm_modeset_acquire_ctx ctx;
0648     int ret;
0649     int i;
0650 
0651     if (!drm_core_check_feature(dev, DRIVER_MODESET))
0652         return -EOPNOTSUPP;
0653 
0654     /*
0655      * Universal plane src offsets are only 16.16, prevent havoc for
0656      * drivers using universal plane code internally.
0657      */
0658     if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
0659         return -ERANGE;
0660 
0661     crtc = drm_crtc_find(dev, file_priv, crtc_req->crtc_id);
0662     if (!crtc) {
0663         DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
0664         return -ENOENT;
0665     }
0666     DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
0667 
0668     plane = crtc->primary;
0669 
0670     /* allow disabling with the primary plane leased */
0671     if (crtc_req->mode_valid && !drm_lease_held(file_priv, plane->base.id))
0672         return -EACCES;
0673 
0674     DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx,
0675                    DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
0676 
0677     if (crtc_req->mode_valid) {
0678         /* If we have a mode we need a framebuffer. */
0679         /* If we pass -1, set the mode with the currently bound fb */
0680         if (crtc_req->fb_id == -1) {
0681             struct drm_framebuffer *old_fb;
0682 
0683             if (plane->state)
0684                 old_fb = plane->state->fb;
0685             else
0686                 old_fb = plane->fb;
0687 
0688             if (!old_fb) {
0689                 DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
0690                 ret = -EINVAL;
0691                 goto out;
0692             }
0693 
0694             fb = old_fb;
0695             /* Make refcounting symmetric with the lookup path. */
0696             drm_framebuffer_get(fb);
0697         } else {
0698             fb = drm_framebuffer_lookup(dev, file_priv, crtc_req->fb_id);
0699             if (!fb) {
0700                 DRM_DEBUG_KMS("Unknown FB ID%d\n",
0701                         crtc_req->fb_id);
0702                 ret = -ENOENT;
0703                 goto out;
0704             }
0705         }
0706 
0707         mode = drm_mode_create(dev);
0708         if (!mode) {
0709             ret = -ENOMEM;
0710             goto out;
0711         }
0712         if (!file_priv->aspect_ratio_allowed &&
0713             (crtc_req->mode.flags & DRM_MODE_FLAG_PIC_AR_MASK) != DRM_MODE_FLAG_PIC_AR_NONE) {
0714             DRM_DEBUG_KMS("Unexpected aspect-ratio flag bits\n");
0715             ret = -EINVAL;
0716             goto out;
0717         }
0718 
0719 
0720         ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode);
0721         if (ret) {
0722             DRM_DEBUG_KMS("Invalid mode (ret=%d, status=%s)\n",
0723                       ret, drm_get_mode_status_name(mode->status));
0724             drm_mode_debug_printmodeline(mode);
0725             goto out;
0726         }
0727 
0728         /*
0729          * Check whether the primary plane supports the fb pixel format.
0730          * Drivers not implementing the universal planes API use a
0731          * default formats list provided by the DRM core which doesn't
0732          * match real hardware capabilities. Skip the check in that
0733          * case.
0734          */
0735         if (!plane->format_default) {
0736             ret = drm_plane_check_pixel_format(plane,
0737                                fb->format->format,
0738                                fb->modifier);
0739             if (ret) {
0740                 DRM_DEBUG_KMS("Invalid pixel format %p4cc, modifier 0x%llx\n",
0741                           &fb->format->format,
0742                           fb->modifier);
0743                 goto out;
0744             }
0745         }
0746 
0747         ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
0748                           mode, fb);
0749         if (ret)
0750             goto out;
0751 
0752     }
0753 
0754     if (crtc_req->count_connectors == 0 && mode) {
0755         DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
0756         ret = -EINVAL;
0757         goto out;
0758     }
0759 
0760     if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
0761         DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
0762               crtc_req->count_connectors);
0763         ret = -EINVAL;
0764         goto out;
0765     }
0766 
0767     if (crtc_req->count_connectors > 0) {
0768         u32 out_id;
0769 
0770         /* Avoid unbounded kernel memory allocation */
0771         if (crtc_req->count_connectors > config->num_connector) {
0772             ret = -EINVAL;
0773             goto out;
0774         }
0775 
0776         connector_set = kmalloc_array(crtc_req->count_connectors,
0777                           sizeof(struct drm_connector *),
0778                           GFP_KERNEL);
0779         if (!connector_set) {
0780             ret = -ENOMEM;
0781             goto out;
0782         }
0783 
0784         for (i = 0; i < crtc_req->count_connectors; i++) {
0785             connector_set[i] = NULL;
0786             set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
0787             if (get_user(out_id, &set_connectors_ptr[i])) {
0788                 ret = -EFAULT;
0789                 goto out;
0790             }
0791 
0792             connector = drm_connector_lookup(dev, file_priv, out_id);
0793             if (!connector) {
0794                 DRM_DEBUG_KMS("Connector id %d unknown\n",
0795                         out_id);
0796                 ret = -ENOENT;
0797                 goto out;
0798             }
0799             DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
0800                     connector->base.id,
0801                     connector->name);
0802 
0803             connector_set[i] = connector;
0804         }
0805     }
0806 
0807     set.crtc = crtc;
0808     set.x = crtc_req->x;
0809     set.y = crtc_req->y;
0810     set.mode = mode;
0811     set.connectors = connector_set;
0812     set.num_connectors = crtc_req->count_connectors;
0813     set.fb = fb;
0814 
0815     if (drm_drv_uses_atomic_modeset(dev))
0816         ret = crtc->funcs->set_config(&set, &ctx);
0817     else
0818         ret = __drm_mode_set_config_internal(&set, &ctx);
0819 
0820 out:
0821     if (fb)
0822         drm_framebuffer_put(fb);
0823 
0824     if (connector_set) {
0825         for (i = 0; i < crtc_req->count_connectors; i++) {
0826             if (connector_set[i])
0827                 drm_connector_put(connector_set[i]);
0828         }
0829     }
0830     kfree(connector_set);
0831     drm_mode_destroy(dev, mode);
0832 
0833     /* In case we need to retry... */
0834     connector_set = NULL;
0835     fb = NULL;
0836     mode = NULL;
0837 
0838     DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
0839 
0840     return ret;
0841 }
0842 
0843 int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
0844                    struct drm_property *property,
0845                    uint64_t value)
0846 {
0847     int ret = -EINVAL;
0848     struct drm_crtc *crtc = obj_to_crtc(obj);
0849 
0850     if (crtc->funcs->set_property)
0851         ret = crtc->funcs->set_property(crtc, property, value);
0852     if (!ret)
0853         drm_object_property_set_value(obj, property, value);
0854 
0855     return ret;
0856 }
0857 
0858 /**
0859  * drm_crtc_create_scaling_filter_property - create a new scaling filter
0860  * property
0861  *
0862  * @crtc: drm CRTC
0863  * @supported_filters: bitmask of supported scaling filters, must include
0864  *             BIT(DRM_SCALING_FILTER_DEFAULT).
0865  *
0866  * This function lets driver to enable the scaling filter property on a given
0867  * CRTC.
0868  *
0869  * RETURNS:
0870  * Zero for success or -errno
0871  */
0872 int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc,
0873                         unsigned int supported_filters)
0874 {
0875     struct drm_property *prop =
0876         drm_create_scaling_filter_prop(crtc->dev, supported_filters);
0877 
0878     if (IS_ERR(prop))
0879         return PTR_ERR(prop);
0880 
0881     drm_object_attach_property(&crtc->base, prop,
0882                    DRM_SCALING_FILTER_DEFAULT);
0883     crtc->scaling_filter_property = prop;
0884 
0885     return 0;
0886 }
0887 EXPORT_SYMBOL(drm_crtc_create_scaling_filter_property);