LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_crtc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 6 297 2.0 %
Date: 2023-04-06 08:38:28 Functions: 2 22 9.1 %

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

Generated by: LCOV version 1.14