drm_crtc.c 19.4 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 286
	ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
	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 492 493 494 495 496 497 498 499 500 501 502 503 504
/**
 * drm_crtc_get_hv_timing - Fetches hdisplay/vdisplay for given mode
 * @mode: mode to query
 * @hdisplay: hdisplay value to fill in
 * @vdisplay: vdisplay value to fill in
 *
 * The vdisplay value will be doubled if the specified mode is a stereo mode of
 * the appropriate layout.
 */
void drm_crtc_get_hv_timing(const struct drm_display_mode *mode,
			    int *hdisplay, int *vdisplay)
{
	struct drm_display_mode adjusted;

	drm_mode_copy(&adjusted, mode);
	drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY);
	*hdisplay = adjusted.crtc_hdisplay;
	*vdisplay = adjusted.crtc_vdisplay;
}
EXPORT_SYMBOL(drm_crtc_get_hv_timing);

505 506 507 508 509 510 511 512
/**
 * 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
513
 */
514 515 516 517
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)
518 519 520 521

{
	int hdisplay, vdisplay;

522
	drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay);
523

524
	if (crtc->state &&
525
	    drm_rotation_90_or_270(crtc->primary->state->rotation))
526 527
		swap(hdisplay, vdisplay);

D
Daniel Vetter 已提交
528 529 530
	return drm_framebuffer_check_src_coords(x << 16, y << 16,
						hdisplay << 16, vdisplay << 16,
						fb);
531
}
532
EXPORT_SYMBOL(drm_crtc_check_viewport);
533

D
Dave Airlie 已提交
534 535
/**
 * drm_mode_setcrtc - set CRTC configuration
536 537 538
 * @dev: drm device for the ioctl
 * @data: data pointer for the ioctl
 * @file_priv: drm file for the ioctl call
D
Dave Airlie 已提交
539 540 541 542 543
 *
 * Build a new CRTC configuration based on user request.
 *
 * Called by the user via ioctl.
 *
544
 * Returns:
D
Daniel Vetter 已提交
545
 * Zero on success, negative errno on failure.
D
Dave Airlie 已提交
546 547 548 549 550 551
 */
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;
552
	struct drm_crtc *crtc;
D
Dave Airlie 已提交
553 554 555 556 557
	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;
558
	int ret;
D
Dave Airlie 已提交
559 560
	int i;

561 562 563
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
		return -EINVAL;

564 565 566 567 568
	/*
	 * 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)
569 570
		return -ERANGE;

571
	drm_modeset_lock_all(dev);
R
Rob Clark 已提交
572 573
	crtc = drm_crtc_find(dev, crtc_req->crtc_id);
	if (!crtc) {
574
		DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
575
		ret = -ENOENT;
D
Dave Airlie 已提交
576 577
		goto out;
	}
578
	DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
D
Dave Airlie 已提交
579 580 581 582 583

	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) {
584
			if (!crtc->primary->fb) {
585 586 587
				DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
				ret = -EINVAL;
				goto out;
D
Dave Airlie 已提交
588
			}
589
			fb = crtc->primary->fb;
590 591
			/* Make refcounting symmetric with the lookup path. */
			drm_framebuffer_reference(fb);
D
Dave Airlie 已提交
592
		} else {
593 594
			fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
			if (!fb) {
595 596
				DRM_DEBUG_KMS("Unknown FB ID%d\n",
						crtc_req->fb_id);
597
				ret = -ENOENT;
D
Dave Airlie 已提交
598 599 600 601 602
				goto out;
			}
		}

		mode = drm_mode_create(dev);
603 604 605 606 607
		if (!mode) {
			ret = -ENOMEM;
			goto out;
		}

608
		ret = drm_mode_convert_umode(mode, &crtc_req->mode);
609 610 611 612 613
		if (ret) {
			DRM_DEBUG_KMS("Invalid mode\n");
			goto out;
		}

614 615 616 617 618 619 620 621 622
		/*
		 * 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ä 已提交
623
							   fb->format->format);
624
			if (ret) {
625 626
				struct drm_format_name_buf format_name;
				DRM_DEBUG_KMS("Invalid pixel format %s\n",
V
Ville Syrjälä 已提交
627
				              drm_get_format_name(fb->format->format,
628
				                                  &format_name));
629 630 631 632
				goto out;
			}
		}

633 634 635
		ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
					      mode, fb);
		if (ret)
636
			goto out;
637

D
Dave Airlie 已提交
638 639 640
	}

	if (crtc_req->count_connectors == 0 && mode) {
641
		DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
D
Dave Airlie 已提交
642 643 644 645
		ret = -EINVAL;
		goto out;
	}

646
	if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
647
		DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
D
Dave Airlie 已提交
648 649 650 651 652 653 654 655 656 657 658 659 660 661
			  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;
		}

662 663 664
		connector_set = kmalloc_array(crtc_req->count_connectors,
					      sizeof(struct drm_connector *),
					      GFP_KERNEL);
D
Dave Airlie 已提交
665 666 667 668 669 670
		if (!connector_set) {
			ret = -ENOMEM;
			goto out;
		}

		for (i = 0; i < crtc_req->count_connectors; i++) {
671
			connector_set[i] = NULL;
V
Ville Syrjälä 已提交
672
			set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
D
Dave Airlie 已提交
673 674 675 676 677
			if (get_user(out_id, &set_connectors_ptr[i])) {
				ret = -EFAULT;
				goto out;
			}

678
			connector = drm_connector_lookup(dev, out_id);
R
Rob Clark 已提交
679
			if (!connector) {
680 681
				DRM_DEBUG_KMS("Connector id %d unknown\n",
						out_id);
682
				ret = -ENOENT;
D
Dave Airlie 已提交
683 684
				goto out;
			}
685 686
			DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
					connector->base.id,
687
					connector->name);
D
Dave Airlie 已提交
688 689 690 691 692 693 694 695 696 697 698

			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;
699
	set.fb = fb;
700
	ret = drm_mode_set_config_internal(&set);
D
Dave Airlie 已提交
701 702

out:
703 704 705
	if (fb)
		drm_framebuffer_unreference(fb);

706 707 708 709 710 711
	if (connector_set) {
		for (i = 0; i < crtc_req->count_connectors; i++) {
			if (connector_set[i])
				drm_connector_unreference(connector_set[i]);
		}
	}
D
Dave Airlie 已提交
712
	kfree(connector_set);
713
	drm_mode_destroy(dev, mode);
714
	drm_modeset_unlock_all(dev);
D
Dave Airlie 已提交
715 716 717
	return ret;
}

718 719 720
int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
			       struct drm_property *property,
			       uint64_t value)
721
{
P
Paulo Zanoni 已提交
722 723
	int ret = -EINVAL;
	struct drm_crtc *crtc = obj_to_crtc(obj);
724

P
Paulo Zanoni 已提交
725 726 727 728
	if (crtc->funcs->set_property)
		ret = crtc->funcs->set_property(crtc, property, value);
	if (!ret)
		drm_object_property_set_value(obj, property, value);
729

P
Paulo Zanoni 已提交
730
	return ret;
731
}