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