LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_crtc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 287 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 20 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2006-2008 Intel Corporation
       3             :  * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
       4             :  * Copyright (c) 2008 Red Hat Inc.
       5             :  *
       6             :  * DRM core CRTC related functions
       7             :  *
       8             :  * Permission to use, copy, modify, distribute, and sell this software and its
       9             :  * documentation for any purpose is hereby granted without fee, provided that
      10             :  * the above copyright notice appear in all copies and that both that copyright
      11             :  * notice and this permission notice appear in supporting documentation, and
      12             :  * that the name of the copyright holders not be used in advertising or
      13             :  * publicity pertaining to distribution of the software without specific,
      14             :  * written prior permission.  The copyright holders make no representations
      15             :  * about the suitability of this software for any purpose.  It is provided "as
      16             :  * 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 NO
      20             :  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
      21             :  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
      22             :  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
      23             :  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
      24             :  * OF THIS SOFTWARE.
      25             :  *
      26             :  * Authors:
      27             :  *      Keith Packard
      28             :  *      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_crtc.h>
      39             : #include <drm/drm_edid.h>
      40             : #include <drm/drm_fourcc.h>
      41             : #include <drm/drm_managed.h>
      42             : #include <drm/drm_modeset_lock.h>
      43             : #include <drm/drm_atomic.h>
      44             : #include <drm/drm_auth.h>
      45             : #include <drm/drm_debugfs_crc.h>
      46             : #include <drm/drm_drv.h>
      47             : #include <drm/drm_print.h>
      48             : #include <drm/drm_file.h>
      49             : 
      50             : #include "drm_crtc_internal.h"
      51             : #include "drm_internal.h"
      52             : 
      53             : /**
      54             :  * DOC: overview
      55             :  *
      56             :  * A CRTC represents the overall display pipeline. It receives pixel data from
      57             :  * &drm_plane and blends them together. The &drm_display_mode is also attached
      58             :  * to the CRTC, specifying display timings. On the output side the data is fed
      59             :  * to one or more &drm_encoder, which are then each connected to one
      60             :  * &drm_connector.
      61             :  *
      62             :  * To create a CRTC, a KMS drivers allocates and zeroes an instances of
      63             :  * &struct drm_crtc (possibly as part of a larger structure) and registers it
      64             :  * with a call to drm_crtc_init_with_planes().
      65             :  *
      66             :  * The CRTC is also the entry point for legacy modeset operations, see
      67             :  * &drm_crtc_funcs.set_config, legacy plane operations, see
      68             :  * &drm_crtc_funcs.page_flip and &drm_crtc_funcs.cursor_set2, and other legacy
      69             :  * operations like &drm_crtc_funcs.gamma_set. For atomic drivers all these
      70             :  * features are controlled through &drm_property and
      71             :  * &drm_mode_config_funcs.atomic_check.
      72             :  */
      73             : 
      74             : /**
      75             :  * drm_crtc_from_index - find the registered CRTC at an index
      76             :  * @dev: DRM device
      77             :  * @idx: index of registered CRTC to find for
      78             :  *
      79             :  * Given a CRTC index, return the registered CRTC from DRM device's
      80             :  * list of CRTCs with matching index. This is the inverse of drm_crtc_index().
      81             :  * It's useful in the vblank callbacks (like &drm_driver.enable_vblank or
      82             :  * &drm_driver.disable_vblank), since that still deals with indices instead
      83             :  * of pointers to &struct drm_crtc."
      84             :  */
      85           0 : struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx)
      86             : {
      87             :         struct drm_crtc *crtc;
      88             : 
      89           0 :         drm_for_each_crtc(crtc, dev)
      90           0 :                 if (idx == crtc->index)
      91             :                         return crtc;
      92             : 
      93             :         return NULL;
      94             : }
      95             : EXPORT_SYMBOL(drm_crtc_from_index);
      96             : 
      97           0 : int drm_crtc_force_disable(struct drm_crtc *crtc)
      98             : {
      99           0 :         struct drm_mode_set set = {
     100             :                 .crtc = crtc,
     101             :         };
     102             : 
     103           0 :         WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
     104             : 
     105           0 :         return drm_mode_set_config_internal(&set);
     106             : }
     107             : 
     108             : static unsigned int drm_num_crtcs(struct drm_device *dev)
     109             : {
     110           0 :         unsigned int num = 0;
     111             :         struct drm_crtc *tmp;
     112             : 
     113           0 :         drm_for_each_crtc(tmp, dev) {
     114           0 :                 num++;
     115             :         }
     116             : 
     117             :         return num;
     118             : }
     119             : 
     120           0 : int drm_crtc_register_all(struct drm_device *dev)
     121             : {
     122             :         struct drm_crtc *crtc;
     123           0 :         int ret = 0;
     124             : 
     125           0 :         drm_for_each_crtc(crtc, dev) {
     126           0 :                 drm_debugfs_crtc_add(crtc);
     127             : 
     128           0 :                 if (crtc->funcs->late_register)
     129           0 :                         ret = crtc->funcs->late_register(crtc);
     130           0 :                 if (ret)
     131             :                         return ret;
     132             :         }
     133             : 
     134             :         return 0;
     135             : }
     136             : 
     137           0 : void drm_crtc_unregister_all(struct drm_device *dev)
     138             : {
     139             :         struct drm_crtc *crtc;
     140             : 
     141           0 :         drm_for_each_crtc(crtc, dev) {
     142           0 :                 if (crtc->funcs->early_unregister)
     143           0 :                         crtc->funcs->early_unregister(crtc);
     144           0 :                 drm_debugfs_crtc_remove(crtc);
     145             :         }
     146           0 : }
     147             : 
     148             : static int drm_crtc_crc_init(struct drm_crtc *crtc)
     149             : {
     150             : #ifdef CONFIG_DEBUG_FS
     151             :         spin_lock_init(&crtc->crc.lock);
     152             :         init_waitqueue_head(&crtc->crc.wq);
     153             :         crtc->crc.source = kstrdup("auto", GFP_KERNEL);
     154             :         if (!crtc->crc.source)
     155             :                 return -ENOMEM;
     156             : #endif
     157             :         return 0;
     158             : }
     159             : 
     160             : static void drm_crtc_crc_fini(struct drm_crtc *crtc)
     161             : {
     162             : #ifdef CONFIG_DEBUG_FS
     163             :         kfree(crtc->crc.source);
     164             : #endif
     165             : }
     166             : 
     167             : static const struct dma_fence_ops drm_crtc_fence_ops;
     168             : 
     169           0 : static struct drm_crtc *fence_to_crtc(struct dma_fence *fence)
     170             : {
     171           0 :         BUG_ON(fence->ops != &drm_crtc_fence_ops);
     172           0 :         return container_of(fence->lock, struct drm_crtc, fence_lock);
     173             : }
     174             : 
     175           0 : static const char *drm_crtc_fence_get_driver_name(struct dma_fence *fence)
     176             : {
     177           0 :         struct drm_crtc *crtc = fence_to_crtc(fence);
     178             : 
     179           0 :         return crtc->dev->driver->name;
     180             : }
     181             : 
     182           0 : static const char *drm_crtc_fence_get_timeline_name(struct dma_fence *fence)
     183             : {
     184           0 :         struct drm_crtc *crtc = fence_to_crtc(fence);
     185             : 
     186           0 :         return crtc->timeline_name;
     187             : }
     188             : 
     189             : static const struct dma_fence_ops drm_crtc_fence_ops = {
     190             :         .get_driver_name = drm_crtc_fence_get_driver_name,
     191             :         .get_timeline_name = drm_crtc_fence_get_timeline_name,
     192             : };
     193             : 
     194           0 : struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc)
     195             : {
     196             :         struct dma_fence *fence;
     197             : 
     198           0 :         fence = kzalloc(sizeof(*fence), GFP_KERNEL);
     199           0 :         if (!fence)
     200             :                 return NULL;
     201             : 
     202           0 :         dma_fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock,
     203           0 :                        crtc->fence_context, ++crtc->fence_seqno);
     204             : 
     205           0 :         return fence;
     206             : }
     207             : 
     208             : /**
     209             :  * DOC: standard CRTC properties
     210             :  *
     211             :  * DRM CRTCs have a few standardized properties:
     212             :  *
     213             :  * ACTIVE:
     214             :  *      Atomic property for setting the power state of the CRTC. When set to 1
     215             :  *      the CRTC will actively display content. When set to 0 the CRTC will be
     216             :  *      powered off. There is no expectation that user-space will reset CRTC
     217             :  *      resources like the mode and planes when setting ACTIVE to 0.
     218             :  *
     219             :  *      User-space can rely on an ACTIVE change to 1 to never fail an atomic
     220             :  *      test as long as no other property has changed. If a change to ACTIVE
     221             :  *      fails an atomic test, this is a driver bug. For this reason setting
     222             :  *      ACTIVE to 0 must not release internal resources (like reserved memory
     223             :  *      bandwidth or clock generators).
     224             :  *
     225             :  *      Note that the legacy DPMS property on connectors is internally routed
     226             :  *      to control this property for atomic drivers.
     227             :  * MODE_ID:
     228             :  *      Atomic property for setting the CRTC display timings. The value is the
     229             :  *      ID of a blob containing the DRM mode info. To disable the CRTC,
     230             :  *      user-space must set this property to 0.
     231             :  *
     232             :  *      Setting MODE_ID to 0 will release reserved resources for the CRTC.
     233             :  * SCALING_FILTER:
     234             :  *      Atomic property for setting the scaling filter for CRTC scaler
     235             :  *
     236             :  *      The value of this property can be one of the following:
     237             :  *
     238             :  *      Default:
     239             :  *              Driver's default scaling filter
     240             :  *      Nearest Neighbor:
     241             :  *              Nearest Neighbor scaling filter
     242             :  */
     243             : 
     244             : __printf(6, 0)
     245           0 : static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
     246             :                                        struct drm_plane *primary,
     247             :                                        struct drm_plane *cursor,
     248             :                                        const struct drm_crtc_funcs *funcs,
     249             :                                        const char *name, va_list ap)
     250             : {
     251           0 :         struct drm_mode_config *config = &dev->mode_config;
     252             :         int ret;
     253             : 
     254           0 :         WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY);
     255           0 :         WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR);
     256             : 
     257             :         /* crtc index is used with 32bit bitmasks */
     258           0 :         if (WARN_ON(config->num_crtc >= 32))
     259             :                 return -EINVAL;
     260             : 
     261           0 :         WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
     262             :                 (!funcs->atomic_destroy_state ||
     263             :                  !funcs->atomic_duplicate_state));
     264             : 
     265           0 :         crtc->dev = dev;
     266           0 :         crtc->funcs = funcs;
     267             : 
     268           0 :         INIT_LIST_HEAD(&crtc->commit_list);
     269           0 :         spin_lock_init(&crtc->commit_lock);
     270             : 
     271           0 :         drm_modeset_lock_init(&crtc->mutex);
     272           0 :         ret = drm_mode_object_add(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
     273           0 :         if (ret)
     274             :                 return ret;
     275             : 
     276           0 :         if (name) {
     277           0 :                 crtc->name = kvasprintf(GFP_KERNEL, name, ap);
     278             :         } else {
     279           0 :                 crtc->name = kasprintf(GFP_KERNEL, "crtc-%d",
     280             :                                        drm_num_crtcs(dev));
     281             :         }
     282           0 :         if (!crtc->name) {
     283           0 :                 drm_mode_object_unregister(dev, &crtc->base);
     284           0 :                 return -ENOMEM;
     285             :         }
     286             : 
     287           0 :         crtc->fence_context = dma_fence_context_alloc(1);
     288           0 :         spin_lock_init(&crtc->fence_lock);
     289           0 :         snprintf(crtc->timeline_name, sizeof(crtc->timeline_name),
     290             :                  "CRTC:%d-%s", crtc->base.id, crtc->name);
     291             : 
     292           0 :         crtc->base.properties = &crtc->properties;
     293             : 
     294           0 :         list_add_tail(&crtc->head, &config->crtc_list);
     295           0 :         crtc->index = config->num_crtc++;
     296             : 
     297           0 :         crtc->primary = primary;
     298           0 :         crtc->cursor = cursor;
     299           0 :         if (primary && !primary->possible_crtcs)
     300           0 :                 primary->possible_crtcs = drm_crtc_mask(crtc);
     301           0 :         if (cursor && !cursor->possible_crtcs)
     302           0 :                 cursor->possible_crtcs = drm_crtc_mask(crtc);
     303             : 
     304           0 :         ret = drm_crtc_crc_init(crtc);
     305             :         if (ret) {
     306             :                 drm_mode_object_unregister(dev, &crtc->base);
     307             :                 return ret;
     308             :         }
     309             : 
     310           0 :         if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
     311           0 :                 drm_object_attach_property(&crtc->base, config->prop_active, 0);
     312           0 :                 drm_object_attach_property(&crtc->base, config->prop_mode_id, 0);
     313           0 :                 drm_object_attach_property(&crtc->base,
     314             :                                            config->prop_out_fence_ptr, 0);
     315           0 :                 drm_object_attach_property(&crtc->base,
     316             :                                            config->prop_vrr_enabled, 0);
     317             :         }
     318             : 
     319             :         return 0;
     320             : }
     321             : 
     322             : /**
     323             :  * drm_crtc_init_with_planes - Initialise a new CRTC object with
     324             :  *    specified primary and cursor planes.
     325             :  * @dev: DRM device
     326             :  * @crtc: CRTC object to init
     327             :  * @primary: Primary plane for CRTC
     328             :  * @cursor: Cursor plane for CRTC
     329             :  * @funcs: callbacks for the new CRTC
     330             :  * @name: printf style format string for the CRTC name, or NULL for default name
     331             :  *
     332             :  * Inits a new object created as base part of a driver crtc object. Drivers
     333             :  * should use this function instead of drm_crtc_init(), which is only provided
     334             :  * for backwards compatibility with drivers which do not yet support universal
     335             :  * planes). For really simple hardware which has only 1 plane look at
     336             :  * drm_simple_display_pipe_init() instead.
     337             :  * The &drm_crtc_funcs.destroy hook should call drm_crtc_cleanup() and kfree()
     338             :  * the crtc structure. The crtc structure should not be allocated with
     339             :  * devm_kzalloc().
     340             :  *
     341             :  * The @primary and @cursor planes are only relevant for legacy uAPI, see
     342             :  * &drm_crtc.primary and &drm_crtc.cursor.
     343             :  *
     344             :  * Note: consider using drmm_crtc_alloc_with_planes() instead of
     345             :  * drm_crtc_init_with_planes() to let the DRM managed resource infrastructure
     346             :  * take care of cleanup and deallocation.
     347             :  *
     348             :  * Returns:
     349             :  * Zero on success, error code on failure.
     350             :  */
     351           0 : int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
     352             :                               struct drm_plane *primary,
     353             :                               struct drm_plane *cursor,
     354             :                               const struct drm_crtc_funcs *funcs,
     355             :                               const char *name, ...)
     356             : {
     357             :         va_list ap;
     358             :         int ret;
     359             : 
     360           0 :         WARN_ON(!funcs->destroy);
     361             : 
     362           0 :         va_start(ap, name);
     363           0 :         ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
     364             :                                           name, ap);
     365           0 :         va_end(ap);
     366             : 
     367           0 :         return ret;
     368             : }
     369             : EXPORT_SYMBOL(drm_crtc_init_with_planes);
     370             : 
     371           0 : static void drmm_crtc_alloc_with_planes_cleanup(struct drm_device *dev,
     372             :                                                 void *ptr)
     373             : {
     374           0 :         struct drm_crtc *crtc = ptr;
     375             : 
     376           0 :         drm_crtc_cleanup(crtc);
     377           0 : }
     378             : 
     379           0 : void *__drmm_crtc_alloc_with_planes(struct drm_device *dev,
     380             :                                     size_t size, size_t offset,
     381             :                                     struct drm_plane *primary,
     382             :                                     struct drm_plane *cursor,
     383             :                                     const struct drm_crtc_funcs *funcs,
     384             :                                     const char *name, ...)
     385             : {
     386             :         void *container;
     387             :         struct drm_crtc *crtc;
     388             :         va_list ap;
     389             :         int ret;
     390             : 
     391           0 :         if (WARN_ON(!funcs || funcs->destroy))
     392             :                 return ERR_PTR(-EINVAL);
     393             : 
     394           0 :         container = drmm_kzalloc(dev, size, GFP_KERNEL);
     395           0 :         if (!container)
     396             :                 return ERR_PTR(-ENOMEM);
     397             : 
     398           0 :         crtc = container + offset;
     399             : 
     400           0 :         va_start(ap, name);
     401           0 :         ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
     402             :                                           name, ap);
     403           0 :         va_end(ap);
     404           0 :         if (ret)
     405           0 :                 return ERR_PTR(ret);
     406             : 
     407           0 :         ret = drmm_add_action_or_reset(dev, drmm_crtc_alloc_with_planes_cleanup,
     408             :                                        crtc);
     409           0 :         if (ret)
     410           0 :                 return ERR_PTR(ret);
     411             : 
     412             :         return container;
     413             : }
     414             : EXPORT_SYMBOL(__drmm_crtc_alloc_with_planes);
     415             : 
     416             : /**
     417             :  * drm_crtc_cleanup - Clean up the core crtc usage
     418             :  * @crtc: CRTC to cleanup
     419             :  *
     420             :  * This function cleans up @crtc and removes it from the DRM mode setting
     421             :  * core. Note that the function does *not* free the crtc structure itself,
     422             :  * this is the responsibility of the caller.
     423             :  */
     424           0 : void drm_crtc_cleanup(struct drm_crtc *crtc)
     425             : {
     426           0 :         struct drm_device *dev = crtc->dev;
     427             : 
     428             :         /* Note that the crtc_list is considered to be static; should we
     429             :          * remove the drm_crtc at runtime we would have to decrement all
     430             :          * the indices on the drm_crtc after us in the crtc_list.
     431             :          */
     432             : 
     433           0 :         drm_crtc_crc_fini(crtc);
     434             : 
     435           0 :         kfree(crtc->gamma_store);
     436           0 :         crtc->gamma_store = NULL;
     437             : 
     438           0 :         drm_modeset_lock_fini(&crtc->mutex);
     439             : 
     440           0 :         drm_mode_object_unregister(dev, &crtc->base);
     441           0 :         list_del(&crtc->head);
     442           0 :         dev->mode_config.num_crtc--;
     443             : 
     444           0 :         WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state);
     445           0 :         if (crtc->state && crtc->funcs->atomic_destroy_state)
     446           0 :                 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
     447             : 
     448           0 :         kfree(crtc->name);
     449             : 
     450           0 :         memset(crtc, 0, sizeof(*crtc));
     451           0 : }
     452             : EXPORT_SYMBOL(drm_crtc_cleanup);
     453             : 
     454             : /**
     455             :  * drm_mode_getcrtc - get CRTC configuration
     456             :  * @dev: drm device for the ioctl
     457             :  * @data: data pointer for the ioctl
     458             :  * @file_priv: drm file for the ioctl call
     459             :  *
     460             :  * Construct a CRTC configuration structure to return to the user.
     461             :  *
     462             :  * Called by the user via ioctl.
     463             :  *
     464             :  * Returns:
     465             :  * Zero on success, negative errno on failure.
     466             :  */
     467           0 : int drm_mode_getcrtc(struct drm_device *dev,
     468             :                      void *data, struct drm_file *file_priv)
     469             : {
     470           0 :         struct drm_mode_crtc *crtc_resp = data;
     471             :         struct drm_crtc *crtc;
     472             :         struct drm_plane *plane;
     473             : 
     474           0 :         if (!drm_core_check_feature(dev, DRIVER_MODESET))
     475             :                 return -EOPNOTSUPP;
     476             : 
     477           0 :         crtc = drm_crtc_find(dev, file_priv, crtc_resp->crtc_id);
     478           0 :         if (!crtc)
     479             :                 return -ENOENT;
     480             : 
     481           0 :         plane = crtc->primary;
     482             : 
     483           0 :         crtc_resp->gamma_size = crtc->gamma_size;
     484             : 
     485           0 :         drm_modeset_lock(&plane->mutex, NULL);
     486           0 :         if (plane->state && plane->state->fb)
     487           0 :                 crtc_resp->fb_id = plane->state->fb->base.id;
     488           0 :         else if (!plane->state && plane->fb)
     489           0 :                 crtc_resp->fb_id = plane->fb->base.id;
     490             :         else
     491           0 :                 crtc_resp->fb_id = 0;
     492             : 
     493           0 :         if (plane->state) {
     494           0 :                 crtc_resp->x = plane->state->src_x >> 16;
     495           0 :                 crtc_resp->y = plane->state->src_y >> 16;
     496             :         }
     497           0 :         drm_modeset_unlock(&plane->mutex);
     498             : 
     499           0 :         drm_modeset_lock(&crtc->mutex, NULL);
     500           0 :         if (crtc->state) {
     501           0 :                 if (crtc->state->enable) {
     502           0 :                         drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
     503           0 :                         crtc_resp->mode_valid = 1;
     504             :                 } else {
     505           0 :                         crtc_resp->mode_valid = 0;
     506             :                 }
     507             :         } else {
     508           0 :                 crtc_resp->x = crtc->x;
     509           0 :                 crtc_resp->y = crtc->y;
     510             : 
     511           0 :                 if (crtc->enabled) {
     512           0 :                         drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode);
     513           0 :                         crtc_resp->mode_valid = 1;
     514             : 
     515             :                 } else {
     516           0 :                         crtc_resp->mode_valid = 0;
     517             :                 }
     518             :         }
     519           0 :         if (!file_priv->aspect_ratio_allowed)
     520           0 :                 crtc_resp->mode.flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
     521           0 :         drm_modeset_unlock(&crtc->mutex);
     522             : 
     523           0 :         return 0;
     524             : }
     525             : 
     526           0 : static int __drm_mode_set_config_internal(struct drm_mode_set *set,
     527             :                                           struct drm_modeset_acquire_ctx *ctx)
     528             : {
     529           0 :         struct drm_crtc *crtc = set->crtc;
     530             :         struct drm_framebuffer *fb;
     531             :         struct drm_crtc *tmp;
     532             :         int ret;
     533             : 
     534           0 :         WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
     535             : 
     536             :         /*
     537             :          * NOTE: ->set_config can also disable other crtcs (if we steal all
     538             :          * connectors from it), hence we need to refcount the fbs across all
     539             :          * crtcs. Atomic modeset will have saner semantics ...
     540             :          */
     541           0 :         drm_for_each_crtc(tmp, crtc->dev) {
     542           0 :                 struct drm_plane *plane = tmp->primary;
     543             : 
     544           0 :                 plane->old_fb = plane->fb;
     545             :         }
     546             : 
     547           0 :         fb = set->fb;
     548             : 
     549           0 :         ret = crtc->funcs->set_config(set, ctx);
     550           0 :         if (ret == 0) {
     551           0 :                 struct drm_plane *plane = crtc->primary;
     552             : 
     553           0 :                 plane->crtc = fb ? crtc : NULL;
     554           0 :                 plane->fb = fb;
     555             :         }
     556             : 
     557           0 :         drm_for_each_crtc(tmp, crtc->dev) {
     558           0 :                 struct drm_plane *plane = tmp->primary;
     559             : 
     560           0 :                 if (plane->fb)
     561           0 :                         drm_framebuffer_get(plane->fb);
     562           0 :                 if (plane->old_fb)
     563           0 :                         drm_framebuffer_put(plane->old_fb);
     564           0 :                 plane->old_fb = NULL;
     565             :         }
     566             : 
     567           0 :         return ret;
     568             : }
     569             : 
     570             : /**
     571             :  * drm_mode_set_config_internal - helper to call &drm_mode_config_funcs.set_config
     572             :  * @set: modeset config to set
     573             :  *
     574             :  * This is a little helper to wrap internal calls to the
     575             :  * &drm_mode_config_funcs.set_config driver interface. The only thing it adds is
     576             :  * correct refcounting dance.
     577             :  *
     578             :  * This should only be used by non-atomic legacy drivers.
     579             :  *
     580             :  * Returns:
     581             :  * Zero on success, negative errno on failure.
     582             :  */
     583           0 : int drm_mode_set_config_internal(struct drm_mode_set *set)
     584             : {
     585           0 :         WARN_ON(drm_drv_uses_atomic_modeset(set->crtc->dev));
     586             : 
     587           0 :         return __drm_mode_set_config_internal(set, NULL);
     588             : }
     589             : EXPORT_SYMBOL(drm_mode_set_config_internal);
     590             : 
     591             : /**
     592             :  * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the
     593             :  *     CRTC viewport
     594             :  * @crtc: CRTC that framebuffer will be displayed on
     595             :  * @x: x panning
     596             :  * @y: y panning
     597             :  * @mode: mode that framebuffer will be displayed under
     598             :  * @fb: framebuffer to check size of
     599             :  */
     600           0 : int drm_crtc_check_viewport(const struct drm_crtc *crtc,
     601             :                             int x, int y,
     602             :                             const struct drm_display_mode *mode,
     603             :                             const struct drm_framebuffer *fb)
     604             : 
     605             : {
     606             :         int hdisplay, vdisplay;
     607             : 
     608           0 :         drm_mode_get_hv_timing(mode, &hdisplay, &vdisplay);
     609             : 
     610           0 :         if (crtc->state &&
     611           0 :             drm_rotation_90_or_270(crtc->primary->state->rotation))
     612           0 :                 swap(hdisplay, vdisplay);
     613             : 
     614           0 :         return drm_framebuffer_check_src_coords(x << 16, y << 16,
     615           0 :                                                 hdisplay << 16, vdisplay << 16,
     616             :                                                 fb);
     617             : }
     618             : EXPORT_SYMBOL(drm_crtc_check_viewport);
     619             : 
     620             : /**
     621             :  * drm_mode_setcrtc - set CRTC configuration
     622             :  * @dev: drm device for the ioctl
     623             :  * @data: data pointer for the ioctl
     624             :  * @file_priv: drm file for the ioctl call
     625             :  *
     626             :  * Build a new CRTC configuration based on user request.
     627             :  *
     628             :  * Called by the user via ioctl.
     629             :  *
     630             :  * Returns:
     631             :  * Zero on success, negative errno on failure.
     632             :  */
     633           0 : int drm_mode_setcrtc(struct drm_device *dev, void *data,
     634             :                      struct drm_file *file_priv)
     635             : {
     636           0 :         struct drm_mode_config *config = &dev->mode_config;
     637           0 :         struct drm_mode_crtc *crtc_req = data;
     638             :         struct drm_crtc *crtc;
     639             :         struct drm_plane *plane;
     640           0 :         struct drm_connector **connector_set = NULL, *connector;
     641           0 :         struct drm_framebuffer *fb = NULL;
     642           0 :         struct drm_display_mode *mode = NULL;
     643             :         struct drm_mode_set set;
     644             :         uint32_t __user *set_connectors_ptr;
     645             :         struct drm_modeset_acquire_ctx ctx;
     646             :         int ret;
     647             :         int i;
     648             : 
     649           0 :         if (!drm_core_check_feature(dev, DRIVER_MODESET))
     650             :                 return -EOPNOTSUPP;
     651             : 
     652             :         /*
     653             :          * Universal plane src offsets are only 16.16, prevent havoc for
     654             :          * drivers using universal plane code internally.
     655             :          */
     656           0 :         if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
     657             :                 return -ERANGE;
     658             : 
     659           0 :         crtc = drm_crtc_find(dev, file_priv, crtc_req->crtc_id);
     660           0 :         if (!crtc) {
     661           0 :                 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
     662           0 :                 return -ENOENT;
     663             :         }
     664           0 :         DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
     665             : 
     666           0 :         plane = crtc->primary;
     667             : 
     668             :         /* allow disabling with the primary plane leased */
     669           0 :         if (crtc_req->mode_valid && !drm_lease_held(file_priv, plane->base.id))
     670             :                 return -EACCES;
     671             : 
     672           0 :         DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx,
     673             :                                    DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
     674             : 
     675           0 :         if (crtc_req->mode_valid) {
     676             :                 /* If we have a mode we need a framebuffer. */
     677             :                 /* If we pass -1, set the mode with the currently bound fb */
     678           0 :                 if (crtc_req->fb_id == -1) {
     679             :                         struct drm_framebuffer *old_fb;
     680             : 
     681           0 :                         if (plane->state)
     682           0 :                                 old_fb = plane->state->fb;
     683             :                         else
     684           0 :                                 old_fb = plane->fb;
     685             : 
     686           0 :                         if (!old_fb) {
     687           0 :                                 DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
     688           0 :                                 ret = -EINVAL;
     689           0 :                                 goto out;
     690             :                         }
     691             : 
     692           0 :                         fb = old_fb;
     693             :                         /* Make refcounting symmetric with the lookup path. */
     694             :                         drm_framebuffer_get(fb);
     695             :                 } else {
     696           0 :                         fb = drm_framebuffer_lookup(dev, file_priv, crtc_req->fb_id);
     697           0 :                         if (!fb) {
     698           0 :                                 DRM_DEBUG_KMS("Unknown FB ID%d\n",
     699             :                                                 crtc_req->fb_id);
     700           0 :                                 ret = -ENOENT;
     701           0 :                                 goto out;
     702             :                         }
     703             :                 }
     704             : 
     705           0 :                 mode = drm_mode_create(dev);
     706           0 :                 if (!mode) {
     707             :                         ret = -ENOMEM;
     708             :                         goto out;
     709             :                 }
     710           0 :                 if (!file_priv->aspect_ratio_allowed &&
     711           0 :                     (crtc_req->mode.flags & DRM_MODE_FLAG_PIC_AR_MASK) != DRM_MODE_FLAG_PIC_AR_NONE) {
     712           0 :                         DRM_DEBUG_KMS("Unexpected aspect-ratio flag bits\n");
     713           0 :                         ret = -EINVAL;
     714           0 :                         goto out;
     715             :                 }
     716             : 
     717             : 
     718           0 :                 ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode);
     719           0 :                 if (ret) {
     720           0 :                         DRM_DEBUG_KMS("Invalid mode (ret=%d, status=%s)\n",
     721             :                                       ret, drm_get_mode_status_name(mode->status));
     722           0 :                         drm_mode_debug_printmodeline(mode);
     723           0 :                         goto out;
     724             :                 }
     725             : 
     726             :                 /*
     727             :                  * Check whether the primary plane supports the fb pixel format.
     728             :                  * Drivers not implementing the universal planes API use a
     729             :                  * default formats list provided by the DRM core which doesn't
     730             :                  * match real hardware capabilities. Skip the check in that
     731             :                  * case.
     732             :                  */
     733           0 :                 if (!plane->format_default) {
     734           0 :                         ret = drm_plane_check_pixel_format(plane,
     735           0 :                                                            fb->format->format,
     736             :                                                            fb->modifier);
     737           0 :                         if (ret) {
     738           0 :                                 DRM_DEBUG_KMS("Invalid pixel format %p4cc, modifier 0x%llx\n",
     739             :                                               &fb->format->format,
     740             :                                               fb->modifier);
     741           0 :                                 goto out;
     742             :                         }
     743             :                 }
     744             : 
     745           0 :                 ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
     746             :                                               mode, fb);
     747           0 :                 if (ret)
     748             :                         goto out;
     749             : 
     750             :         }
     751             : 
     752           0 :         if (crtc_req->count_connectors == 0 && mode) {
     753           0 :                 DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
     754           0 :                 ret = -EINVAL;
     755           0 :                 goto out;
     756             :         }
     757             : 
     758           0 :         if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
     759           0 :                 DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
     760             :                           crtc_req->count_connectors);
     761           0 :                 ret = -EINVAL;
     762           0 :                 goto out;
     763             :         }
     764             : 
     765           0 :         if (crtc_req->count_connectors > 0) {
     766             :                 u32 out_id;
     767             : 
     768             :                 /* Avoid unbounded kernel memory allocation */
     769           0 :                 if (crtc_req->count_connectors > config->num_connector) {
     770             :                         ret = -EINVAL;
     771             :                         goto out;
     772             :                 }
     773             : 
     774           0 :                 connector_set = kmalloc_array(crtc_req->count_connectors,
     775             :                                               sizeof(struct drm_connector *),
     776             :                                               GFP_KERNEL);
     777           0 :                 if (!connector_set) {
     778             :                         ret = -ENOMEM;
     779             :                         goto out;
     780             :                 }
     781             : 
     782           0 :                 for (i = 0; i < crtc_req->count_connectors; i++) {
     783           0 :                         connector_set[i] = NULL;
     784           0 :                         set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
     785           0 :                         if (get_user(out_id, &set_connectors_ptr[i])) {
     786             :                                 ret = -EFAULT;
     787             :                                 goto out;
     788             :                         }
     789             : 
     790           0 :                         connector = drm_connector_lookup(dev, file_priv, out_id);
     791           0 :                         if (!connector) {
     792           0 :                                 DRM_DEBUG_KMS("Connector id %d unknown\n",
     793             :                                                 out_id);
     794           0 :                                 ret = -ENOENT;
     795           0 :                                 goto out;
     796             :                         }
     797           0 :                         DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
     798             :                                         connector->base.id,
     799             :                                         connector->name);
     800             : 
     801           0 :                         connector_set[i] = connector;
     802             :                 }
     803             :         }
     804             : 
     805           0 :         set.crtc = crtc;
     806           0 :         set.x = crtc_req->x;
     807           0 :         set.y = crtc_req->y;
     808           0 :         set.mode = mode;
     809           0 :         set.connectors = connector_set;
     810           0 :         set.num_connectors = crtc_req->count_connectors;
     811           0 :         set.fb = fb;
     812             : 
     813           0 :         if (drm_drv_uses_atomic_modeset(dev))
     814           0 :                 ret = crtc->funcs->set_config(&set, &ctx);
     815             :         else
     816           0 :                 ret = __drm_mode_set_config_internal(&set, &ctx);
     817             : 
     818             : out:
     819           0 :         if (fb)
     820             :                 drm_framebuffer_put(fb);
     821             : 
     822           0 :         if (connector_set) {
     823           0 :                 for (i = 0; i < crtc_req->count_connectors; i++) {
     824           0 :                         if (connector_set[i])
     825           0 :                                 drm_connector_put(connector_set[i]);
     826             :                 }
     827             :         }
     828           0 :         kfree(connector_set);
     829           0 :         drm_mode_destroy(dev, mode);
     830             : 
     831             :         /* In case we need to retry... */
     832           0 :         connector_set = NULL;
     833           0 :         fb = NULL;
     834           0 :         mode = NULL;
     835             : 
     836           0 :         DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
     837             : 
     838             :         return ret;
     839             : }
     840             : 
     841           0 : int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
     842             :                                struct drm_property *property,
     843             :                                uint64_t value)
     844             : {
     845           0 :         int ret = -EINVAL;
     846           0 :         struct drm_crtc *crtc = obj_to_crtc(obj);
     847             : 
     848           0 :         if (crtc->funcs->set_property)
     849           0 :                 ret = crtc->funcs->set_property(crtc, property, value);
     850           0 :         if (!ret)
     851           0 :                 drm_object_property_set_value(obj, property, value);
     852             : 
     853           0 :         return ret;
     854             : }
     855             : 
     856             : /**
     857             :  * drm_crtc_create_scaling_filter_property - create a new scaling filter
     858             :  * property
     859             :  *
     860             :  * @crtc: drm CRTC
     861             :  * @supported_filters: bitmask of supported scaling filters, must include
     862             :  *                     BIT(DRM_SCALING_FILTER_DEFAULT).
     863             :  *
     864             :  * This function lets driver to enable the scaling filter property on a given
     865             :  * CRTC.
     866             :  *
     867             :  * RETURNS:
     868             :  * Zero for success or -errno
     869             :  */
     870           0 : int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc,
     871             :                                             unsigned int supported_filters)
     872             : {
     873           0 :         struct drm_property *prop =
     874           0 :                 drm_create_scaling_filter_prop(crtc->dev, supported_filters);
     875             : 
     876           0 :         if (IS_ERR(prop))
     877           0 :                 return PTR_ERR(prop);
     878             : 
     879           0 :         drm_object_attach_property(&crtc->base, prop,
     880             :                                    DRM_SCALING_FILTER_DEFAULT);
     881           0 :         crtc->scaling_filter_property = prop;
     882             : 
     883           0 :         return 0;
     884             : }
     885             : EXPORT_SYMBOL(drm_crtc_create_scaling_filter_property);

Generated by: LCOV version 1.14