brintos

brintos / linux-shallow public Read only

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