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
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_crtc.h>
39#include <drm/drm_edid.h>
40#include <drm/drm_fourcc.h>
41#include <drm/drm_managed.h>
42#include <drm/drm_modeset_lock.h>
43#include <drm/drm_atomic.h>
44#include <drm/drm_auth.h>
45#include <drm/drm_debugfs_crc.h>
46#include <drm/drm_drv.h>
47#include <drm/drm_print.h>
48#include <drm/drm_file.h>
49
50#include "drm_crtc_internal.h"
51#include "drm_internal.h"
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx)
86{
87 struct drm_crtc *crtc;
88
89 drm_for_each_crtc(crtc, dev)
90 if (idx == crtc->index)
91 return crtc;
92
93 return NULL;
94}
95EXPORT_SYMBOL(drm_crtc_from_index);
96
97int drm_crtc_force_disable(struct drm_crtc *crtc)
98{
99 struct drm_mode_set set = {
100 .crtc = crtc,
101 };
102
103 WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
104
105 return drm_mode_set_config_internal(&set);
106}
107
108static unsigned int drm_num_crtcs(struct drm_device *dev)
109{
110 unsigned int num = 0;
111 struct drm_crtc *tmp;
112
113 drm_for_each_crtc(tmp, dev) {
114 num++;
115 }
116
117 return num;
118}
119
120int drm_crtc_register_all(struct drm_device *dev)
121{
122 struct drm_crtc *crtc;
123 int ret = 0;
124
125 drm_for_each_crtc(crtc, dev) {
126 drm_debugfs_crtc_add(crtc);
127
128 if (crtc->funcs->late_register)
129 ret = crtc->funcs->late_register(crtc);
130 if (ret)
131 return ret;
132 }
133
134 return 0;
135}
136
137void drm_crtc_unregister_all(struct drm_device *dev)
138{
139 struct drm_crtc *crtc;
140
141 drm_for_each_crtc(crtc, dev) {
142 if (crtc->funcs->early_unregister)
143 crtc->funcs->early_unregister(crtc);
144 drm_debugfs_crtc_remove(crtc);
145 }
146}
147
148static int drm_crtc_crc_init(struct drm_crtc *crtc)
149{
150#ifdef CONFIG_DEBUG_FS
151 spin_lock_init(&crtc->crc.lock);
152 init_waitqueue_head(&crtc->crc.wq);
153 crtc->crc.source = kstrdup("auto", GFP_KERNEL);
154 if (!crtc->crc.source)
155 return -ENOMEM;
156#endif
157 return 0;
158}
159
160static void drm_crtc_crc_fini(struct drm_crtc *crtc)
161{
162#ifdef CONFIG_DEBUG_FS
163 kfree(crtc->crc.source);
164#endif
165}
166
167static const struct dma_fence_ops drm_crtc_fence_ops;
168
169static struct drm_crtc *fence_to_crtc(struct dma_fence *fence)
170{
171 BUG_ON(fence->ops != &drm_crtc_fence_ops);
172 return container_of(fence->lock, struct drm_crtc, fence_lock);
173}
174
175static const char *drm_crtc_fence_get_driver_name(struct dma_fence *fence)
176{
177 struct drm_crtc *crtc = fence_to_crtc(fence);
178
179 return crtc->dev->driver->name;
180}
181
182static const char *drm_crtc_fence_get_timeline_name(struct dma_fence *fence)
183{
184 struct drm_crtc *crtc = fence_to_crtc(fence);
185
186 return crtc->timeline_name;
187}
188
189static const struct dma_fence_ops drm_crtc_fence_ops = {
190 .get_driver_name = drm_crtc_fence_get_driver_name,
191 .get_timeline_name = drm_crtc_fence_get_timeline_name,
192};
193
194struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc)
195{
196 struct dma_fence *fence;
197
198 fence = kzalloc(sizeof(*fence), GFP_KERNEL);
199 if (!fence)
200 return NULL;
201
202 dma_fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock,
203 crtc->fence_context, ++crtc->fence_seqno);
204
205 return fence;
206}
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244__printf(6, 0)
245static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
246 struct drm_plane *primary,
247 struct drm_plane *cursor,
248 const struct drm_crtc_funcs *funcs,
249 const char *name, va_list ap)
250{
251 struct drm_mode_config *config = &dev->mode_config;
252 int ret;
253
254 WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY);
255 WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR);
256
257
258 if (WARN_ON(config->num_crtc >= 32))
259 return -EINVAL;
260
261 WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
262 (!funcs->atomic_destroy_state ||
263 !funcs->atomic_duplicate_state));
264
265 crtc->dev = dev;
266 crtc->funcs = funcs;
267
268 INIT_LIST_HEAD(&crtc->commit_list);
269 spin_lock_init(&crtc->commit_lock);
270
271 drm_modeset_lock_init(&crtc->mutex);
272 ret = drm_mode_object_add(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
273 if (ret)
274 return ret;
275
276 if (name) {
277 crtc->name = kvasprintf(GFP_KERNEL, name, ap);
278 } else {
279 crtc->name = kasprintf(GFP_KERNEL, "crtc-%d",
280 drm_num_crtcs(dev));
281 }
282 if (!crtc->name) {
283 drm_mode_object_unregister(dev, &crtc->base);
284 return -ENOMEM;
285 }
286
287 crtc->fence_context = dma_fence_context_alloc(1);
288 spin_lock_init(&crtc->fence_lock);
289 snprintf(crtc->timeline_name, sizeof(crtc->timeline_name),
290 "CRTC:%d-%s", crtc->base.id, crtc->name);
291
292 crtc->base.properties = &crtc->properties;
293
294 list_add_tail(&crtc->head, &config->crtc_list);
295 crtc->index = config->num_crtc++;
296
297 crtc->primary = primary;
298 crtc->cursor = cursor;
299 if (primary && !primary->possible_crtcs)
300 primary->possible_crtcs = drm_crtc_mask(crtc);
301 if (cursor && !cursor->possible_crtcs)
302 cursor->possible_crtcs = drm_crtc_mask(crtc);
303
304 ret = drm_crtc_crc_init(crtc);
305 if (ret) {
306 drm_mode_object_unregister(dev, &crtc->base);
307 return ret;
308 }
309
310 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
311 drm_object_attach_property(&crtc->base, config->prop_active, 0);
312 drm_object_attach_property(&crtc->base, config->prop_mode_id, 0);
313 drm_object_attach_property(&crtc->base,
314 config->prop_out_fence_ptr, 0);
315 drm_object_attach_property(&crtc->base,
316 config->prop_vrr_enabled, 0);
317 }
318
319 return 0;
320}
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
352 struct drm_plane *primary,
353 struct drm_plane *cursor,
354 const struct drm_crtc_funcs *funcs,
355 const char *name, ...)
356{
357 va_list ap;
358 int ret;
359
360 WARN_ON(!funcs->destroy);
361
362 va_start(ap, name);
363 ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
364 name, ap);
365 va_end(ap);
366
367 return ret;
368}
369EXPORT_SYMBOL(drm_crtc_init_with_planes);
370
371static void drmm_crtc_alloc_with_planes_cleanup(struct drm_device *dev,
372 void *ptr)
373{
374 struct drm_crtc *crtc = ptr;
375
376 drm_crtc_cleanup(crtc);
377}
378
379void *__drmm_crtc_alloc_with_planes(struct drm_device *dev,
380 size_t size, size_t offset,
381 struct drm_plane *primary,
382 struct drm_plane *cursor,
383 const struct drm_crtc_funcs *funcs,
384 const char *name, ...)
385{
386 void *container;
387 struct drm_crtc *crtc;
388 va_list ap;
389 int ret;
390
391 if (WARN_ON(!funcs || funcs->destroy))
392 return ERR_PTR(-EINVAL);
393
394 container = drmm_kzalloc(dev, size, GFP_KERNEL);
395 if (!container)
396 return ERR_PTR(-ENOMEM);
397
398 crtc = container + offset;
399
400 va_start(ap, name);
401 ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
402 name, ap);
403 va_end(ap);
404 if (ret)
405 return ERR_PTR(ret);
406
407 ret = drmm_add_action_or_reset(dev, drmm_crtc_alloc_with_planes_cleanup,
408 crtc);
409 if (ret)
410 return ERR_PTR(ret);
411
412 return container;
413}
414EXPORT_SYMBOL(__drmm_crtc_alloc_with_planes);
415
416
417
418
419
420
421
422
423
424void drm_crtc_cleanup(struct drm_crtc *crtc)
425{
426 struct drm_device *dev = crtc->dev;
427
428
429
430
431
432
433 drm_crtc_crc_fini(crtc);
434
435 kfree(crtc->gamma_store);
436 crtc->gamma_store = NULL;
437
438 drm_modeset_lock_fini(&crtc->mutex);
439
440 drm_mode_object_unregister(dev, &crtc->base);
441 list_del(&crtc->head);
442 dev->mode_config.num_crtc--;
443
444 WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state);
445 if (crtc->state && crtc->funcs->atomic_destroy_state)
446 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
447
448 kfree(crtc->name);
449
450 memset(crtc, 0, sizeof(*crtc));
451}
452EXPORT_SYMBOL(drm_crtc_cleanup);
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467int drm_mode_getcrtc(struct drm_device *dev,
468 void *data, struct drm_file *file_priv)
469{
470 struct drm_mode_crtc *crtc_resp = data;
471 struct drm_crtc *crtc;
472 struct drm_plane *plane;
473
474 if (!drm_core_check_feature(dev, DRIVER_MODESET))
475 return -EOPNOTSUPP;
476
477 crtc = drm_crtc_find(dev, file_priv, crtc_resp->crtc_id);
478 if (!crtc)
479 return -ENOENT;
480
481 plane = crtc->primary;
482
483 crtc_resp->gamma_size = crtc->gamma_size;
484
485 drm_modeset_lock(&plane->mutex, NULL);
486 if (plane->state && plane->state->fb)
487 crtc_resp->fb_id = plane->state->fb->base.id;
488 else if (!plane->state && plane->fb)
489 crtc_resp->fb_id = plane->fb->base.id;
490 else
491 crtc_resp->fb_id = 0;
492
493 if (plane->state) {
494 crtc_resp->x = plane->state->src_x >> 16;
495 crtc_resp->y = plane->state->src_y >> 16;
496 }
497 drm_modeset_unlock(&plane->mutex);
498
499 drm_modeset_lock(&crtc->mutex, NULL);
500 if (crtc->state) {
501 if (crtc->state->enable) {
502 drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
503 crtc_resp->mode_valid = 1;
504 } else {
505 crtc_resp->mode_valid = 0;
506 }
507 } else {
508 crtc_resp->x = crtc->x;
509 crtc_resp->y = crtc->y;
510
511 if (crtc->enabled) {
512 drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode);
513 crtc_resp->mode_valid = 1;
514
515 } else {
516 crtc_resp->mode_valid = 0;
517 }
518 }
519 if (!file_priv->aspect_ratio_allowed)
520 crtc_resp->mode.flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
521 drm_modeset_unlock(&crtc->mutex);
522
523 return 0;
524}
525
526static int __drm_mode_set_config_internal(struct drm_mode_set *set,
527 struct drm_modeset_acquire_ctx *ctx)
528{
529 struct drm_crtc *crtc = set->crtc;
530 struct drm_framebuffer *fb;
531 struct drm_crtc *tmp;
532 int ret;
533
534 WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
535
536
537
538
539
540
541 drm_for_each_crtc(tmp, crtc->dev) {
542 struct drm_plane *plane = tmp->primary;
543
544 plane->old_fb = plane->fb;
545 }
546
547 fb = set->fb;
548
549 ret = crtc->funcs->set_config(set, ctx);
550 if (ret == 0) {
551 struct drm_plane *plane = crtc->primary;
552
553 plane->crtc = fb ? crtc : NULL;
554 plane->fb = fb;
555 }
556
557 drm_for_each_crtc(tmp, crtc->dev) {
558 struct drm_plane *plane = tmp->primary;
559
560 if (plane->fb)
561 drm_framebuffer_get(plane->fb);
562 if (plane->old_fb)
563 drm_framebuffer_put(plane->old_fb);
564 plane->old_fb = NULL;
565 }
566
567 return ret;
568}
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583int drm_mode_set_config_internal(struct drm_mode_set *set)
584{
585 WARN_ON(drm_drv_uses_atomic_modeset(set->crtc->dev));
586
587 return __drm_mode_set_config_internal(set, NULL);
588}
589EXPORT_SYMBOL(drm_mode_set_config_internal);
590
591
592
593
594
595
596
597
598
599
600int drm_crtc_check_viewport(const struct drm_crtc *crtc,
601 int x, int y,
602 const struct drm_display_mode *mode,
603 const struct drm_framebuffer *fb)
604
605{
606 int hdisplay, vdisplay;
607
608 drm_mode_get_hv_timing(mode, &hdisplay, &vdisplay);
609
610 if (crtc->state &&
611 drm_rotation_90_or_270(crtc->primary->state->rotation))
612 swap(hdisplay, vdisplay);
613
614 return drm_framebuffer_check_src_coords(x << 16, y << 16,
615 hdisplay << 16, vdisplay << 16,
616 fb);
617}
618EXPORT_SYMBOL(drm_crtc_check_viewport);
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633int drm_mode_setcrtc(struct drm_device *dev, void *data,
634 struct drm_file *file_priv)
635{
636 struct drm_mode_config *config = &dev->mode_config;
637 struct drm_mode_crtc *crtc_req = data;
638 struct drm_crtc *crtc;
639 struct drm_plane *plane;
640 struct drm_connector **connector_set = NULL, *connector;
641 struct drm_framebuffer *fb = NULL;
642 struct drm_display_mode *mode = NULL;
643 struct drm_mode_set set;
644 uint32_t __user *set_connectors_ptr;
645 struct drm_modeset_acquire_ctx ctx;
646 int ret;
647 int i;
648
649 if (!drm_core_check_feature(dev, DRIVER_MODESET))
650 return -EOPNOTSUPP;
651
652
653
654
655
656 if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
657 return -ERANGE;
658
659 crtc = drm_crtc_find(dev, file_priv, crtc_req->crtc_id);
660 if (!crtc) {
661 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
662 return -ENOENT;
663 }
664 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
665
666 plane = crtc->primary;
667
668
669 if (crtc_req->mode_valid && !drm_lease_held(file_priv, plane->base.id))
670 return -EACCES;
671
672 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx,
673 DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
674
675 if (crtc_req->mode_valid) {
676
677
678 if (crtc_req->fb_id == -1) {
679 struct drm_framebuffer *old_fb;
680
681 if (plane->state)
682 old_fb = plane->state->fb;
683 else
684 old_fb = plane->fb;
685
686 if (!old_fb) {
687 DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
688 ret = -EINVAL;
689 goto out;
690 }
691
692 fb = old_fb;
693
694 drm_framebuffer_get(fb);
695 } else {
696 fb = drm_framebuffer_lookup(dev, file_priv, crtc_req->fb_id);
697 if (!fb) {
698 DRM_DEBUG_KMS("Unknown FB ID%d\n",
699 crtc_req->fb_id);
700 ret = -ENOENT;
701 goto out;
702 }
703 }
704
705 mode = drm_mode_create(dev);
706 if (!mode) {
707 ret = -ENOMEM;
708 goto out;
709 }
710 if (!file_priv->aspect_ratio_allowed &&
711 (crtc_req->mode.flags & DRM_MODE_FLAG_PIC_AR_MASK) != DRM_MODE_FLAG_PIC_AR_NONE) {
712 DRM_DEBUG_KMS("Unexpected aspect-ratio flag bits\n");
713 ret = -EINVAL;
714 goto out;
715 }
716
717
718 ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode);
719 if (ret) {
720 DRM_DEBUG_KMS("Invalid mode (ret=%d, status=%s)\n",
721 ret, drm_get_mode_status_name(mode->status));
722 drm_mode_debug_printmodeline(mode);
723 goto out;
724 }
725
726
727
728
729
730
731
732
733 if (!plane->format_default) {
734 ret = drm_plane_check_pixel_format(plane,
735 fb->format->format,
736 fb->modifier);
737 if (ret) {
738 DRM_DEBUG_KMS("Invalid pixel format %p4cc, modifier 0x%llx\n",
739 &fb->format->format,
740 fb->modifier);
741 goto out;
742 }
743 }
744
745 ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
746 mode, fb);
747 if (ret)
748 goto out;
749
750 }
751
752 if (crtc_req->count_connectors == 0 && mode) {
753 DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
754 ret = -EINVAL;
755 goto out;
756 }
757
758 if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
759 DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
760 crtc_req->count_connectors);
761 ret = -EINVAL;
762 goto out;
763 }
764
765 if (crtc_req->count_connectors > 0) {
766 u32 out_id;
767
768
769 if (crtc_req->count_connectors > config->num_connector) {
770 ret = -EINVAL;
771 goto out;
772 }
773
774 connector_set = kmalloc_array(crtc_req->count_connectors,
775 sizeof(struct drm_connector *),
776 GFP_KERNEL);
777 if (!connector_set) {
778 ret = -ENOMEM;
779 goto out;
780 }
781
782 for (i = 0; i < crtc_req->count_connectors; i++) {
783 connector_set[i] = NULL;
784 set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
785 if (get_user(out_id, &set_connectors_ptr[i])) {
786 ret = -EFAULT;
787 goto out;
788 }
789
790 connector = drm_connector_lookup(dev, file_priv, out_id);
791 if (!connector) {
792 DRM_DEBUG_KMS("Connector id %d unknown\n",
793 out_id);
794 ret = -ENOENT;
795 goto out;
796 }
797 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
798 connector->base.id,
799 connector->name);
800
801 connector_set[i] = connector;
802 }
803 }
804
805 set.crtc = crtc;
806 set.x = crtc_req->x;
807 set.y = crtc_req->y;
808 set.mode = mode;
809 set.connectors = connector_set;
810 set.num_connectors = crtc_req->count_connectors;
811 set.fb = fb;
812
813 if (drm_drv_uses_atomic_modeset(dev))
814 ret = crtc->funcs->set_config(&set, &ctx);
815 else
816 ret = __drm_mode_set_config_internal(&set, &ctx);
817
818out:
819 if (fb)
820 drm_framebuffer_put(fb);
821
822 if (connector_set) {
823 for (i = 0; i < crtc_req->count_connectors; i++) {
824 if (connector_set[i])
825 drm_connector_put(connector_set[i]);
826 }
827 }
828 kfree(connector_set);
829 drm_mode_destroy(dev, mode);
830
831
832 connector_set = NULL;
833 fb = NULL;
834 mode = NULL;
835
836 DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
837
838 return ret;
839}
840
841int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
842 struct drm_property *property,
843 uint64_t value)
844{
845 int ret = -EINVAL;
846 struct drm_crtc *crtc = obj_to_crtc(obj);
847
848 if (crtc->funcs->set_property)
849 ret = crtc->funcs->set_property(crtc, property, value);
850 if (!ret)
851 drm_object_property_set_value(obj, property, value);
852
853 return ret;
854}
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc,
871 unsigned int supported_filters)
872{
873 struct drm_property *prop =
874 drm_create_scaling_filter_prop(crtc->dev, supported_filters);
875
876 if (IS_ERR(prop))
877 return PTR_ERR(prop);
878
879 drm_object_attach_property(&crtc->base, prop,
880 DRM_SCALING_FILTER_DEFAULT);
881 crtc->scaling_filter_property = prop;
882
883 return 0;
884}
885EXPORT_SYMBOL(drm_crtc_create_scaling_filter_property);
886