]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/gpu/drm/drm_crtc.c
dma-buf/sync_file: hold reference to fence when creating sync_file
[mirror_ubuntu-jammy-kernel.git] / drivers / gpu / drm / drm_crtc.c
CommitLineData
f453ba04
DA
1/*
2 * Copyright (c) 2006-2008 Intel Corporation
3 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
4 * Copyright (c) 2008 Red Hat Inc.
5 *
6 * DRM core CRTC related functions
7 *
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that copyright
11 * notice and this permission notice appear in supporting documentation, and
12 * that the name of the copyright holders not be used in advertising or
13 * publicity pertaining to distribution of the software without specific,
14 * written prior permission. The copyright holders make no representations
15 * about the suitability of this software for any purpose. It is provided "as
16 * is" without express or implied warranty.
17 *
18 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
20 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
23 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 * OF THIS SOFTWARE.
25 *
26 * Authors:
27 * Keith Packard
28 * Eric Anholt <eric@anholt.net>
29 * Dave Airlie <airlied@linux.ie>
30 * Jesse Barnes <jesse.barnes@intel.com>
31 */
6ba6d03e 32#include <linux/ctype.h>
f453ba04 33#include <linux/list.h>
5a0e3ad6 34#include <linux/slab.h>
2d1a8a48 35#include <linux/export.h>
760285e7
DH
36#include <drm/drmP.h>
37#include <drm/drm_crtc.h>
38#include <drm/drm_edid.h>
39#include <drm/drm_fourcc.h>
51fd371b 40#include <drm/drm_modeset_lock.h>
88a48e29 41#include <drm/drm_atomic.h>
3b96a0b1 42#include <drm/drm_auth.h>
9edbf1fa 43#include <drm/drm_debugfs_crc.h>
f453ba04 44
8bd441b2 45#include "drm_crtc_internal.h"
67d0ec4e 46#include "drm_internal.h"
8bd441b2 47
f453ba04
DA
48/*
49 * Global properties
50 */
4dfd909f 51static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
9922ab5a
RC
52 { DRM_PLANE_TYPE_OVERLAY, "Overlay" },
53 { DRM_PLANE_TYPE_PRIMARY, "Primary" },
54 { DRM_PLANE_TYPE_CURSOR, "Cursor" },
55};
56
52217195
DV
57/*
58 * Optional properties
ac1bb36c 59 */
6a0d9528
LW
60/**
61 * drm_crtc_force_disable - Forcibly turn off a CRTC
62 * @crtc: CRTC to turn off
63 *
64 * Returns:
65 * Zero on success, error code on failure.
66 */
67int drm_crtc_force_disable(struct drm_crtc *crtc)
68{
69 struct drm_mode_set set = {
70 .crtc = crtc,
71 };
72
73 return drm_mode_set_config_internal(&set);
74}
75EXPORT_SYMBOL(drm_crtc_force_disable);
76
77/**
78 * drm_crtc_force_disable_all - Forcibly turn off all enabled CRTCs
79 * @dev: DRM device whose CRTCs to turn off
80 *
81 * Drivers may want to call this on unload to ensure that all displays are
82 * unlit and the GPU is in a consistent, low power state. Takes modeset locks.
83 *
84 * Returns:
85 * Zero on success, error code on failure.
86 */
87int drm_crtc_force_disable_all(struct drm_device *dev)
88{
89 struct drm_crtc *crtc;
90 int ret = 0;
91
92 drm_modeset_lock_all(dev);
93 drm_for_each_crtc(crtc, dev)
94 if (crtc->enabled) {
95 ret = drm_crtc_force_disable(crtc);
96 if (ret)
97 goto out;
98 }
99out:
100 drm_modeset_unlock_all(dev);
101 return ret;
102}
103EXPORT_SYMBOL(drm_crtc_force_disable_all);
104
51fd371b
RC
105DEFINE_WW_CLASS(crtc_ww_class);
106
fa3ab4c2
VS
107static unsigned int drm_num_crtcs(struct drm_device *dev)
108{
109 unsigned int num = 0;
110 struct drm_crtc *tmp;
111
112 drm_for_each_crtc(tmp, dev) {
113 num++;
114 }
115
116 return num;
117}
118
79190ea2
BG
119static int drm_crtc_register_all(struct drm_device *dev)
120{
121 struct drm_crtc *crtc;
122 int ret = 0;
123
124 drm_for_each_crtc(crtc, dev) {
9edbf1fa
TV
125 if (drm_debugfs_crtc_add(crtc))
126 DRM_ERROR("Failed to initialize debugfs entry for CRTC '%s'.\n",
127 crtc->name);
128
79190ea2
BG
129 if (crtc->funcs->late_register)
130 ret = crtc->funcs->late_register(crtc);
131 if (ret)
132 return ret;
133 }
134
135 return 0;
136}
137
138static void drm_crtc_unregister_all(struct drm_device *dev)
139{
140 struct drm_crtc *crtc;
141
142 drm_for_each_crtc(crtc, dev) {
143 if (crtc->funcs->early_unregister)
144 crtc->funcs->early_unregister(crtc);
9edbf1fa 145 drm_debugfs_crtc_remove(crtc);
79190ea2
BG
146 }
147}
148
9edbf1fa
TV
149static int drm_crtc_crc_init(struct drm_crtc *crtc)
150{
151#ifdef CONFIG_DEBUG_FS
152 spin_lock_init(&crtc->crc.lock);
153 init_waitqueue_head(&crtc->crc.wq);
154 crtc->crc.source = kstrdup("auto", GFP_KERNEL);
155 if (!crtc->crc.source)
156 return -ENOMEM;
157#endif
158 return 0;
159}
160
161static void drm_crtc_crc_fini(struct drm_crtc *crtc)
162{
163#ifdef CONFIG_DEBUG_FS
164 kfree(crtc->crc.source);
165#endif
166}
167
f453ba04 168/**
e13161af
MR
169 * drm_crtc_init_with_planes - Initialise a new CRTC object with
170 * specified primary and cursor planes.
f453ba04
DA
171 * @dev: DRM device
172 * @crtc: CRTC object to init
e13161af
MR
173 * @primary: Primary plane for CRTC
174 * @cursor: Cursor plane for CRTC
f453ba04 175 * @funcs: callbacks for the new CRTC
f9882876 176 * @name: printf style format string for the CRTC name, or NULL for default name
f453ba04 177 *
532b3671
DV
178 * Inits a new object created as base part of a driver crtc object. Drivers
179 * should use this function instead of drm_crtc_init(), which is only provided
180 * for backwards compatibility with drivers which do not yet support universal
181 * planes). For really simple hardware which has only 1 plane look at
182 * drm_simple_display_pipe_init() instead.
6bfc56aa 183 *
c8e32cc1 184 * Returns:
6bfc56aa 185 * Zero on success, error code on failure.
f453ba04 186 */
e13161af
MR
187int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
188 struct drm_plane *primary,
fc1d3e44 189 struct drm_plane *cursor,
f9882876
VS
190 const struct drm_crtc_funcs *funcs,
191 const char *name, ...)
f453ba04 192{
51fd371b 193 struct drm_mode_config *config = &dev->mode_config;
6bfc56aa
VS
194 int ret;
195
522cf91f
BG
196 WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY);
197 WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR);
198
f453ba04
DA
199 crtc->dev = dev;
200 crtc->funcs = funcs;
201
3b24f7d6
DV
202 INIT_LIST_HEAD(&crtc->commit_list);
203 spin_lock_init(&crtc->commit_lock);
204
51fd371b 205 drm_modeset_lock_init(&crtc->mutex);
6bfc56aa
VS
206 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
207 if (ret)
baf698b0 208 return ret;
f453ba04 209
fa3ab4c2
VS
210 if (name) {
211 va_list ap;
212
213 va_start(ap, name);
214 crtc->name = kvasprintf(GFP_KERNEL, name, ap);
215 va_end(ap);
216 } else {
217 crtc->name = kasprintf(GFP_KERNEL, "crtc-%d",
218 drm_num_crtcs(dev));
219 }
220 if (!crtc->name) {
7c8f6d25 221 drm_mode_object_unregister(dev, &crtc->base);
fa3ab4c2
VS
222 return -ENOMEM;
223 }
224
bffd9de0
PZ
225 crtc->base.properties = &crtc->properties;
226
51fd371b 227 list_add_tail(&crtc->head, &config->crtc_list);
490d3d1b 228 crtc->index = config->num_crtc++;
6bfc56aa 229
e13161af 230 crtc->primary = primary;
fc1d3e44 231 crtc->cursor = cursor;
e13161af
MR
232 if (primary)
233 primary->possible_crtcs = 1 << drm_crtc_index(crtc);
fc1d3e44
MR
234 if (cursor)
235 cursor->possible_crtcs = 1 << drm_crtc_index(crtc);
e13161af 236
9edbf1fa
TV
237 ret = drm_crtc_crc_init(crtc);
238 if (ret) {
239 drm_mode_object_unregister(dev, &crtc->base);
240 return ret;
241 }
242
eab3bbef
DV
243 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
244 drm_object_attach_property(&crtc->base, config->prop_active, 0);
955f3c33 245 drm_object_attach_property(&crtc->base, config->prop_mode_id, 0);
eab3bbef
DV
246 }
247
baf698b0 248 return 0;
f453ba04 249}
e13161af 250EXPORT_SYMBOL(drm_crtc_init_with_planes);
f453ba04
DA
251
252/**
ad6f5c34 253 * drm_crtc_cleanup - Clean up the core crtc usage
f453ba04
DA
254 * @crtc: CRTC to cleanup
255 *
ad6f5c34
VS
256 * This function cleans up @crtc and removes it from the DRM mode setting
257 * core. Note that the function does *not* free the crtc structure itself,
258 * this is the responsibility of the caller.
f453ba04
DA
259 */
260void drm_crtc_cleanup(struct drm_crtc *crtc)
261{
262 struct drm_device *dev = crtc->dev;
263
490d3d1b
CW
264 /* Note that the crtc_list is considered to be static; should we
265 * remove the drm_crtc at runtime we would have to decrement all
266 * the indices on the drm_crtc after us in the crtc_list.
267 */
268
9edbf1fa
TV
269 drm_crtc_crc_fini(crtc);
270
9e1c156f
SK
271 kfree(crtc->gamma_store);
272 crtc->gamma_store = NULL;
f453ba04 273
51fd371b
RC
274 drm_modeset_lock_fini(&crtc->mutex);
275
7c8f6d25 276 drm_mode_object_unregister(dev, &crtc->base);
f453ba04
DA
277 list_del(&crtc->head);
278 dev->mode_config.num_crtc--;
3009c037
TR
279
280 WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state);
281 if (crtc->state && crtc->funcs->atomic_destroy_state)
282 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
a18c0af1 283
fa3ab4c2
VS
284 kfree(crtc->name);
285
a18c0af1 286 memset(crtc, 0, sizeof(*crtc));
f453ba04
DA
287}
288EXPORT_SYMBOL(drm_crtc_cleanup);
289
79190ea2
BG
290int drm_modeset_register_all(struct drm_device *dev)
291{
292 int ret;
293
294 ret = drm_plane_register_all(dev);
295 if (ret)
296 goto err_plane;
297
298 ret = drm_crtc_register_all(dev);
299 if (ret)
300 goto err_crtc;
301
302 ret = drm_encoder_register_all(dev);
303 if (ret)
304 goto err_encoder;
305
306 ret = drm_connector_register_all(dev);
307 if (ret)
308 goto err_connector;
309
310 return 0;
311
312err_connector:
313 drm_encoder_unregister_all(dev);
314err_encoder:
315 drm_crtc_unregister_all(dev);
316err_crtc:
317 drm_plane_unregister_all(dev);
318err_plane:
319 return ret;
320}
321
322void drm_modeset_unregister_all(struct drm_device *dev)
323{
324 drm_connector_unregister_all(dev);
325 drm_encoder_unregister_all(dev);
326 drm_crtc_unregister_all(dev);
327 drm_plane_unregister_all(dev);
328}
329
6b4959f4 330static int drm_mode_create_standard_properties(struct drm_device *dev)
f453ba04 331{
356af0e1 332 struct drm_property *prop;
52217195 333 int ret;
f453ba04 334
52217195
DV
335 ret = drm_connector_create_standard_properties(dev);
336 if (ret)
337 return ret;
9922ab5a 338
6b4959f4 339 prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
9922ab5a
RC
340 "type", drm_plane_type_enum_list,
341 ARRAY_SIZE(drm_plane_type_enum_list));
6b4959f4
RC
342 if (!prop)
343 return -ENOMEM;
344 dev->mode_config.plane_type_property = prop;
345
346 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
347 "SRC_X", 0, UINT_MAX);
348 if (!prop)
349 return -ENOMEM;
350 dev->mode_config.prop_src_x = prop;
351
352 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
353 "SRC_Y", 0, UINT_MAX);
354 if (!prop)
355 return -ENOMEM;
356 dev->mode_config.prop_src_y = prop;
357
358 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
359 "SRC_W", 0, UINT_MAX);
360 if (!prop)
361 return -ENOMEM;
362 dev->mode_config.prop_src_w = prop;
363
364 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
365 "SRC_H", 0, UINT_MAX);
366 if (!prop)
367 return -ENOMEM;
368 dev->mode_config.prop_src_h = prop;
369
370 prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
371 "CRTC_X", INT_MIN, INT_MAX);
372 if (!prop)
373 return -ENOMEM;
374 dev->mode_config.prop_crtc_x = prop;
375
376 prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
377 "CRTC_Y", INT_MIN, INT_MAX);
378 if (!prop)
379 return -ENOMEM;
380 dev->mode_config.prop_crtc_y = prop;
381
382 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
383 "CRTC_W", 0, INT_MAX);
384 if (!prop)
385 return -ENOMEM;
386 dev->mode_config.prop_crtc_w = prop;
387
388 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
389 "CRTC_H", 0, INT_MAX);
390 if (!prop)
391 return -ENOMEM;
392 dev->mode_config.prop_crtc_h = prop;
393
394 prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
395 "FB_ID", DRM_MODE_OBJECT_FB);
396 if (!prop)
397 return -ENOMEM;
398 dev->mode_config.prop_fb_id = prop;
399
400 prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
401 "CRTC_ID", DRM_MODE_OBJECT_CRTC);
402 if (!prop)
403 return -ENOMEM;
404 dev->mode_config.prop_crtc_id = prop;
9922ab5a 405
eab3bbef
DV
406 prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
407 "ACTIVE");
408 if (!prop)
409 return -ENOMEM;
410 dev->mode_config.prop_active = prop;
411
955f3c33
DS
412 prop = drm_property_create(dev,
413 DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB,
414 "MODE_ID", 0);
415 if (!prop)
416 return -ENOMEM;
417 dev->mode_config.prop_mode_id = prop;
418
5488dc16
LL
419 prop = drm_property_create(dev,
420 DRM_MODE_PROP_BLOB,
421 "DEGAMMA_LUT", 0);
422 if (!prop)
423 return -ENOMEM;
424 dev->mode_config.degamma_lut_property = prop;
425
426 prop = drm_property_create_range(dev,
427 DRM_MODE_PROP_IMMUTABLE,
428 "DEGAMMA_LUT_SIZE", 0, UINT_MAX);
429 if (!prop)
430 return -ENOMEM;
431 dev->mode_config.degamma_lut_size_property = prop;
432
433 prop = drm_property_create(dev,
434 DRM_MODE_PROP_BLOB,
435 "CTM", 0);
436 if (!prop)
437 return -ENOMEM;
438 dev->mode_config.ctm_property = prop;
439
440 prop = drm_property_create(dev,
441 DRM_MODE_PROP_BLOB,
442 "GAMMA_LUT", 0);
443 if (!prop)
444 return -ENOMEM;
445 dev->mode_config.gamma_lut_property = prop;
446
447 prop = drm_property_create_range(dev,
448 DRM_MODE_PROP_IMMUTABLE,
449 "GAMMA_LUT_SIZE", 0, UINT_MAX);
450 if (!prop)
451 return -ENOMEM;
452 dev->mode_config.gamma_lut_size_property = prop;
453
9922ab5a
RC
454 return 0;
455}
456
f453ba04
DA
457/**
458 * drm_mode_getresources - get graphics configuration
065a50ed
DV
459 * @dev: drm device for the ioctl
460 * @data: data pointer for the ioctl
461 * @file_priv: drm file for the ioctl call
f453ba04 462 *
f453ba04
DA
463 * Construct a set of configuration description structures and return
464 * them to the user, including CRTC, connector and framebuffer configuration.
465 *
466 * Called by the user via ioctl.
467 *
c8e32cc1 468 * Returns:
1a498633 469 * Zero on success, negative errno on failure.
f453ba04
DA
470 */
471int drm_mode_getresources(struct drm_device *dev, void *data,
472 struct drm_file *file_priv)
473{
474 struct drm_mode_card_res *card_res = data;
475 struct list_head *lh;
476 struct drm_framebuffer *fb;
477 struct drm_connector *connector;
478 struct drm_crtc *crtc;
479 struct drm_encoder *encoder;
480 int ret = 0;
481 int connector_count = 0;
482 int crtc_count = 0;
483 int fb_count = 0;
484 int encoder_count = 0;
9c7060f7 485 int copied = 0;
f453ba04
DA
486 uint32_t __user *fb_id;
487 uint32_t __user *crtc_id;
488 uint32_t __user *connector_id;
489 uint32_t __user *encoder_id;
f453ba04 490
fb3b06c8
DA
491 if (!drm_core_check_feature(dev, DRIVER_MODESET))
492 return -EINVAL;
493
f453ba04 494
4b096ac1 495 mutex_lock(&file_priv->fbs_lock);
f453ba04
DA
496 /*
497 * For the non-control nodes we need to limit the list of resources
498 * by IDs in the group list for this node
499 */
500 list_for_each(lh, &file_priv->fbs)
501 fb_count++;
502
4b096ac1
DV
503 /* handle this in 4 parts */
504 /* FBs */
505 if (card_res->count_fbs >= fb_count) {
506 copied = 0;
507 fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
508 list_for_each_entry(fb, &file_priv->fbs, filp_head) {
509 if (put_user(fb->base.id, fb_id + copied)) {
510 mutex_unlock(&file_priv->fbs_lock);
511 return -EFAULT;
512 }
513 copied++;
514 }
515 }
516 card_res->count_fbs = fb_count;
517 mutex_unlock(&file_priv->fbs_lock);
518
fcf93f69
DV
519 /* mode_config.mutex protects the connector list against e.g. DP MST
520 * connector hot-adding. CRTC/Plane lists are invariant. */
521 mutex_lock(&dev->mode_config.mutex);
9c7060f7
DV
522 drm_for_each_crtc(crtc, dev)
523 crtc_count++;
f453ba04 524
9c7060f7
DV
525 drm_for_each_connector(connector, dev)
526 connector_count++;
f453ba04 527
9c7060f7
DV
528 drm_for_each_encoder(encoder, dev)
529 encoder_count++;
f453ba04
DA
530
531 card_res->max_height = dev->mode_config.max_height;
532 card_res->min_height = dev->mode_config.min_height;
533 card_res->max_width = dev->mode_config.max_width;
534 card_res->min_width = dev->mode_config.min_width;
535
f453ba04
DA
536 /* CRTCs */
537 if (card_res->count_crtcs >= crtc_count) {
538 copied = 0;
539 crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
9c7060f7 540 drm_for_each_crtc(crtc, dev) {
9c7060f7
DV
541 if (put_user(crtc->base.id, crtc_id + copied)) {
542 ret = -EFAULT;
543 goto out;
f453ba04 544 }
9c7060f7 545 copied++;
f453ba04
DA
546 }
547 }
548 card_res->count_crtcs = crtc_count;
549
550 /* Encoders */
551 if (card_res->count_encoders >= encoder_count) {
552 copied = 0;
553 encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
9c7060f7 554 drm_for_each_encoder(encoder, dev) {
9c7060f7
DV
555 if (put_user(encoder->base.id, encoder_id +
556 copied)) {
557 ret = -EFAULT;
558 goto out;
f453ba04 559 }
9c7060f7 560 copied++;
f453ba04
DA
561 }
562 }
563 card_res->count_encoders = encoder_count;
564
565 /* Connectors */
566 if (card_res->count_connectors >= connector_count) {
567 copied = 0;
568 connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
9c7060f7 569 drm_for_each_connector(connector, dev) {
9c7060f7
DV
570 if (put_user(connector->base.id,
571 connector_id + copied)) {
572 ret = -EFAULT;
573 goto out;
f453ba04 574 }
9c7060f7 575 copied++;
f453ba04
DA
576 }
577 }
578 card_res->count_connectors = connector_count;
579
f453ba04 580out:
fcf93f69 581 mutex_unlock(&dev->mode_config.mutex);
f453ba04
DA
582 return ret;
583}
584
585/**
586 * drm_mode_getcrtc - get CRTC configuration
065a50ed
DV
587 * @dev: drm device for the ioctl
588 * @data: data pointer for the ioctl
589 * @file_priv: drm file for the ioctl call
f453ba04 590 *
f453ba04
DA
591 * Construct a CRTC configuration structure to return to the user.
592 *
593 * Called by the user via ioctl.
594 *
c8e32cc1 595 * Returns:
1a498633 596 * Zero on success, negative errno on failure.
f453ba04
DA
597 */
598int drm_mode_getcrtc(struct drm_device *dev,
599 void *data, struct drm_file *file_priv)
600{
601 struct drm_mode_crtc *crtc_resp = data;
602 struct drm_crtc *crtc;
f453ba04 603
fb3b06c8
DA
604 if (!drm_core_check_feature(dev, DRIVER_MODESET))
605 return -EINVAL;
606
a2b34e22 607 crtc = drm_crtc_find(dev, crtc_resp->crtc_id);
fcf93f69
DV
608 if (!crtc)
609 return -ENOENT;
f453ba04 610
fcf93f69 611 drm_modeset_lock_crtc(crtc, crtc->primary);
f453ba04 612 crtc_resp->gamma_size = crtc->gamma_size;
f4510a27
MR
613 if (crtc->primary->fb)
614 crtc_resp->fb_id = crtc->primary->fb->base.id;
f453ba04
DA
615 else
616 crtc_resp->fb_id = 0;
617
31c946e8
DV
618 if (crtc->state) {
619 crtc_resp->x = crtc->primary->state->src_x >> 16;
620 crtc_resp->y = crtc->primary->state->src_y >> 16;
621 if (crtc->state->enable) {
934a8a89 622 drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
31c946e8 623 crtc_resp->mode_valid = 1;
f453ba04 624
31c946e8
DV
625 } else {
626 crtc_resp->mode_valid = 0;
627 }
f453ba04 628 } else {
31c946e8
DV
629 crtc_resp->x = crtc->x;
630 crtc_resp->y = crtc->y;
631 if (crtc->enabled) {
934a8a89 632 drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode);
31c946e8
DV
633 crtc_resp->mode_valid = 1;
634
635 } else {
636 crtc_resp->mode_valid = 0;
637 }
f453ba04 638 }
fcf93f69 639 drm_modeset_unlock_crtc(crtc);
f453ba04 640
baf698b0 641 return 0;
f453ba04
DA
642}
643
2d13b679
DV
644/**
645 * drm_mode_set_config_internal - helper to call ->set_config
646 * @set: modeset config to set
647 *
648 * This is a little helper to wrap internal calls to the ->set_config driver
649 * interface. The only thing it adds is correct refcounting dance.
4dfd909f 650 *
c8e32cc1 651 * Returns:
1a498633 652 * Zero on success, negative errno on failure.
2d13b679
DV
653 */
654int drm_mode_set_config_internal(struct drm_mode_set *set)
655{
656 struct drm_crtc *crtc = set->crtc;
5cef29aa
DV
657 struct drm_framebuffer *fb;
658 struct drm_crtc *tmp;
b0d12325
DV
659 int ret;
660
5cef29aa
DV
661 /*
662 * NOTE: ->set_config can also disable other crtcs (if we steal all
663 * connectors from it), hence we need to refcount the fbs across all
664 * crtcs. Atomic modeset will have saner semantics ...
665 */
e4f62546 666 drm_for_each_crtc(tmp, crtc->dev)
3d30a59b 667 tmp->primary->old_fb = tmp->primary->fb;
5cef29aa 668
b0d12325 669 fb = set->fb;
2d13b679 670
b0d12325
DV
671 ret = crtc->funcs->set_config(set);
672 if (ret == 0) {
e13161af 673 crtc->primary->crtc = crtc;
0fe27f06 674 crtc->primary->fb = fb;
5cef29aa 675 }
cc85e121 676
e4f62546 677 drm_for_each_crtc(tmp, crtc->dev) {
f4510a27
MR
678 if (tmp->primary->fb)
679 drm_framebuffer_reference(tmp->primary->fb);
3d30a59b
DV
680 if (tmp->primary->old_fb)
681 drm_framebuffer_unreference(tmp->primary->old_fb);
682 tmp->primary->old_fb = NULL;
b0d12325
DV
683 }
684
685 return ret;
2d13b679
DV
686}
687EXPORT_SYMBOL(drm_mode_set_config_internal);
688
ecb7e16b
GP
689/**
690 * drm_crtc_get_hv_timing - Fetches hdisplay/vdisplay for given mode
691 * @mode: mode to query
692 * @hdisplay: hdisplay value to fill in
693 * @vdisplay: vdisplay value to fill in
694 *
695 * The vdisplay value will be doubled if the specified mode is a stereo mode of
696 * the appropriate layout.
697 */
698void drm_crtc_get_hv_timing(const struct drm_display_mode *mode,
699 int *hdisplay, int *vdisplay)
700{
701 struct drm_display_mode adjusted;
702
703 drm_mode_copy(&adjusted, mode);
704 drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY);
705 *hdisplay = adjusted.crtc_hdisplay;
706 *vdisplay = adjusted.crtc_vdisplay;
707}
708EXPORT_SYMBOL(drm_crtc_get_hv_timing);
709
af93629d
MR
710/**
711 * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the
712 * CRTC viewport
713 * @crtc: CRTC that framebuffer will be displayed on
714 * @x: x panning
715 * @y: y panning
716 * @mode: mode that framebuffer will be displayed under
717 * @fb: framebuffer to check size of
c11e9283 718 */
af93629d
MR
719int drm_crtc_check_viewport(const struct drm_crtc *crtc,
720 int x, int y,
721 const struct drm_display_mode *mode,
722 const struct drm_framebuffer *fb)
c11e9283
DL
723
724{
725 int hdisplay, vdisplay;
726
ecb7e16b 727 drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay);
a0c1bbb0 728
33e0be63 729 if (crtc->state &&
31ad61e4
JL
730 crtc->primary->state->rotation & (DRM_ROTATE_90 |
731 DRM_ROTATE_270))
c11e9283
DL
732 swap(hdisplay, vdisplay);
733
43968d7b
DV
734 return drm_framebuffer_check_src_coords(x << 16, y << 16,
735 hdisplay << 16, vdisplay << 16,
736 fb);
c11e9283 737}
af93629d 738EXPORT_SYMBOL(drm_crtc_check_viewport);
c11e9283 739
f453ba04
DA
740/**
741 * drm_mode_setcrtc - set CRTC configuration
065a50ed
DV
742 * @dev: drm device for the ioctl
743 * @data: data pointer for the ioctl
744 * @file_priv: drm file for the ioctl call
f453ba04 745 *
f453ba04
DA
746 * Build a new CRTC configuration based on user request.
747 *
748 * Called by the user via ioctl.
749 *
c8e32cc1 750 * Returns:
1a498633 751 * Zero on success, negative errno on failure.
f453ba04
DA
752 */
753int drm_mode_setcrtc(struct drm_device *dev, void *data,
754 struct drm_file *file_priv)
755{
756 struct drm_mode_config *config = &dev->mode_config;
757 struct drm_mode_crtc *crtc_req = data;
6653cc8d 758 struct drm_crtc *crtc;
f453ba04
DA
759 struct drm_connector **connector_set = NULL, *connector;
760 struct drm_framebuffer *fb = NULL;
761 struct drm_display_mode *mode = NULL;
762 struct drm_mode_set set;
763 uint32_t __user *set_connectors_ptr;
4a1b0714 764 int ret;
f453ba04
DA
765 int i;
766
fb3b06c8
DA
767 if (!drm_core_check_feature(dev, DRIVER_MODESET))
768 return -EINVAL;
769
01447e9f
ZJ
770 /*
771 * Universal plane src offsets are only 16.16, prevent havoc for
772 * drivers using universal plane code internally.
773 */
774 if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
1d97e915
VS
775 return -ERANGE;
776
84849903 777 drm_modeset_lock_all(dev);
a2b34e22
RC
778 crtc = drm_crtc_find(dev, crtc_req->crtc_id);
779 if (!crtc) {
58367ed6 780 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
f27657f2 781 ret = -ENOENT;
f453ba04
DA
782 goto out;
783 }
fa3ab4c2 784 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
f453ba04
DA
785
786 if (crtc_req->mode_valid) {
787 /* If we have a mode we need a framebuffer. */
788 /* If we pass -1, set the mode with the currently bound fb */
789 if (crtc_req->fb_id == -1) {
f4510a27 790 if (!crtc->primary->fb) {
6653cc8d
VS
791 DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
792 ret = -EINVAL;
793 goto out;
f453ba04 794 }
f4510a27 795 fb = crtc->primary->fb;
b0d12325
DV
796 /* Make refcounting symmetric with the lookup path. */
797 drm_framebuffer_reference(fb);
f453ba04 798 } else {
786b99ed
DV
799 fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
800 if (!fb) {
58367ed6
ZY
801 DRM_DEBUG_KMS("Unknown FB ID%d\n",
802 crtc_req->fb_id);
37c4e705 803 ret = -ENOENT;
f453ba04
DA
804 goto out;
805 }
f453ba04
DA
806 }
807
808 mode = drm_mode_create(dev);
ee34ab5b
VS
809 if (!mode) {
810 ret = -ENOMEM;
811 goto out;
812 }
813
934a8a89 814 ret = drm_mode_convert_umode(mode, &crtc_req->mode);
90367bf6
VS
815 if (ret) {
816 DRM_DEBUG_KMS("Invalid mode\n");
817 goto out;
818 }
819
7eb5f302
LP
820 /*
821 * Check whether the primary plane supports the fb pixel format.
822 * Drivers not implementing the universal planes API use a
823 * default formats list provided by the DRM core which doesn't
824 * match real hardware capabilities. Skip the check in that
825 * case.
826 */
827 if (!crtc->primary->format_default) {
828 ret = drm_plane_check_pixel_format(crtc->primary,
829 fb->pixel_format);
830 if (ret) {
d3828147 831 char *format_name = drm_get_format_name(fb->pixel_format);
90844f00
EE
832 DRM_DEBUG_KMS("Invalid pixel format %s\n", format_name);
833 kfree(format_name);
7eb5f302
LP
834 goto out;
835 }
836 }
837
c11e9283
DL
838 ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
839 mode, fb);
840 if (ret)
5f61bb42 841 goto out;
c11e9283 842
f453ba04
DA
843 }
844
845 if (crtc_req->count_connectors == 0 && mode) {
58367ed6 846 DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
f453ba04
DA
847 ret = -EINVAL;
848 goto out;
849 }
850
7781de74 851 if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
58367ed6 852 DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
f453ba04
DA
853 crtc_req->count_connectors);
854 ret = -EINVAL;
855 goto out;
856 }
857
858 if (crtc_req->count_connectors > 0) {
859 u32 out_id;
860
861 /* Avoid unbounded kernel memory allocation */
862 if (crtc_req->count_connectors > config->num_connector) {
863 ret = -EINVAL;
864 goto out;
865 }
866
2f6c5389
TR
867 connector_set = kmalloc_array(crtc_req->count_connectors,
868 sizeof(struct drm_connector *),
869 GFP_KERNEL);
f453ba04
DA
870 if (!connector_set) {
871 ret = -ENOMEM;
872 goto out;
873 }
874
875 for (i = 0; i < crtc_req->count_connectors; i++) {
b164d31f 876 connector_set[i] = NULL;
81f6c7f8 877 set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
f453ba04
DA
878 if (get_user(out_id, &set_connectors_ptr[i])) {
879 ret = -EFAULT;
880 goto out;
881 }
882
b164d31f 883 connector = drm_connector_lookup(dev, out_id);
a2b34e22 884 if (!connector) {
58367ed6
ZY
885 DRM_DEBUG_KMS("Connector id %d unknown\n",
886 out_id);
f27657f2 887 ret = -ENOENT;
f453ba04
DA
888 goto out;
889 }
9440106b
JG
890 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
891 connector->base.id,
25933820 892 connector->name);
f453ba04
DA
893
894 connector_set[i] = connector;
895 }
896 }
897
898 set.crtc = crtc;
899 set.x = crtc_req->x;
900 set.y = crtc_req->y;
901 set.mode = mode;
902 set.connectors = connector_set;
903 set.num_connectors = crtc_req->count_connectors;
5ef5f72f 904 set.fb = fb;
2d13b679 905 ret = drm_mode_set_config_internal(&set);
f453ba04
DA
906
907out:
b0d12325
DV
908 if (fb)
909 drm_framebuffer_unreference(fb);
910
b164d31f
DA
911 if (connector_set) {
912 for (i = 0; i < crtc_req->count_connectors; i++) {
913 if (connector_set[i])
914 drm_connector_unreference(connector_set[i]);
915 }
916 }
f453ba04 917 kfree(connector_set);
ee34ab5b 918 drm_mode_destroy(dev, mode);
84849903 919 drm_modeset_unlock_all(dev);
f453ba04
DA
920 return ret;
921}
922
949619f3
DV
923int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
924 struct drm_property *property,
925 uint64_t value)
4a67d391 926{
bffd9de0
PZ
927 int ret = -EINVAL;
928 struct drm_crtc *crtc = obj_to_crtc(obj);
4a67d391 929
bffd9de0
PZ
930 if (crtc->funcs->set_property)
931 ret = crtc->funcs->set_property(crtc, property, value);
932 if (!ret)
933 drm_object_property_set_value(obj, property, value);
4a67d391 934
bffd9de0 935 return ret;
4a67d391 936}
4a67d391 937
c8e32cc1
DV
938/**
939 * drm_mode_config_reset - call ->reset callbacks
940 * @dev: drm device
941 *
942 * This functions calls all the crtc's, encoder's and connector's ->reset
943 * callback. Drivers can use this in e.g. their driver load or resume code to
944 * reset hardware and software state.
945 */
eb033556
CW
946void drm_mode_config_reset(struct drm_device *dev)
947{
948 struct drm_crtc *crtc;
2a0d7cfd 949 struct drm_plane *plane;
eb033556
CW
950 struct drm_encoder *encoder;
951 struct drm_connector *connector;
952
e4f62546 953 drm_for_each_plane(plane, dev)
2a0d7cfd
DV
954 if (plane->funcs->reset)
955 plane->funcs->reset(plane);
956
e4f62546 957 drm_for_each_crtc(crtc, dev)
eb033556
CW
958 if (crtc->funcs->reset)
959 crtc->funcs->reset(crtc);
960
e4f62546 961 drm_for_each_encoder(encoder, dev)
eb033556
CW
962 if (encoder->funcs->reset)
963 encoder->funcs->reset(encoder);
964
f8c2ba31 965 mutex_lock(&dev->mode_config.mutex);
4eebf60b 966 drm_for_each_connector(connector, dev)
eb033556
CW
967 if (connector->funcs->reset)
968 connector->funcs->reset(connector);
f8c2ba31 969 mutex_unlock(&dev->mode_config.mutex);
eb033556
CW
970}
971EXPORT_SYMBOL(drm_mode_config_reset);
ff72145b 972
c8e32cc1
DV
973/**
974 * drm_mode_create_dumb_ioctl - create a dumb backing storage buffer
975 * @dev: DRM device
976 * @data: ioctl data
977 * @file_priv: DRM file info
978 *
979 * This creates a new dumb buffer in the driver's backing storage manager (GEM,
980 * TTM or something else entirely) and returns the resulting buffer handle. This
981 * handle can then be wrapped up into a framebuffer modeset object.
982 *
983 * Note that userspace is not allowed to use such objects for render
984 * acceleration - drivers must create their own private ioctls for such a use
985 * case.
986 *
987 * Called by the user via ioctl.
988 *
989 * Returns:
1a498633 990 * Zero on success, negative errno on failure.
c8e32cc1 991 */
ff72145b
DA
992int drm_mode_create_dumb_ioctl(struct drm_device *dev,
993 void *data, struct drm_file *file_priv)
994{
995 struct drm_mode_create_dumb *args = data;
b28cd41f 996 u32 cpp, stride, size;
ff72145b
DA
997
998 if (!dev->driver->dumb_create)
999 return -ENOSYS;
b28cd41f
DH
1000 if (!args->width || !args->height || !args->bpp)
1001 return -EINVAL;
1002
1003 /* overflow checks for 32bit size calculations */
00e72089 1004 /* NOTE: DIV_ROUND_UP() can overflow */
b28cd41f 1005 cpp = DIV_ROUND_UP(args->bpp, 8);
00e72089 1006 if (!cpp || cpp > 0xffffffffU / args->width)
b28cd41f
DH
1007 return -EINVAL;
1008 stride = cpp * args->width;
1009 if (args->height > 0xffffffffU / stride)
1010 return -EINVAL;
1011
1012 /* test for wrap-around */
1013 size = args->height * stride;
1014 if (PAGE_ALIGN(size) == 0)
1015 return -EINVAL;
1016
f6085952
TR
1017 /*
1018 * handle, pitch and size are output parameters. Zero them out to
1019 * prevent drivers from accidentally using uninitialized data. Since
1020 * not all existing userspace is clearing these fields properly we
1021 * cannot reject IOCTL with garbage in them.
1022 */
1023 args->handle = 0;
1024 args->pitch = 0;
1025 args->size = 0;
1026
ff72145b
DA
1027 return dev->driver->dumb_create(file_priv, dev, args);
1028}
1029
c8e32cc1
DV
1030/**
1031 * drm_mode_mmap_dumb_ioctl - create an mmap offset for a dumb backing storage buffer
1032 * @dev: DRM device
1033 * @data: ioctl data
1034 * @file_priv: DRM file info
1035 *
1036 * Allocate an offset in the drm device node's address space to be able to
1037 * memory map a dumb buffer.
1038 *
1039 * Called by the user via ioctl.
1040 *
1041 * Returns:
1a498633 1042 * Zero on success, negative errno on failure.
c8e32cc1 1043 */
ff72145b
DA
1044int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
1045 void *data, struct drm_file *file_priv)
1046{
1047 struct drm_mode_map_dumb *args = data;
1048
1049 /* call driver ioctl to get mmap offset */
1050 if (!dev->driver->dumb_map_offset)
1051 return -ENOSYS;
1052
1053 return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
1054}
1055
c8e32cc1
DV
1056/**
1057 * drm_mode_destroy_dumb_ioctl - destroy a dumb backing strage buffer
1058 * @dev: DRM device
1059 * @data: ioctl data
1060 * @file_priv: DRM file info
1061 *
1062 * This destroys the userspace handle for the given dumb backing storage buffer.
1063 * Since buffer objects must be reference counted in the kernel a buffer object
1064 * won't be immediately freed if a framebuffer modeset object still uses it.
1065 *
1066 * Called by the user via ioctl.
1067 *
1068 * Returns:
1a498633 1069 * Zero on success, negative errno on failure.
c8e32cc1 1070 */
ff72145b
DA
1071int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
1072 void *data, struct drm_file *file_priv)
1073{
1074 struct drm_mode_destroy_dumb *args = data;
1075
1076 if (!dev->driver->dumb_destroy)
1077 return -ENOSYS;
1078
1079 return dev->driver->dumb_destroy(file_priv, dev, args->handle);
1080}
248dbc23 1081
87d24fc3
LP
1082/**
1083 * drm_mode_config_init - initialize DRM mode_configuration structure
1084 * @dev: DRM device
1085 *
1086 * Initialize @dev's mode_config structure, used for tracking the graphics
1087 * configuration of @dev.
1088 *
1089 * Since this initializes the modeset locks, no locking is possible. Which is no
1090 * problem, since this should happen single threaded at init time. It is the
1091 * driver's problem to ensure this guarantee.
1092 *
1093 */
1094void drm_mode_config_init(struct drm_device *dev)
1095{
1096 mutex_init(&dev->mode_config.mutex);
51fd371b 1097 drm_modeset_lock_init(&dev->mode_config.connection_mutex);
87d24fc3
LP
1098 mutex_init(&dev->mode_config.idr_mutex);
1099 mutex_init(&dev->mode_config.fb_lock);
8fb6e7a5 1100 mutex_init(&dev->mode_config.blob_lock);
87d24fc3
LP
1101 INIT_LIST_HEAD(&dev->mode_config.fb_list);
1102 INIT_LIST_HEAD(&dev->mode_config.crtc_list);
1103 INIT_LIST_HEAD(&dev->mode_config.connector_list);
1104 INIT_LIST_HEAD(&dev->mode_config.encoder_list);
1105 INIT_LIST_HEAD(&dev->mode_config.property_list);
1106 INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
1107 INIT_LIST_HEAD(&dev->mode_config.plane_list);
1108 idr_init(&dev->mode_config.crtc_idr);
138f9ebb 1109 idr_init(&dev->mode_config.tile_idr);
5fff80bb 1110 ida_init(&dev->mode_config.connector_ida);
87d24fc3
LP
1111
1112 drm_modeset_lock_all(dev);
6b4959f4 1113 drm_mode_create_standard_properties(dev);
87d24fc3
LP
1114 drm_modeset_unlock_all(dev);
1115
1116 /* Just to be sure */
1117 dev->mode_config.num_fb = 0;
1118 dev->mode_config.num_connector = 0;
1119 dev->mode_config.num_crtc = 0;
1120 dev->mode_config.num_encoder = 0;
e27dde3e
MR
1121 dev->mode_config.num_overlay_plane = 0;
1122 dev->mode_config.num_total_plane = 0;
87d24fc3
LP
1123}
1124EXPORT_SYMBOL(drm_mode_config_init);
1125
1126/**
1127 * drm_mode_config_cleanup - free up DRM mode_config info
1128 * @dev: DRM device
1129 *
1130 * Free up all the connectors and CRTCs associated with this DRM device, then
1131 * free up the framebuffers and associated buffer objects.
1132 *
1133 * Note that since this /should/ happen single-threaded at driver/device
1134 * teardown time, no locking is required. It's the driver's job to ensure that
1135 * this guarantee actually holds true.
1136 *
1137 * FIXME: cleanup any dangling user buffer objects too
1138 */
1139void drm_mode_config_cleanup(struct drm_device *dev)
1140{
1141 struct drm_connector *connector, *ot;
1142 struct drm_crtc *crtc, *ct;
1143 struct drm_encoder *encoder, *enct;
1144 struct drm_framebuffer *fb, *fbt;
1145 struct drm_property *property, *pt;
1146 struct drm_property_blob *blob, *bt;
1147 struct drm_plane *plane, *plt;
1148
1149 list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
1150 head) {
1151 encoder->funcs->destroy(encoder);
1152 }
1153
1154 list_for_each_entry_safe(connector, ot,
1155 &dev->mode_config.connector_list, head) {
1156 connector->funcs->destroy(connector);
1157 }
1158
1159 list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
1160 head) {
1161 drm_property_destroy(dev, property);
1162 }
1163
f35034f8
ML
1164 list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
1165 head) {
1166 plane->funcs->destroy(plane);
1167 }
1168
1169 list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
1170 crtc->funcs->destroy(crtc);
1171 }
1172
87d24fc3 1173 list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
e2f5d2ea 1174 head_global) {
6bcacf51 1175 drm_property_unreference_blob(blob);
87d24fc3
LP
1176 }
1177
1178 /*
1179 * Single-threaded teardown context, so it's not required to grab the
1180 * fb_lock to protect against concurrent fb_list access. Contrary, it
1181 * would actually deadlock with the drm_framebuffer_cleanup function.
1182 *
1183 * Also, if there are any framebuffers left, that's a driver leak now,
1184 * so politely WARN about this.
1185 */
1186 WARN_ON(!list_empty(&dev->mode_config.fb_list));
1187 list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
d0f37cf6 1188 drm_framebuffer_free(&fb->base.refcount);
87d24fc3
LP
1189 }
1190
5fff80bb 1191 ida_destroy(&dev->mode_config.connector_ida);
138f9ebb 1192 idr_destroy(&dev->mode_config.tile_idr);
87d24fc3 1193 idr_destroy(&dev->mode_config.crtc_idr);
51fd371b 1194 drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
87d24fc3
LP
1195}
1196EXPORT_SYMBOL(drm_mode_config_cleanup);
c1df5f3c 1197
138f9ebb
DA
1198/**
1199 * DOC: Tile group
1200 *
1201 * Tile groups are used to represent tiled monitors with a unique
1202 * integer identifier. Tiled monitors using DisplayID v1.3 have
1203 * a unique 8-byte handle, we store this in a tile group, so we
1204 * have a common identifier for all tiles in a monitor group.
1205 */
1206static void drm_tile_group_free(struct kref *kref)
1207{
1208 struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
1209 struct drm_device *dev = tg->dev;
1210 mutex_lock(&dev->mode_config.idr_mutex);
1211 idr_remove(&dev->mode_config.tile_idr, tg->id);
1212 mutex_unlock(&dev->mode_config.idr_mutex);
1213 kfree(tg);
1214}
1215
1216/**
1217 * drm_mode_put_tile_group - drop a reference to a tile group.
1218 * @dev: DRM device
1219 * @tg: tile group to drop reference to.
1220 *
1221 * drop reference to tile group and free if 0.
1222 */
1223void drm_mode_put_tile_group(struct drm_device *dev,
1224 struct drm_tile_group *tg)
1225{
1226 kref_put(&tg->refcount, drm_tile_group_free);
1227}
1228
1229/**
1230 * drm_mode_get_tile_group - get a reference to an existing tile group
1231 * @dev: DRM device
1232 * @topology: 8-bytes unique per monitor.
1233 *
1234 * Use the unique bytes to get a reference to an existing tile group.
1235 *
1236 * RETURNS:
1237 * tile group or NULL if not found.
1238 */
1239struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
1240 char topology[8])
1241{
1242 struct drm_tile_group *tg;
1243 int id;
1244 mutex_lock(&dev->mode_config.idr_mutex);
1245 idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
1246 if (!memcmp(tg->group_data, topology, 8)) {
1247 if (!kref_get_unless_zero(&tg->refcount))
1248 tg = NULL;
1249 mutex_unlock(&dev->mode_config.idr_mutex);
1250 return tg;
1251 }
1252 }
1253 mutex_unlock(&dev->mode_config.idr_mutex);
1254 return NULL;
1255}
81ddd1bc 1256EXPORT_SYMBOL(drm_mode_get_tile_group);
138f9ebb
DA
1257
1258/**
1259 * drm_mode_create_tile_group - create a tile group from a displayid description
1260 * @dev: DRM device
1261 * @topology: 8-bytes unique per monitor.
1262 *
1263 * Create a tile group for the unique monitor, and get a unique
1264 * identifier for the tile group.
1265 *
1266 * RETURNS:
1267 * new tile group or error.
1268 */
1269struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
1270 char topology[8])
1271{
1272 struct drm_tile_group *tg;
1273 int ret;
1274
1275 tg = kzalloc(sizeof(*tg), GFP_KERNEL);
1276 if (!tg)
1277 return ERR_PTR(-ENOMEM);
1278
1279 kref_init(&tg->refcount);
1280 memcpy(tg->group_data, topology, 8);
1281 tg->dev = dev;
1282
1283 mutex_lock(&dev->mode_config.idr_mutex);
1284 ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL);
1285 if (ret >= 0) {
1286 tg->id = ret;
1287 } else {
1288 kfree(tg);
1289 tg = ERR_PTR(ret);
1290 }
1291
1292 mutex_unlock(&dev->mode_config.idr_mutex);
1293 return tg;
1294}
81ddd1bc 1295EXPORT_SYMBOL(drm_mode_create_tile_group);