Line data Source code
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 : */
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: overview
57 : *
58 : * A CRTC represents the overall display pipeline. It receives pixel data from
59 : * &drm_plane and blends them together. The &drm_display_mode is also attached
60 : * to the CRTC, specifying display timings. On the output side the data is fed
61 : * to one or more &drm_encoder, which are then each connected to one
62 : * &drm_connector.
63 : *
64 : * To create a CRTC, a KMS drivers allocates and zeroes an instances of
65 : * &struct drm_crtc (possibly as part of a larger structure) and registers it
66 : * with a call to drm_crtc_init_with_planes().
67 : *
68 : * The CRTC is also the entry point for legacy modeset operations, see
69 : * &drm_crtc_funcs.set_config, legacy plane operations, see
70 : * &drm_crtc_funcs.page_flip and &drm_crtc_funcs.cursor_set2, and other legacy
71 : * operations like &drm_crtc_funcs.gamma_set. For atomic drivers all these
72 : * features are controlled through &drm_property and
73 : * &drm_mode_config_funcs.atomic_check.
74 : */
75 :
76 : /**
77 : * drm_crtc_from_index - find the registered CRTC at an index
78 : * @dev: DRM device
79 : * @idx: index of registered CRTC to find for
80 : *
81 : * Given a CRTC index, return the registered CRTC from DRM device's
82 : * 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 or
84 : * &drm_driver.disable_vblank), since that still deals with indices instead
85 : * of pointers to &struct drm_crtc."
86 : */
87 0 : struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx)
88 : {
89 : struct drm_crtc *crtc;
90 :
91 0 : drm_for_each_crtc(crtc, dev)
92 0 : if (idx == crtc->index)
93 : return crtc;
94 :
95 : return NULL;
96 : }
97 : EXPORT_SYMBOL(drm_crtc_from_index);
98 :
99 0 : int drm_crtc_force_disable(struct drm_crtc *crtc)
100 : {
101 0 : struct drm_mode_set set = {
102 : .crtc = crtc,
103 : };
104 :
105 0 : WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
106 :
107 0 : return drm_mode_set_config_internal(&set);
108 : }
109 :
110 : static unsigned int drm_num_crtcs(struct drm_device *dev)
111 : {
112 0 : unsigned int num = 0;
113 : struct drm_crtc *tmp;
114 :
115 0 : drm_for_each_crtc(tmp, dev) {
116 0 : num++;
117 : }
118 :
119 : return num;
120 : }
121 :
122 0 : int drm_crtc_register_all(struct drm_device *dev)
123 : {
124 : struct drm_crtc *crtc;
125 0 : int ret = 0;
126 :
127 0 : drm_for_each_crtc(crtc, dev) {
128 0 : drm_debugfs_crtc_add(crtc);
129 :
130 0 : if (crtc->funcs->late_register)
131 0 : ret = crtc->funcs->late_register(crtc);
132 0 : if (ret)
133 : return ret;
134 : }
135 :
136 : return 0;
137 : }
138 :
139 0 : void drm_crtc_unregister_all(struct drm_device *dev)
140 : {
141 : struct drm_crtc *crtc;
142 :
143 0 : drm_for_each_crtc(crtc, dev) {
144 0 : if (crtc->funcs->early_unregister)
145 0 : crtc->funcs->early_unregister(crtc);
146 0 : drm_debugfs_crtc_remove(crtc);
147 : }
148 0 : }
149 :
150 : static int drm_crtc_crc_init(struct drm_crtc *crtc)
151 : {
152 : #ifdef CONFIG_DEBUG_FS
153 : spin_lock_init(&crtc->crc.lock);
154 : init_waitqueue_head(&crtc->crc.wq);
155 : crtc->crc.source = kstrdup("auto", GFP_KERNEL);
156 : if (!crtc->crc.source)
157 : return -ENOMEM;
158 : #endif
159 : return 0;
160 : }
161 :
162 : static void drm_crtc_crc_fini(struct drm_crtc *crtc)
163 : {
164 : #ifdef CONFIG_DEBUG_FS
165 : kfree(crtc->crc.source);
166 : #endif
167 : }
168 :
169 : static const struct dma_fence_ops drm_crtc_fence_ops;
170 :
171 0 : static struct drm_crtc *fence_to_crtc(struct dma_fence *fence)
172 : {
173 0 : BUG_ON(fence->ops != &drm_crtc_fence_ops);
174 0 : return container_of(fence->lock, struct drm_crtc, fence_lock);
175 : }
176 :
177 0 : static const char *drm_crtc_fence_get_driver_name(struct dma_fence *fence)
178 : {
179 0 : struct drm_crtc *crtc = fence_to_crtc(fence);
180 :
181 0 : return crtc->dev->driver->name;
182 : }
183 :
184 0 : static const char *drm_crtc_fence_get_timeline_name(struct dma_fence *fence)
185 : {
186 0 : struct drm_crtc *crtc = fence_to_crtc(fence);
187 :
188 0 : return crtc->timeline_name;
189 : }
190 :
191 : static const struct dma_fence_ops drm_crtc_fence_ops = {
192 : .get_driver_name = drm_crtc_fence_get_driver_name,
193 : .get_timeline_name = drm_crtc_fence_get_timeline_name,
194 : };
195 :
196 0 : struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc)
197 : {
198 : struct dma_fence *fence;
199 :
200 0 : fence = kzalloc(sizeof(*fence), GFP_KERNEL);
201 0 : if (!fence)
202 : return NULL;
203 :
204 0 : dma_fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock,
205 0 : crtc->fence_context, ++crtc->fence_seqno);
206 :
207 0 : return fence;
208 : }
209 :
210 : /**
211 : * DOC: standard CRTC properties
212 : *
213 : * DRM CRTCs have a few standardized properties:
214 : *
215 : * ACTIVE:
216 : * Atomic property for setting the power state of the CRTC. When set to 1
217 : * the CRTC will actively display content. When set to 0 the CRTC will be
218 : * powered off. There is no expectation that user-space will reset CRTC
219 : * resources like the mode and planes when setting ACTIVE to 0.
220 : *
221 : * User-space can rely on an ACTIVE change to 1 to never fail an atomic
222 : * test as long as no other property has changed. If a change to ACTIVE
223 : * fails an atomic test, this is a driver bug. For this reason setting
224 : * ACTIVE to 0 must not release internal resources (like reserved memory
225 : * bandwidth or clock generators).
226 : *
227 : * Note that the legacy DPMS property on connectors is internally routed
228 : * to control this property for atomic drivers.
229 : * MODE_ID:
230 : * Atomic property for setting the CRTC display timings. The value is the
231 : * ID of a blob containing the DRM mode info. To disable the CRTC,
232 : * user-space must set this property to 0.
233 : *
234 : * Setting MODE_ID to 0 will release reserved resources for the CRTC.
235 : * SCALING_FILTER:
236 : * Atomic property for setting the scaling filter for CRTC scaler
237 : *
238 : * The value of this property can be one of the following:
239 : *
240 : * Default:
241 : * Driver's default scaling filter
242 : * Nearest Neighbor:
243 : * Nearest Neighbor scaling filter
244 : */
245 :
246 : __printf(6, 0)
247 0 : static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
248 : struct drm_plane *primary,
249 : struct drm_plane *cursor,
250 : const struct drm_crtc_funcs *funcs,
251 : const char *name, va_list ap)
252 : {
253 0 : struct drm_mode_config *config = &dev->mode_config;
254 : int ret;
255 :
256 0 : WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY);
257 0 : WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR);
258 :
259 : /* crtc index is used with 32bit bitmasks */
260 0 : if (WARN_ON(config->num_crtc >= 32))
261 : return -EINVAL;
262 :
263 0 : WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
264 : (!funcs->atomic_destroy_state ||
265 : !funcs->atomic_duplicate_state));
266 :
267 0 : crtc->dev = dev;
268 0 : crtc->funcs = funcs;
269 :
270 0 : INIT_LIST_HEAD(&crtc->commit_list);
271 0 : spin_lock_init(&crtc->commit_lock);
272 :
273 0 : drm_modeset_lock_init(&crtc->mutex);
274 0 : ret = drm_mode_object_add(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
275 0 : if (ret)
276 : return ret;
277 :
278 0 : if (name) {
279 0 : crtc->name = kvasprintf(GFP_KERNEL, name, ap);
280 : } else {
281 0 : crtc->name = kasprintf(GFP_KERNEL, "crtc-%d",
282 : drm_num_crtcs(dev));
283 : }
284 0 : if (!crtc->name) {
285 0 : drm_mode_object_unregister(dev, &crtc->base);
286 0 : return -ENOMEM;
287 : }
288 :
289 0 : crtc->fence_context = dma_fence_context_alloc(1);
290 0 : spin_lock_init(&crtc->fence_lock);
291 0 : snprintf(crtc->timeline_name, sizeof(crtc->timeline_name),
292 : "CRTC:%d-%s", crtc->base.id, crtc->name);
293 :
294 0 : crtc->base.properties = &crtc->properties;
295 :
296 0 : list_add_tail(&crtc->head, &config->crtc_list);
297 0 : crtc->index = config->num_crtc++;
298 :
299 0 : crtc->primary = primary;
300 0 : crtc->cursor = cursor;
301 0 : if (primary && !primary->possible_crtcs)
302 0 : primary->possible_crtcs = drm_crtc_mask(crtc);
303 0 : if (cursor && !cursor->possible_crtcs)
304 0 : cursor->possible_crtcs = drm_crtc_mask(crtc);
305 :
306 0 : ret = drm_crtc_crc_init(crtc);
307 : if (ret) {
308 : drm_mode_object_unregister(dev, &crtc->base);
309 : return ret;
310 : }
311 :
312 0 : if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
313 0 : drm_object_attach_property(&crtc->base, config->prop_active, 0);
314 0 : drm_object_attach_property(&crtc->base, config->prop_mode_id, 0);
315 0 : drm_object_attach_property(&crtc->base,
316 : config->prop_out_fence_ptr, 0);
317 0 : drm_object_attach_property(&crtc->base,
318 : config->prop_vrr_enabled, 0);
319 : }
320 :
321 : return 0;
322 : }
323 :
324 : /**
325 : * drm_crtc_init_with_planes - Initialise a new CRTC object with
326 : * specified primary and cursor planes.
327 : * @dev: DRM device
328 : * @crtc: CRTC object to init
329 : * @primary: Primary plane for CRTC
330 : * @cursor: Cursor plane for CRTC
331 : * @funcs: callbacks for the new CRTC
332 : * @name: printf style format string for the CRTC name, or NULL for default name
333 : *
334 : * Inits a new object created as base part of a driver crtc object. Drivers
335 : * should use this function instead of drm_crtc_init(), which is only provided
336 : * for backwards compatibility with drivers which do not yet support universal
337 : * planes). For really simple hardware which has only 1 plane look at
338 : * drm_simple_display_pipe_init() instead.
339 : * The &drm_crtc_funcs.destroy hook should call drm_crtc_cleanup() and kfree()
340 : * the crtc structure. The crtc structure should not be allocated with
341 : * devm_kzalloc().
342 : *
343 : * The @primary and @cursor planes are only relevant for legacy uAPI, see
344 : * &drm_crtc.primary and &drm_crtc.cursor.
345 : *
346 : * Note: consider using drmm_crtc_alloc_with_planes() or
347 : * drmm_crtc_init_with_planes() instead of drm_crtc_init_with_planes()
348 : * to let the DRM managed resource infrastructure take care of cleanup
349 : * and deallocation.
350 : *
351 : * Returns:
352 : * Zero on success, error code on failure.
353 : */
354 0 : int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
355 : struct drm_plane *primary,
356 : struct drm_plane *cursor,
357 : const struct drm_crtc_funcs *funcs,
358 : const char *name, ...)
359 : {
360 : va_list ap;
361 : int ret;
362 :
363 0 : WARN_ON(!funcs->destroy);
364 :
365 0 : va_start(ap, name);
366 0 : ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
367 : name, ap);
368 0 : va_end(ap);
369 :
370 0 : return ret;
371 : }
372 : EXPORT_SYMBOL(drm_crtc_init_with_planes);
373 :
374 0 : static void drmm_crtc_init_with_planes_cleanup(struct drm_device *dev,
375 : void *ptr)
376 : {
377 0 : struct drm_crtc *crtc = ptr;
378 :
379 0 : drm_crtc_cleanup(crtc);
380 0 : }
381 :
382 : __printf(6, 0)
383 0 : static int __drmm_crtc_init_with_planes(struct drm_device *dev,
384 : struct drm_crtc *crtc,
385 : struct drm_plane *primary,
386 : struct drm_plane *cursor,
387 : const struct drm_crtc_funcs *funcs,
388 : const char *name,
389 : va_list args)
390 : {
391 : int ret;
392 :
393 0 : drm_WARN_ON(dev, funcs && funcs->destroy);
394 :
395 0 : ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
396 : name, args);
397 0 : if (ret)
398 : return ret;
399 :
400 0 : ret = drmm_add_action_or_reset(dev, drmm_crtc_init_with_planes_cleanup,
401 : crtc);
402 0 : if (ret)
403 : return ret;
404 :
405 0 : return 0;
406 : }
407 :
408 : /**
409 : * drmm_crtc_init_with_planes - Initialise a new CRTC object with
410 : * specified primary and cursor planes.
411 : * @dev: DRM device
412 : * @crtc: CRTC object to init
413 : * @primary: Primary plane for CRTC
414 : * @cursor: Cursor plane for CRTC
415 : * @funcs: callbacks for the new CRTC
416 : * @name: printf style format string for the CRTC name, or NULL for default name
417 : *
418 : * Inits a new object created as base part of a driver crtc object. Drivers
419 : * should use this function instead of drm_crtc_init(), which is only provided
420 : * for backwards compatibility with drivers which do not yet support universal
421 : * planes). For really simple hardware which has only 1 plane look at
422 : * drm_simple_display_pipe_init() instead.
423 : *
424 : * Cleanup is automatically handled through registering
425 : * drmm_crtc_cleanup() with drmm_add_action(). The crtc structure should
426 : * be allocated with drmm_kzalloc().
427 : *
428 : * The @drm_crtc_funcs.destroy hook must be NULL.
429 : *
430 : * The @primary and @cursor planes are only relevant for legacy uAPI, see
431 : * &drm_crtc.primary and &drm_crtc.cursor.
432 : *
433 : * Returns:
434 : * Zero on success, error code on failure.
435 : */
436 0 : int drmm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
437 : struct drm_plane *primary,
438 : struct drm_plane *cursor,
439 : const struct drm_crtc_funcs *funcs,
440 : const char *name, ...)
441 : {
442 : va_list ap;
443 : int ret;
444 :
445 0 : va_start(ap, name);
446 0 : ret = __drmm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
447 : name, ap);
448 0 : va_end(ap);
449 0 : if (ret)
450 : return ret;
451 :
452 0 : return 0;
453 : }
454 : EXPORT_SYMBOL(drmm_crtc_init_with_planes);
455 :
456 0 : void *__drmm_crtc_alloc_with_planes(struct drm_device *dev,
457 : size_t size, size_t offset,
458 : struct drm_plane *primary,
459 : struct drm_plane *cursor,
460 : const struct drm_crtc_funcs *funcs,
461 : const char *name, ...)
462 : {
463 : void *container;
464 : struct drm_crtc *crtc;
465 : va_list ap;
466 : int ret;
467 :
468 0 : if (WARN_ON(!funcs || funcs->destroy))
469 : return ERR_PTR(-EINVAL);
470 :
471 0 : container = drmm_kzalloc(dev, size, GFP_KERNEL);
472 0 : if (!container)
473 : return ERR_PTR(-ENOMEM);
474 :
475 0 : crtc = container + offset;
476 :
477 0 : va_start(ap, name);
478 0 : ret = __drmm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
479 : name, ap);
480 0 : va_end(ap);
481 0 : if (ret)
482 0 : return ERR_PTR(ret);
483 :
484 : return container;
485 : }
486 : EXPORT_SYMBOL(__drmm_crtc_alloc_with_planes);
487 :
488 : /**
489 : * drm_crtc_cleanup - Clean up the core crtc usage
490 : * @crtc: CRTC to cleanup
491 : *
492 : * This function cleans up @crtc and removes it from the DRM mode setting
493 : * core. Note that the function does *not* free the crtc structure itself,
494 : * this is the responsibility of the caller.
495 : */
496 0 : void drm_crtc_cleanup(struct drm_crtc *crtc)
497 : {
498 0 : struct drm_device *dev = crtc->dev;
499 :
500 : /* Note that the crtc_list is considered to be static; should we
501 : * remove the drm_crtc at runtime we would have to decrement all
502 : * the indices on the drm_crtc after us in the crtc_list.
503 : */
504 :
505 0 : drm_crtc_crc_fini(crtc);
506 :
507 0 : kfree(crtc->gamma_store);
508 0 : crtc->gamma_store = NULL;
509 :
510 0 : drm_modeset_lock_fini(&crtc->mutex);
511 :
512 0 : drm_mode_object_unregister(dev, &crtc->base);
513 0 : list_del(&crtc->head);
514 0 : dev->mode_config.num_crtc--;
515 :
516 0 : WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state);
517 0 : if (crtc->state && crtc->funcs->atomic_destroy_state)
518 0 : crtc->funcs->atomic_destroy_state(crtc, crtc->state);
519 :
520 0 : kfree(crtc->name);
521 :
522 0 : memset(crtc, 0, sizeof(*crtc));
523 0 : }
524 : EXPORT_SYMBOL(drm_crtc_cleanup);
525 :
526 : /**
527 : * drm_mode_getcrtc - get CRTC configuration
528 : * @dev: drm device for the ioctl
529 : * @data: data pointer for the ioctl
530 : * @file_priv: drm file for the ioctl call
531 : *
532 : * Construct a CRTC configuration structure to return to the user.
533 : *
534 : * Called by the user via ioctl.
535 : *
536 : * Returns:
537 : * Zero on success, negative errno on failure.
538 : */
539 0 : int drm_mode_getcrtc(struct drm_device *dev,
540 : void *data, struct drm_file *file_priv)
541 : {
542 0 : struct drm_mode_crtc *crtc_resp = data;
543 : struct drm_crtc *crtc;
544 : struct drm_plane *plane;
545 :
546 0 : if (!drm_core_check_feature(dev, DRIVER_MODESET))
547 : return -EOPNOTSUPP;
548 :
549 0 : crtc = drm_crtc_find(dev, file_priv, crtc_resp->crtc_id);
550 0 : if (!crtc)
551 : return -ENOENT;
552 :
553 0 : plane = crtc->primary;
554 :
555 0 : crtc_resp->gamma_size = crtc->gamma_size;
556 :
557 0 : drm_modeset_lock(&plane->mutex, NULL);
558 0 : if (plane->state && plane->state->fb)
559 0 : crtc_resp->fb_id = plane->state->fb->base.id;
560 0 : else if (!plane->state && plane->fb)
561 0 : crtc_resp->fb_id = plane->fb->base.id;
562 : else
563 0 : crtc_resp->fb_id = 0;
564 :
565 0 : if (plane->state) {
566 0 : crtc_resp->x = plane->state->src_x >> 16;
567 0 : crtc_resp->y = plane->state->src_y >> 16;
568 : }
569 0 : drm_modeset_unlock(&plane->mutex);
570 :
571 0 : drm_modeset_lock(&crtc->mutex, NULL);
572 0 : if (crtc->state) {
573 0 : if (crtc->state->enable) {
574 0 : drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
575 0 : crtc_resp->mode_valid = 1;
576 : } else {
577 0 : crtc_resp->mode_valid = 0;
578 : }
579 : } else {
580 0 : crtc_resp->x = crtc->x;
581 0 : crtc_resp->y = crtc->y;
582 :
583 0 : if (crtc->enabled) {
584 0 : drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode);
585 0 : crtc_resp->mode_valid = 1;
586 :
587 : } else {
588 0 : crtc_resp->mode_valid = 0;
589 : }
590 : }
591 0 : if (!file_priv->aspect_ratio_allowed)
592 0 : crtc_resp->mode.flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
593 0 : drm_modeset_unlock(&crtc->mutex);
594 :
595 0 : return 0;
596 : }
597 :
598 0 : static int __drm_mode_set_config_internal(struct drm_mode_set *set,
599 : struct drm_modeset_acquire_ctx *ctx)
600 : {
601 0 : struct drm_crtc *crtc = set->crtc;
602 : struct drm_framebuffer *fb;
603 : struct drm_crtc *tmp;
604 : int ret;
605 :
606 0 : WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
607 :
608 : /*
609 : * NOTE: ->set_config can also disable other crtcs (if we steal all
610 : * connectors from it), hence we need to refcount the fbs across all
611 : * crtcs. Atomic modeset will have saner semantics ...
612 : */
613 0 : drm_for_each_crtc(tmp, crtc->dev) {
614 0 : struct drm_plane *plane = tmp->primary;
615 :
616 0 : plane->old_fb = plane->fb;
617 : }
618 :
619 0 : fb = set->fb;
620 :
621 0 : ret = crtc->funcs->set_config(set, ctx);
622 0 : if (ret == 0) {
623 0 : struct drm_plane *plane = crtc->primary;
624 :
625 0 : plane->crtc = fb ? crtc : NULL;
626 0 : plane->fb = fb;
627 : }
628 :
629 0 : drm_for_each_crtc(tmp, crtc->dev) {
630 0 : struct drm_plane *plane = tmp->primary;
631 :
632 0 : if (plane->fb)
633 0 : drm_framebuffer_get(plane->fb);
634 0 : if (plane->old_fb)
635 0 : drm_framebuffer_put(plane->old_fb);
636 0 : plane->old_fb = NULL;
637 : }
638 :
639 0 : return ret;
640 : }
641 :
642 : /**
643 : * drm_mode_set_config_internal - helper to call &drm_mode_config_funcs.set_config
644 : * @set: modeset config to set
645 : *
646 : * This is a little helper to wrap internal calls to the
647 : * &drm_mode_config_funcs.set_config driver interface. The only thing it adds is
648 : * correct refcounting dance.
649 : *
650 : * This should only be used by non-atomic legacy drivers.
651 : *
652 : * Returns:
653 : * Zero on success, negative errno on failure.
654 : */
655 0 : int drm_mode_set_config_internal(struct drm_mode_set *set)
656 : {
657 0 : WARN_ON(drm_drv_uses_atomic_modeset(set->crtc->dev));
658 :
659 0 : return __drm_mode_set_config_internal(set, NULL);
660 : }
661 : EXPORT_SYMBOL(drm_mode_set_config_internal);
662 :
663 : /**
664 : * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the
665 : * CRTC viewport
666 : * @crtc: CRTC that framebuffer will be displayed on
667 : * @x: x panning
668 : * @y: y panning
669 : * @mode: mode that framebuffer will be displayed under
670 : * @fb: framebuffer to check size of
671 : */
672 0 : int drm_crtc_check_viewport(const struct drm_crtc *crtc,
673 : int x, int y,
674 : const struct drm_display_mode *mode,
675 : const struct drm_framebuffer *fb)
676 :
677 : {
678 : int hdisplay, vdisplay;
679 :
680 0 : drm_mode_get_hv_timing(mode, &hdisplay, &vdisplay);
681 :
682 0 : if (crtc->state &&
683 0 : drm_rotation_90_or_270(crtc->primary->state->rotation))
684 0 : swap(hdisplay, vdisplay);
685 :
686 0 : return drm_framebuffer_check_src_coords(x << 16, y << 16,
687 0 : hdisplay << 16, vdisplay << 16,
688 : fb);
689 : }
690 : EXPORT_SYMBOL(drm_crtc_check_viewport);
691 :
692 : /**
693 : * drm_mode_setcrtc - set CRTC configuration
694 : * @dev: drm device for the ioctl
695 : * @data: data pointer for the ioctl
696 : * @file_priv: drm file for the ioctl call
697 : *
698 : * Build a new CRTC configuration based on user request.
699 : *
700 : * Called by the user via ioctl.
701 : *
702 : * Returns:
703 : * Zero on success, negative errno on failure.
704 : */
705 0 : int drm_mode_setcrtc(struct drm_device *dev, void *data,
706 : struct drm_file *file_priv)
707 : {
708 0 : struct drm_mode_config *config = &dev->mode_config;
709 0 : struct drm_mode_crtc *crtc_req = data;
710 : struct drm_crtc *crtc;
711 : struct drm_plane *plane;
712 0 : struct drm_connector **connector_set = NULL, *connector;
713 0 : struct drm_framebuffer *fb = NULL;
714 0 : struct drm_display_mode *mode = NULL;
715 : struct drm_mode_set set;
716 : uint32_t __user *set_connectors_ptr;
717 : struct drm_modeset_acquire_ctx ctx;
718 : int ret;
719 : int i;
720 :
721 0 : if (!drm_core_check_feature(dev, DRIVER_MODESET))
722 : return -EOPNOTSUPP;
723 :
724 : /*
725 : * Universal plane src offsets are only 16.16, prevent havoc for
726 : * drivers using universal plane code internally.
727 : */
728 0 : if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
729 : return -ERANGE;
730 :
731 0 : crtc = drm_crtc_find(dev, file_priv, crtc_req->crtc_id);
732 0 : if (!crtc) {
733 0 : DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
734 0 : return -ENOENT;
735 : }
736 0 : DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
737 :
738 0 : plane = crtc->primary;
739 :
740 : /* allow disabling with the primary plane leased */
741 0 : if (crtc_req->mode_valid && !drm_lease_held(file_priv, plane->base.id))
742 : return -EACCES;
743 :
744 0 : DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx,
745 : DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
746 :
747 0 : if (crtc_req->mode_valid) {
748 : /* If we have a mode we need a framebuffer. */
749 : /* If we pass -1, set the mode with the currently bound fb */
750 0 : if (crtc_req->fb_id == -1) {
751 : struct drm_framebuffer *old_fb;
752 :
753 0 : if (plane->state)
754 0 : old_fb = plane->state->fb;
755 : else
756 0 : old_fb = plane->fb;
757 :
758 0 : if (!old_fb) {
759 0 : DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
760 0 : ret = -EINVAL;
761 0 : goto out;
762 : }
763 :
764 0 : fb = old_fb;
765 : /* Make refcounting symmetric with the lookup path. */
766 : drm_framebuffer_get(fb);
767 : } else {
768 0 : fb = drm_framebuffer_lookup(dev, file_priv, crtc_req->fb_id);
769 0 : if (!fb) {
770 0 : DRM_DEBUG_KMS("Unknown FB ID%d\n",
771 : crtc_req->fb_id);
772 0 : ret = -ENOENT;
773 0 : goto out;
774 : }
775 : }
776 :
777 0 : mode = drm_mode_create(dev);
778 0 : if (!mode) {
779 : ret = -ENOMEM;
780 : goto out;
781 : }
782 0 : if (!file_priv->aspect_ratio_allowed &&
783 0 : (crtc_req->mode.flags & DRM_MODE_FLAG_PIC_AR_MASK) != DRM_MODE_FLAG_PIC_AR_NONE) {
784 0 : DRM_DEBUG_KMS("Unexpected aspect-ratio flag bits\n");
785 0 : ret = -EINVAL;
786 0 : goto out;
787 : }
788 :
789 :
790 0 : ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode);
791 0 : if (ret) {
792 0 : DRM_DEBUG_KMS("Invalid mode (ret=%d, status=%s)\n",
793 : ret, drm_get_mode_status_name(mode->status));
794 0 : drm_mode_debug_printmodeline(mode);
795 0 : goto out;
796 : }
797 :
798 : /*
799 : * Check whether the primary plane supports the fb pixel format.
800 : * Drivers not implementing the universal planes API use a
801 : * default formats list provided by the DRM core which doesn't
802 : * match real hardware capabilities. Skip the check in that
803 : * case.
804 : */
805 0 : if (!plane->format_default) {
806 0 : ret = drm_plane_check_pixel_format(plane,
807 0 : fb->format->format,
808 : fb->modifier);
809 0 : if (ret) {
810 0 : DRM_DEBUG_KMS("Invalid pixel format %p4cc, modifier 0x%llx\n",
811 : &fb->format->format,
812 : fb->modifier);
813 0 : goto out;
814 : }
815 : }
816 :
817 0 : ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
818 : mode, fb);
819 0 : if (ret)
820 : goto out;
821 :
822 : }
823 :
824 0 : if (crtc_req->count_connectors == 0 && mode) {
825 0 : DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
826 0 : ret = -EINVAL;
827 0 : goto out;
828 : }
829 :
830 0 : if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
831 0 : DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
832 : crtc_req->count_connectors);
833 0 : ret = -EINVAL;
834 0 : goto out;
835 : }
836 :
837 0 : if (crtc_req->count_connectors > 0) {
838 : u32 out_id;
839 :
840 : /* Avoid unbounded kernel memory allocation */
841 0 : if (crtc_req->count_connectors > config->num_connector) {
842 : ret = -EINVAL;
843 : goto out;
844 : }
845 :
846 0 : connector_set = kmalloc_array(crtc_req->count_connectors,
847 : sizeof(struct drm_connector *),
848 : GFP_KERNEL);
849 0 : if (!connector_set) {
850 : ret = -ENOMEM;
851 : goto out;
852 : }
853 :
854 0 : for (i = 0; i < crtc_req->count_connectors; i++) {
855 0 : connector_set[i] = NULL;
856 0 : set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
857 0 : if (get_user(out_id, &set_connectors_ptr[i])) {
858 : ret = -EFAULT;
859 : goto out;
860 : }
861 :
862 0 : connector = drm_connector_lookup(dev, file_priv, out_id);
863 0 : if (!connector) {
864 0 : DRM_DEBUG_KMS("Connector id %d unknown\n",
865 : out_id);
866 0 : ret = -ENOENT;
867 0 : goto out;
868 : }
869 0 : DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
870 : connector->base.id,
871 : connector->name);
872 :
873 0 : connector_set[i] = connector;
874 : }
875 : }
876 :
877 0 : set.crtc = crtc;
878 0 : set.x = crtc_req->x;
879 0 : set.y = crtc_req->y;
880 0 : set.mode = mode;
881 0 : set.connectors = connector_set;
882 0 : set.num_connectors = crtc_req->count_connectors;
883 0 : set.fb = fb;
884 :
885 0 : if (drm_drv_uses_atomic_modeset(dev))
886 0 : ret = crtc->funcs->set_config(&set, &ctx);
887 : else
888 0 : ret = __drm_mode_set_config_internal(&set, &ctx);
889 :
890 : out:
891 0 : if (fb)
892 : drm_framebuffer_put(fb);
893 :
894 0 : if (connector_set) {
895 0 : for (i = 0; i < crtc_req->count_connectors; i++) {
896 0 : if (connector_set[i])
897 0 : drm_connector_put(connector_set[i]);
898 : }
899 : }
900 0 : kfree(connector_set);
901 0 : drm_mode_destroy(dev, mode);
902 :
903 : /* In case we need to retry... */
904 0 : connector_set = NULL;
905 0 : fb = NULL;
906 0 : mode = NULL;
907 :
908 0 : DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
909 :
910 : return ret;
911 : }
912 :
913 0 : int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
914 : struct drm_property *property,
915 : uint64_t value)
916 : {
917 0 : int ret = -EINVAL;
918 0 : struct drm_crtc *crtc = obj_to_crtc(obj);
919 :
920 0 : if (crtc->funcs->set_property)
921 0 : ret = crtc->funcs->set_property(crtc, property, value);
922 0 : if (!ret)
923 0 : drm_object_property_set_value(obj, property, value);
924 :
925 0 : return ret;
926 : }
927 :
928 : /**
929 : * drm_crtc_create_scaling_filter_property - create a new scaling filter
930 : * property
931 : *
932 : * @crtc: drm CRTC
933 : * @supported_filters: bitmask of supported scaling filters, must include
934 : * BIT(DRM_SCALING_FILTER_DEFAULT).
935 : *
936 : * This function lets driver to enable the scaling filter property on a given
937 : * CRTC.
938 : *
939 : * RETURNS:
940 : * Zero for success or -errno
941 : */
942 0 : int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc,
943 : unsigned int supported_filters)
944 : {
945 0 : struct drm_property *prop =
946 0 : drm_create_scaling_filter_prop(crtc->dev, supported_filters);
947 :
948 0 : if (IS_ERR(prop))
949 0 : return PTR_ERR(prop);
950 :
951 0 : drm_object_attach_property(&crtc->base, prop,
952 : DRM_SCALING_FILTER_DEFAULT);
953 0 : crtc->scaling_filter_property = prop;
954 :
955 0 : return 0;
956 : }
957 : EXPORT_SYMBOL(drm_crtc_create_scaling_filter_property);
|