drm_crtc.c 18.8 KB
Newer Older
D
Dave Airlie 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*
 * Copyright (c) 2006-2008 Intel Corporation
 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
 * Copyright (c) 2008 Red Hat Inc.
 *
 * DRM core CRTC related functions
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that copyright
 * notice and this permission notice appear in supporting documentation, and
 * that the name of the copyright holders not be used in advertising or
 * publicity pertaining to distribution of the software without specific,
 * written prior permission.  The copyright holders make no representations
 * about the suitability of this software for any purpose.  It is provided "as
 * is" without express or implied warranty.
 *
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 * OF THIS SOFTWARE.
 *
 * Authors:
 *      Keith Packard
 *	Eric Anholt <eric@anholt.net>
 *      Dave Airlie <airlied@linux.ie>
 *      Jesse Barnes <jesse.barnes@intel.com>
 */
32
#include <linux/ctype.h>
D
Dave Airlie 已提交
33
#include <linux/list.h>
34
#include <linux/slab.h>
35
#include <linux/export.h>
36
#include <linux/dma-fence.h>
37 38 39 40
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_fourcc.h>
41
#include <drm/drm_modeset_lock.h>
R
Rob Clark 已提交
42
#include <drm/drm_atomic.h>
D
Daniel Vetter 已提交
43
#include <drm/drm_auth.h>
44
#include <drm/drm_debugfs_crc.h>
D
Dave Airlie 已提交
45

46
#include "drm_crtc_internal.h"
47
#include "drm_internal.h"
48

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
/**
 * DOC: overview
 *
 * A CRTC represents the overall display pipeline. It receives pixel data from
 * &drm_plane and blends them together. The &drm_display_mode is also attached
 * to the CRTC, specifying display timings. On the output side the data is fed
 * to one or more &drm_encoder, which are then each connected to one
 * &drm_connector.
 *
 * To create a CRTC, a KMS drivers allocates and zeroes an instances of
 * &struct drm_crtc (possibly as part of a larger structure) and registers it
 * with a call to drm_crtc_init_with_planes().
 *
 * The CRTC is also the entry point for legacy modeset operations, see
 * &drm_crtc_funcs.set_config, legacy plane operations, see
 * &drm_crtc_funcs.page_flip and &drm_crtc_funcs.cursor_set2, and other legacy
 * operations like &drm_crtc_funcs.gamma_set. For atomic drivers all these
 * features are controlled through &drm_property and
 * &drm_mode_config_funcs.atomic_check and &drm_mode_config_funcs.atomic_check.
 */

70 71 72 73 74 75
/**
 * drm_crtc_from_index - find the registered CRTC at an index
 * @dev: DRM device
 * @idx: index of registered CRTC to find for
 *
 * Given a CRTC index, return the registered CRTC from DRM device's
76 77 78 79
 * list of CRTCs with matching index. This is the inverse of drm_crtc_index().
 * It's useful in the vblank callbacks (like &drm_driver.enable_vblank or
 * &drm_driver.disable_vblank), since that still deals with indices instead
 * of pointers to &struct drm_crtc."
80 81 82 83 84 85 86 87 88 89 90 91 92
 */
struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx)
{
	struct drm_crtc *crtc;

	drm_for_each_crtc(crtc, dev)
		if (idx == crtc->index)
			return crtc;

	return NULL;
}
EXPORT_SYMBOL(drm_crtc_from_index);

93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
/**
 * drm_crtc_force_disable - Forcibly turn off a CRTC
 * @crtc: CRTC to turn off
 *
 * Returns:
 * Zero on success, error code on failure.
 */
int drm_crtc_force_disable(struct drm_crtc *crtc)
{
	struct drm_mode_set set = {
		.crtc = crtc,
	};

	return drm_mode_set_config_internal(&set);
}
EXPORT_SYMBOL(drm_crtc_force_disable);

/**
 * drm_crtc_force_disable_all - Forcibly turn off all enabled CRTCs
 * @dev: DRM device whose CRTCs to turn off
 *
 * Drivers may want to call this on unload to ensure that all displays are
 * unlit and the GPU is in a consistent, low power state. Takes modeset locks.
 *
 * Returns:
 * Zero on success, error code on failure.
 */
int drm_crtc_force_disable_all(struct drm_device *dev)
{
	struct drm_crtc *crtc;
	int ret = 0;

	drm_modeset_lock_all(dev);
	drm_for_each_crtc(crtc, dev)
		if (crtc->enabled) {
			ret = drm_crtc_force_disable(crtc);
			if (ret)
				goto out;
		}
out:
	drm_modeset_unlock_all(dev);
	return ret;
}
EXPORT_SYMBOL(drm_crtc_force_disable_all);

138 139 140 141 142 143 144 145 146 147 148 149
static unsigned int drm_num_crtcs(struct drm_device *dev)
{
	unsigned int num = 0;
	struct drm_crtc *tmp;

	drm_for_each_crtc(tmp, dev) {
		num++;
	}

	return num;
}

D
Daniel Vetter 已提交
150
int drm_crtc_register_all(struct drm_device *dev)
151 152 153 154 155
{
	struct drm_crtc *crtc;
	int ret = 0;

	drm_for_each_crtc(crtc, dev) {
156 157 158 159
		if (drm_debugfs_crtc_add(crtc))
			DRM_ERROR("Failed to initialize debugfs entry for CRTC '%s'.\n",
				  crtc->name);

160 161 162 163 164 165 166 167 168
		if (crtc->funcs->late_register)
			ret = crtc->funcs->late_register(crtc);
		if (ret)
			return ret;
	}

	return 0;
}

D
Daniel Vetter 已提交
169
void drm_crtc_unregister_all(struct drm_device *dev)
170 171 172 173 174 175
{
	struct drm_crtc *crtc;

	drm_for_each_crtc(crtc, dev) {
		if (crtc->funcs->early_unregister)
			crtc->funcs->early_unregister(crtc);
176
		drm_debugfs_crtc_remove(crtc);
177 178 179
	}
}

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
static int drm_crtc_crc_init(struct drm_crtc *crtc)
{
#ifdef CONFIG_DEBUG_FS
	spin_lock_init(&crtc->crc.lock);
	init_waitqueue_head(&crtc->crc.wq);
	crtc->crc.source = kstrdup("auto", GFP_KERNEL);
	if (!crtc->crc.source)
		return -ENOMEM;
#endif
	return 0;
}

static void drm_crtc_crc_fini(struct drm_crtc *crtc)
{
#ifdef CONFIG_DEBUG_FS
	kfree(crtc->crc.source);
#endif
}

199 200
static const struct dma_fence_ops drm_crtc_fence_ops;

201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
static struct drm_crtc *fence_to_crtc(struct dma_fence *fence)
{
	BUG_ON(fence->ops != &drm_crtc_fence_ops);
	return container_of(fence->lock, struct drm_crtc, fence_lock);
}

static const char *drm_crtc_fence_get_driver_name(struct dma_fence *fence)
{
	struct drm_crtc *crtc = fence_to_crtc(fence);

	return crtc->dev->driver->name;
}

static const char *drm_crtc_fence_get_timeline_name(struct dma_fence *fence)
{
	struct drm_crtc *crtc = fence_to_crtc(fence);

	return crtc->timeline_name;
}

static bool drm_crtc_fence_enable_signaling(struct dma_fence *fence)
{
	return true;
}

226
static const struct dma_fence_ops drm_crtc_fence_ops = {
227 228 229 230 231 232
	.get_driver_name = drm_crtc_fence_get_driver_name,
	.get_timeline_name = drm_crtc_fence_get_timeline_name,
	.enable_signaling = drm_crtc_fence_enable_signaling,
	.wait = dma_fence_default_wait,
};

233 234 235 236 237 238 239 240 241 242 243 244 245 246
struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc)
{
	struct dma_fence *fence;

	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
	if (!fence)
		return NULL;

	dma_fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock,
		       crtc->fence_context, ++crtc->fence_seqno);

	return fence;
}

D
Dave Airlie 已提交
247
/**
248 249
 * drm_crtc_init_with_planes - Initialise a new CRTC object with
 *    specified primary and cursor planes.
D
Dave Airlie 已提交
250 251
 * @dev: DRM device
 * @crtc: CRTC object to init
252 253
 * @primary: Primary plane for CRTC
 * @cursor: Cursor plane for CRTC
D
Dave Airlie 已提交
254
 * @funcs: callbacks for the new CRTC
255
 * @name: printf style format string for the CRTC name, or NULL for default name
D
Dave Airlie 已提交
256
 *
257 258 259 260 261
 * Inits a new object created as base part of a driver crtc object. Drivers
 * should use this function instead of drm_crtc_init(), which is only provided
 * for backwards compatibility with drivers which do not yet support universal
 * planes). For really simple hardware which has only 1 plane look at
 * drm_simple_display_pipe_init() instead.
262
 *
263
 * Returns:
264
 * Zero on success, error code on failure.
D
Dave Airlie 已提交
265
 */
266 267
int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
			      struct drm_plane *primary,
268
			      struct drm_plane *cursor,
269 270
			      const struct drm_crtc_funcs *funcs,
			      const char *name, ...)
D
Dave Airlie 已提交
271
{
272
	struct drm_mode_config *config = &dev->mode_config;
273 274
	int ret;

275 276 277
	WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY);
	WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR);

D
Dave Airlie 已提交
278 279 280
	crtc->dev = dev;
	crtc->funcs = funcs;

281 282 283
	INIT_LIST_HEAD(&crtc->commit_list);
	spin_lock_init(&crtc->commit_lock);

284
	drm_modeset_lock_init(&crtc->mutex);
285
	ret = drm_mode_object_add(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
286
	if (ret)
287
		return ret;
D
Dave Airlie 已提交
288

289 290 291 292 293 294 295 296 297 298 299
	if (name) {
		va_list ap;

		va_start(ap, name);
		crtc->name = kvasprintf(GFP_KERNEL, name, ap);
		va_end(ap);
	} else {
		crtc->name = kasprintf(GFP_KERNEL, "crtc-%d",
				       drm_num_crtcs(dev));
	}
	if (!crtc->name) {
300
		drm_mode_object_unregister(dev, &crtc->base);
301 302 303
		return -ENOMEM;
	}

304 305 306 307 308
	crtc->fence_context = dma_fence_context_alloc(1);
	spin_lock_init(&crtc->fence_lock);
	snprintf(crtc->timeline_name, sizeof(crtc->timeline_name),
		 "CRTC:%d-%s", crtc->base.id, crtc->name);

P
Paulo Zanoni 已提交
309 310
	crtc->base.properties = &crtc->properties;

311
	list_add_tail(&crtc->head, &config->crtc_list);
C
Chris Wilson 已提交
312
	crtc->index = config->num_crtc++;
313

314
	crtc->primary = primary;
315
	crtc->cursor = cursor;
316
	if (primary && !primary->possible_crtcs)
317
		primary->possible_crtcs = 1 << drm_crtc_index(crtc);
318
	if (cursor && !cursor->possible_crtcs)
319
		cursor->possible_crtcs = 1 << drm_crtc_index(crtc);
320

321 322 323 324 325 326
	ret = drm_crtc_crc_init(crtc);
	if (ret) {
		drm_mode_object_unregister(dev, &crtc->base);
		return ret;
	}

327 328
	if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
		drm_object_attach_property(&crtc->base, config->prop_active, 0);
D
Daniel Stone 已提交
329
		drm_object_attach_property(&crtc->base, config->prop_mode_id, 0);
330 331
		drm_object_attach_property(&crtc->base,
					   config->prop_out_fence_ptr, 0);
332 333
	}

334
	return 0;
D
Dave Airlie 已提交
335
}
336
EXPORT_SYMBOL(drm_crtc_init_with_planes);
D
Dave Airlie 已提交
337 338

/**
339
 * drm_crtc_cleanup - Clean up the core crtc usage
D
Dave Airlie 已提交
340 341
 * @crtc: CRTC to cleanup
 *
342 343 344
 * This function cleans up @crtc and removes it from the DRM mode setting
 * core. Note that the function does *not* free the crtc structure itself,
 * this is the responsibility of the caller.
D
Dave Airlie 已提交
345 346 347 348 349
 */
void drm_crtc_cleanup(struct drm_crtc *crtc)
{
	struct drm_device *dev = crtc->dev;

C
Chris Wilson 已提交
350 351 352 353 354
	/* Note that the crtc_list is considered to be static; should we
	 * remove the drm_crtc at runtime we would have to decrement all
	 * the indices on the drm_crtc after us in the crtc_list.
	 */

355 356
	drm_crtc_crc_fini(crtc);

357 358
	kfree(crtc->gamma_store);
	crtc->gamma_store = NULL;
D
Dave Airlie 已提交
359

360 361
	drm_modeset_lock_fini(&crtc->mutex);

362
	drm_mode_object_unregister(dev, &crtc->base);
D
Dave Airlie 已提交
363 364
	list_del(&crtc->head);
	dev->mode_config.num_crtc--;
365 366 367 368

	WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state);
	if (crtc->state && crtc->funcs->atomic_destroy_state)
		crtc->funcs->atomic_destroy_state(crtc, crtc->state);
369

370 371
	kfree(crtc->name);

372
	memset(crtc, 0, sizeof(*crtc));
D
Dave Airlie 已提交
373 374 375 376 377
}
EXPORT_SYMBOL(drm_crtc_cleanup);

/**
 * drm_mode_getcrtc - get CRTC configuration
378 379 380
 * @dev: drm device for the ioctl
 * @data: data pointer for the ioctl
 * @file_priv: drm file for the ioctl call
D
Dave Airlie 已提交
381 382 383 384 385
 *
 * Construct a CRTC configuration structure to return to the user.
 *
 * Called by the user via ioctl.
 *
386
 * Returns:
D
Daniel Vetter 已提交
387
 * Zero on success, negative errno on failure.
D
Dave Airlie 已提交
388 389 390 391 392 393 394
 */
int drm_mode_getcrtc(struct drm_device *dev,
		     void *data, struct drm_file *file_priv)
{
	struct drm_mode_crtc *crtc_resp = data;
	struct drm_crtc *crtc;

395 396 397
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
		return -EINVAL;

R
Rob Clark 已提交
398
	crtc = drm_crtc_find(dev, crtc_resp->crtc_id);
399 400
	if (!crtc)
		return -ENOENT;
D
Dave Airlie 已提交
401

402
	drm_modeset_lock_crtc(crtc, crtc->primary);
D
Dave Airlie 已提交
403
	crtc_resp->gamma_size = crtc->gamma_size;
404 405 406 407

	if (crtc->primary->state && crtc->primary->state->fb)
		crtc_resp->fb_id = crtc->primary->state->fb->base.id;
	else if (!crtc->primary->state && crtc->primary->fb)
408
		crtc_resp->fb_id = crtc->primary->fb->base.id;
D
Dave Airlie 已提交
409 410 411
	else
		crtc_resp->fb_id = 0;

412 413 414 415
	if (crtc->state) {
		crtc_resp->x = crtc->primary->state->src_x >> 16;
		crtc_resp->y = crtc->primary->state->src_y >> 16;
		if (crtc->state->enable) {
416
			drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
417
			crtc_resp->mode_valid = 1;
D
Dave Airlie 已提交
418

419 420 421
		} else {
			crtc_resp->mode_valid = 0;
		}
D
Dave Airlie 已提交
422
	} else {
423 424 425
		crtc_resp->x = crtc->x;
		crtc_resp->y = crtc->y;
		if (crtc->enabled) {
426
			drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode);
427 428 429 430 431
			crtc_resp->mode_valid = 1;

		} else {
			crtc_resp->mode_valid = 0;
		}
D
Dave Airlie 已提交
432
	}
433
	drm_modeset_unlock_crtc(crtc);
D
Dave Airlie 已提交
434

435
	return 0;
D
Dave Airlie 已提交
436 437
}

438
/**
439
 * drm_mode_set_config_internal - helper to call &drm_mode_config_funcs.set_config
440 441
 * @set: modeset config to set
 *
442 443 444
 * This is a little helper to wrap internal calls to the
 * &drm_mode_config_funcs.set_config driver interface. The only thing it adds is
 * correct refcounting dance.
445
 *
446
 * Returns:
D
Daniel Vetter 已提交
447
 * Zero on success, negative errno on failure.
448 449 450 451
 */
int drm_mode_set_config_internal(struct drm_mode_set *set)
{
	struct drm_crtc *crtc = set->crtc;
D
Daniel Vetter 已提交
452 453
	struct drm_framebuffer *fb;
	struct drm_crtc *tmp;
454 455
	int ret;

D
Daniel Vetter 已提交
456 457 458 459 460
	/*
	 * NOTE: ->set_config can also disable other crtcs (if we steal all
	 * connectors from it), hence we need to refcount the fbs across all
	 * crtcs. Atomic modeset will have saner semantics ...
	 */
461
	drm_for_each_crtc(tmp, crtc->dev)
462
		tmp->primary->old_fb = tmp->primary->fb;
D
Daniel Vetter 已提交
463

464
	fb = set->fb;
465

466 467
	ret = crtc->funcs->set_config(set);
	if (ret == 0) {
468
		crtc->primary->crtc = crtc;
469
		crtc->primary->fb = fb;
D
Daniel Vetter 已提交
470
	}
471

472
	drm_for_each_crtc(tmp, crtc->dev) {
473 474
		if (tmp->primary->fb)
			drm_framebuffer_reference(tmp->primary->fb);
475 476 477
		if (tmp->primary->old_fb)
			drm_framebuffer_unreference(tmp->primary->old_fb);
		tmp->primary->old_fb = NULL;
478 479 480
	}

	return ret;
481 482 483
}
EXPORT_SYMBOL(drm_mode_set_config_internal);

484 485 486 487 488 489 490 491
/**
 * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the
 *     CRTC viewport
 * @crtc: CRTC that framebuffer will be displayed on
 * @x: x panning
 * @y: y panning
 * @mode: mode that framebuffer will be displayed under
 * @fb: framebuffer to check size of
492
 */
493 494 495 496
int drm_crtc_check_viewport(const struct drm_crtc *crtc,
			    int x, int y,
			    const struct drm_display_mode *mode,
			    const struct drm_framebuffer *fb)
497 498 499 500

{
	int hdisplay, vdisplay;

501
	drm_mode_get_hv_timing(mode, &hdisplay, &vdisplay);
502

503
	if (crtc->state &&
504
	    drm_rotation_90_or_270(crtc->primary->state->rotation))
505 506
		swap(hdisplay, vdisplay);

D
Daniel Vetter 已提交
507 508 509
	return drm_framebuffer_check_src_coords(x << 16, y << 16,
						hdisplay << 16, vdisplay << 16,
						fb);
510
}
511
EXPORT_SYMBOL(drm_crtc_check_viewport);
512

D
Dave Airlie 已提交
513 514
/**
 * drm_mode_setcrtc - set CRTC configuration
515 516 517
 * @dev: drm device for the ioctl
 * @data: data pointer for the ioctl
 * @file_priv: drm file for the ioctl call
D
Dave Airlie 已提交
518 519 520 521 522
 *
 * Build a new CRTC configuration based on user request.
 *
 * Called by the user via ioctl.
 *
523
 * Returns:
D
Daniel Vetter 已提交
524
 * Zero on success, negative errno on failure.
D
Dave Airlie 已提交
525 526 527 528 529 530
 */
int drm_mode_setcrtc(struct drm_device *dev, void *data,
		     struct drm_file *file_priv)
{
	struct drm_mode_config *config = &dev->mode_config;
	struct drm_mode_crtc *crtc_req = data;
531
	struct drm_crtc *crtc;
D
Dave Airlie 已提交
532 533 534 535 536
	struct drm_connector **connector_set = NULL, *connector;
	struct drm_framebuffer *fb = NULL;
	struct drm_display_mode *mode = NULL;
	struct drm_mode_set set;
	uint32_t __user *set_connectors_ptr;
537
	int ret;
D
Dave Airlie 已提交
538 539
	int i;

540 541 542
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
		return -EINVAL;

543 544 545 546 547
	/*
	 * Universal plane src offsets are only 16.16, prevent havoc for
	 * drivers using universal plane code internally.
	 */
	if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
548 549
		return -ERANGE;

550
	drm_modeset_lock_all(dev);
R
Rob Clark 已提交
551 552
	crtc = drm_crtc_find(dev, crtc_req->crtc_id);
	if (!crtc) {
553
		DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
554
		ret = -ENOENT;
D
Dave Airlie 已提交
555 556
		goto out;
	}
557
	DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
D
Dave Airlie 已提交
558 559 560 561 562

	if (crtc_req->mode_valid) {
		/* If we have a mode we need a framebuffer. */
		/* If we pass -1, set the mode with the currently bound fb */
		if (crtc_req->fb_id == -1) {
563
			if (!crtc->primary->fb) {
564 565 566
				DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
				ret = -EINVAL;
				goto out;
D
Dave Airlie 已提交
567
			}
568
			fb = crtc->primary->fb;
569 570
			/* Make refcounting symmetric with the lookup path. */
			drm_framebuffer_reference(fb);
D
Dave Airlie 已提交
571
		} else {
572 573
			fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
			if (!fb) {
574 575
				DRM_DEBUG_KMS("Unknown FB ID%d\n",
						crtc_req->fb_id);
576
				ret = -ENOENT;
D
Dave Airlie 已提交
577 578 579 580 581
				goto out;
			}
		}

		mode = drm_mode_create(dev);
582 583 584 585 586
		if (!mode) {
			ret = -ENOMEM;
			goto out;
		}

587
		ret = drm_mode_convert_umode(mode, &crtc_req->mode);
588 589 590 591 592
		if (ret) {
			DRM_DEBUG_KMS("Invalid mode\n");
			goto out;
		}

593 594 595 596 597 598 599 600 601
		/*
		 * Check whether the primary plane supports the fb pixel format.
		 * Drivers not implementing the universal planes API use a
		 * default formats list provided by the DRM core which doesn't
		 * match real hardware capabilities. Skip the check in that
		 * case.
		 */
		if (!crtc->primary->format_default) {
			ret = drm_plane_check_pixel_format(crtc->primary,
V
Ville Syrjälä 已提交
602
							   fb->format->format);
603
			if (ret) {
604 605
				struct drm_format_name_buf format_name;
				DRM_DEBUG_KMS("Invalid pixel format %s\n",
V
Ville Syrjälä 已提交
606
				              drm_get_format_name(fb->format->format,
607
				                                  &format_name));
608 609 610 611
				goto out;
			}
		}

612 613 614
		ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
					      mode, fb);
		if (ret)
615
			goto out;
616

D
Dave Airlie 已提交
617 618 619
	}

	if (crtc_req->count_connectors == 0 && mode) {
620
		DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
D
Dave Airlie 已提交
621 622 623 624
		ret = -EINVAL;
		goto out;
	}

625
	if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
626
		DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
D
Dave Airlie 已提交
627 628 629 630 631 632 633 634 635 636 637 638 639 640
			  crtc_req->count_connectors);
		ret = -EINVAL;
		goto out;
	}

	if (crtc_req->count_connectors > 0) {
		u32 out_id;

		/* Avoid unbounded kernel memory allocation */
		if (crtc_req->count_connectors > config->num_connector) {
			ret = -EINVAL;
			goto out;
		}

641 642 643
		connector_set = kmalloc_array(crtc_req->count_connectors,
					      sizeof(struct drm_connector *),
					      GFP_KERNEL);
D
Dave Airlie 已提交
644 645 646 647 648 649
		if (!connector_set) {
			ret = -ENOMEM;
			goto out;
		}

		for (i = 0; i < crtc_req->count_connectors; i++) {
650
			connector_set[i] = NULL;
V
Ville Syrjälä 已提交
651
			set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
D
Dave Airlie 已提交
652 653 654 655 656
			if (get_user(out_id, &set_connectors_ptr[i])) {
				ret = -EFAULT;
				goto out;
			}

657
			connector = drm_connector_lookup(dev, out_id);
R
Rob Clark 已提交
658
			if (!connector) {
659 660
				DRM_DEBUG_KMS("Connector id %d unknown\n",
						out_id);
661
				ret = -ENOENT;
D
Dave Airlie 已提交
662 663
				goto out;
			}
664 665
			DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
					connector->base.id,
666
					connector->name);
D
Dave Airlie 已提交
667 668 669 670 671 672 673 674 675 676 677

			connector_set[i] = connector;
		}
	}

	set.crtc = crtc;
	set.x = crtc_req->x;
	set.y = crtc_req->y;
	set.mode = mode;
	set.connectors = connector_set;
	set.num_connectors = crtc_req->count_connectors;
678
	set.fb = fb;
679
	ret = drm_mode_set_config_internal(&set);
D
Dave Airlie 已提交
680 681

out:
682 683 684
	if (fb)
		drm_framebuffer_unreference(fb);

685 686 687
	if (connector_set) {
		for (i = 0; i < crtc_req->count_connectors; i++) {
			if (connector_set[i])
688
				drm_connector_put(connector_set[i]);
689 690
		}
	}
D
Dave Airlie 已提交
691
	kfree(connector_set);
692
	drm_mode_destroy(dev, mode);
693
	drm_modeset_unlock_all(dev);
D
Dave Airlie 已提交
694 695 696
	return ret;
}

697 698 699
int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
			       struct drm_property *property,
			       uint64_t value)
700
{
P
Paulo Zanoni 已提交
701 702
	int ret = -EINVAL;
	struct drm_crtc *crtc = obj_to_crtc(obj);
703

P
Paulo Zanoni 已提交
704 705 706 707
	if (crtc->funcs->set_property)
		ret = crtc->funcs->set_property(crtc, property, value);
	if (!ret)
		drm_object_property_set_value(obj, property, value);
708

P
Paulo Zanoni 已提交
709
	return ret;
710
}