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 <drm/drmP.h>
37#include <drm/drm_crtc.h>
38#include <drm/drm_edid.h>
39#include <drm/drm_fourcc.h>
40#include <drm/drm_modeset_lock.h>
41#include <drm/drm_atomic.h>
42
43#include "drm_crtc_internal.h"
44#include "drm_internal.h"
45
46static struct drm_framebuffer *
47internal_framebuffer_create(struct drm_device *dev,
48 const struct drm_mode_fb_cmd2 *r,
49 struct drm_file *file_priv);
50
51
52#define DRM_ENUM_NAME_FN(fnname, list) \
53 const char *fnname(int val) \
54 { \
55 int i; \
56 for (i = 0; i < ARRAY_SIZE(list); i++) { \
57 if (list[i].type == val) \
58 return list[i].name; \
59 } \
60 return "(unknown)"; \
61 }
62
63
64
65
66static const struct drm_prop_enum_list drm_dpms_enum_list[] = {
67 { DRM_MODE_DPMS_ON, "On" },
68 { DRM_MODE_DPMS_STANDBY, "Standby" },
69 { DRM_MODE_DPMS_SUSPEND, "Suspend" },
70 { DRM_MODE_DPMS_OFF, "Off" }
71};
72
73DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
74
75static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
76 { DRM_PLANE_TYPE_OVERLAY, "Overlay" },
77 { DRM_PLANE_TYPE_PRIMARY, "Primary" },
78 { DRM_PLANE_TYPE_CURSOR, "Cursor" },
79};
80
81
82
83
84static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = {
85 { DRM_MODE_SCALE_NONE, "None" },
86 { DRM_MODE_SCALE_FULLSCREEN, "Full" },
87 { DRM_MODE_SCALE_CENTER, "Center" },
88 { DRM_MODE_SCALE_ASPECT, "Full aspect" },
89};
90
91static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = {
92 { DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" },
93 { DRM_MODE_PICTURE_ASPECT_4_3, "4:3" },
94 { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" },
95};
96
97
98
99
100static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = {
101 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" },
102 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" },
103 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" },
104};
105
106DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list)
107
108static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = {
109 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" },
110 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" },
111 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" },
112};
113
114DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
115 drm_dvi_i_subconnector_enum_list)
116
117static const struct drm_prop_enum_list drm_tv_select_enum_list[] = {
118 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" },
119 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" },
120 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" },
121 { DRM_MODE_SUBCONNECTOR_Component, "Component" },
122 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" },
123};
124
125DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
126
127static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = {
128 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" },
129 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" },
130 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" },
131 { DRM_MODE_SUBCONNECTOR_Component, "Component" },
132 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" },
133};
134
135DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
136 drm_tv_subconnector_enum_list)
137
138static const struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
139 { DRM_MODE_DIRTY_OFF, "Off" },
140 { DRM_MODE_DIRTY_ON, "On" },
141 { DRM_MODE_DIRTY_ANNOTATE, "Annotate" },
142};
143
144struct drm_conn_prop_enum_list {
145 int type;
146 const char *name;
147 struct ida ida;
148};
149
150
151
152
153static struct drm_conn_prop_enum_list drm_connector_enum_list[] = {
154 { DRM_MODE_CONNECTOR_Unknown, "Unknown" },
155 { DRM_MODE_CONNECTOR_VGA, "VGA" },
156 { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
157 { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
158 { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
159 { DRM_MODE_CONNECTOR_Composite, "Composite" },
160 { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" },
161 { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
162 { DRM_MODE_CONNECTOR_Component, "Component" },
163 { DRM_MODE_CONNECTOR_9PinDIN, "DIN" },
164 { DRM_MODE_CONNECTOR_DisplayPort, "DP" },
165 { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
166 { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
167 { DRM_MODE_CONNECTOR_TV, "TV" },
168 { DRM_MODE_CONNECTOR_eDP, "eDP" },
169 { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
170 { DRM_MODE_CONNECTOR_DSI, "DSI" },
171};
172
173static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
174 { DRM_MODE_ENCODER_NONE, "None" },
175 { DRM_MODE_ENCODER_DAC, "DAC" },
176 { DRM_MODE_ENCODER_TMDS, "TMDS" },
177 { DRM_MODE_ENCODER_LVDS, "LVDS" },
178 { DRM_MODE_ENCODER_TVDAC, "TV" },
179 { DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
180 { DRM_MODE_ENCODER_DSI, "DSI" },
181 { DRM_MODE_ENCODER_DPMST, "DP MST" },
182};
183
184static const struct drm_prop_enum_list drm_subpixel_enum_list[] = {
185 { SubPixelUnknown, "Unknown" },
186 { SubPixelHorizontalRGB, "Horizontal RGB" },
187 { SubPixelHorizontalBGR, "Horizontal BGR" },
188 { SubPixelVerticalRGB, "Vertical RGB" },
189 { SubPixelVerticalBGR, "Vertical BGR" },
190 { SubPixelNone, "None" },
191};
192
193void drm_connector_ida_init(void)
194{
195 int i;
196
197 for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
198 ida_init(&drm_connector_enum_list[i].ida);
199}
200
201void drm_connector_ida_destroy(void)
202{
203 int i;
204
205 for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
206 ida_destroy(&drm_connector_enum_list[i].ida);
207}
208
209
210
211
212
213
214
215
216const char *drm_get_connector_status_name(enum drm_connector_status status)
217{
218 if (status == connector_status_connected)
219 return "connected";
220 else if (status == connector_status_disconnected)
221 return "disconnected";
222 else
223 return "unknown";
224}
225EXPORT_SYMBOL(drm_get_connector_status_name);
226
227
228
229
230
231
232
233
234const char *drm_get_subpixel_order_name(enum subpixel_order order)
235{
236 return drm_subpixel_enum_list[order].name;
237}
238EXPORT_SYMBOL(drm_get_subpixel_order_name);
239
240static char printable_char(int c)
241{
242 return isascii(c) && isprint(c) ? c : '?';
243}
244
245
246
247
248
249
250
251
252
253
254const char *drm_get_format_name(uint32_t format)
255{
256 static char buf[32];
257
258 snprintf(buf, sizeof(buf),
259 "%c%c%c%c %s-endian (0x%08x)",
260 printable_char(format & 0xff),
261 printable_char((format >> 8) & 0xff),
262 printable_char((format >> 16) & 0xff),
263 printable_char((format >> 24) & 0x7f),
264 format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",
265 format);
266
267 return buf;
268}
269EXPORT_SYMBOL(drm_get_format_name);
270
271
272
273
274
275static int drm_mode_object_get_reg(struct drm_device *dev,
276 struct drm_mode_object *obj,
277 uint32_t obj_type,
278 bool register_obj)
279{
280 int ret;
281
282 mutex_lock(&dev->mode_config.idr_mutex);
283 ret = idr_alloc(&dev->mode_config.crtc_idr, register_obj ? obj : NULL, 1, 0, GFP_KERNEL);
284 if (ret >= 0) {
285
286
287
288
289 obj->id = ret;
290 obj->type = obj_type;
291 }
292 mutex_unlock(&dev->mode_config.idr_mutex);
293
294 return ret < 0 ? ret : 0;
295}
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311int drm_mode_object_get(struct drm_device *dev,
312 struct drm_mode_object *obj, uint32_t obj_type)
313{
314 return drm_mode_object_get_reg(dev, obj, obj_type, true);
315}
316
317static void drm_mode_object_register(struct drm_device *dev,
318 struct drm_mode_object *obj)
319{
320 mutex_lock(&dev->mode_config.idr_mutex);
321 idr_replace(&dev->mode_config.crtc_idr, obj, obj->id);
322 mutex_unlock(&dev->mode_config.idr_mutex);
323}
324
325
326
327
328
329
330
331
332
333
334void drm_mode_object_put(struct drm_device *dev,
335 struct drm_mode_object *object)
336{
337 mutex_lock(&dev->mode_config.idr_mutex);
338 idr_remove(&dev->mode_config.crtc_idr, object->id);
339 mutex_unlock(&dev->mode_config.idr_mutex);
340}
341
342static struct drm_mode_object *_object_find(struct drm_device *dev,
343 uint32_t id, uint32_t type)
344{
345 struct drm_mode_object *obj = NULL;
346
347 mutex_lock(&dev->mode_config.idr_mutex);
348 obj = idr_find(&dev->mode_config.crtc_idr, id);
349 if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
350 obj = NULL;
351 if (obj && obj->id != id)
352 obj = NULL;
353
354 if (obj &&
355 (obj->type == DRM_MODE_OBJECT_FB ||
356 obj->type == DRM_MODE_OBJECT_BLOB))
357 obj = NULL;
358 mutex_unlock(&dev->mode_config.idr_mutex);
359
360 return obj;
361}
362
363
364
365
366
367
368
369
370
371
372
373
374struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
375 uint32_t id, uint32_t type)
376{
377 struct drm_mode_object *obj = NULL;
378
379
380
381 WARN_ON(type == DRM_MODE_OBJECT_FB || type == DRM_MODE_OBJECT_BLOB);
382 obj = _object_find(dev, id, type);
383 return obj;
384}
385EXPORT_SYMBOL(drm_mode_object_find);
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
406 const struct drm_framebuffer_funcs *funcs)
407{
408 int ret;
409
410 mutex_lock(&dev->mode_config.fb_lock);
411 kref_init(&fb->refcount);
412 INIT_LIST_HEAD(&fb->filp_head);
413 fb->dev = dev;
414 fb->funcs = funcs;
415
416 ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB);
417 if (ret)
418 goto out;
419
420 dev->mode_config.num_fb++;
421 list_add(&fb->head, &dev->mode_config.fb_list);
422out:
423 mutex_unlock(&dev->mode_config.fb_lock);
424
425 return ret;
426}
427EXPORT_SYMBOL(drm_framebuffer_init);
428
429
430static void __drm_framebuffer_unregister(struct drm_device *dev,
431 struct drm_framebuffer *fb)
432{
433 drm_mode_object_put(dev, &fb->base);
434
435 fb->base.id = 0;
436}
437
438static void drm_framebuffer_free(struct kref *kref)
439{
440 struct drm_framebuffer *fb =
441 container_of(kref, struct drm_framebuffer, refcount);
442 struct drm_device *dev = fb->dev;
443
444
445
446
447
448 mutex_lock(&dev->mode_config.fb_lock);
449 if (fb->base.id) {
450
451 __drm_framebuffer_unregister(dev, fb);
452 }
453 mutex_unlock(&dev->mode_config.fb_lock);
454
455 fb->funcs->destroy(fb);
456}
457
458static struct drm_framebuffer *__drm_framebuffer_lookup(struct drm_device *dev,
459 uint32_t id)
460{
461 struct drm_mode_object *obj = NULL;
462 struct drm_framebuffer *fb;
463
464 mutex_lock(&dev->mode_config.idr_mutex);
465 obj = idr_find(&dev->mode_config.crtc_idr, id);
466 if (!obj || (obj->type != DRM_MODE_OBJECT_FB) || (obj->id != id))
467 fb = NULL;
468 else
469 fb = obj_to_fb(obj);
470 mutex_unlock(&dev->mode_config.idr_mutex);
471
472 return fb;
473}
474
475
476
477
478
479
480
481
482
483
484struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
485 uint32_t id)
486{
487 struct drm_framebuffer *fb;
488
489 mutex_lock(&dev->mode_config.fb_lock);
490 fb = __drm_framebuffer_lookup(dev, id);
491 if (fb) {
492 if (!kref_get_unless_zero(&fb->refcount))
493 fb = NULL;
494 }
495 mutex_unlock(&dev->mode_config.fb_lock);
496
497 return fb;
498}
499EXPORT_SYMBOL(drm_framebuffer_lookup);
500
501
502
503
504
505
506
507void drm_framebuffer_unreference(struct drm_framebuffer *fb)
508{
509 DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount));
510 kref_put(&fb->refcount, drm_framebuffer_free);
511}
512EXPORT_SYMBOL(drm_framebuffer_unreference);
513
514
515
516
517
518
519
520void drm_framebuffer_reference(struct drm_framebuffer *fb)
521{
522 DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount));
523 kref_get(&fb->refcount);
524}
525EXPORT_SYMBOL(drm_framebuffer_reference);
526
527
528
529
530
531
532
533
534
535
536void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
537{
538 struct drm_device *dev;
539
540 if (!fb)
541 return;
542
543 dev = fb->dev;
544
545 mutex_lock(&dev->mode_config.fb_lock);
546
547 __drm_framebuffer_unregister(dev, fb);
548 mutex_unlock(&dev->mode_config.fb_lock);
549}
550EXPORT_SYMBOL(drm_framebuffer_unregister_private);
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
570{
571 struct drm_device *dev = fb->dev;
572
573 mutex_lock(&dev->mode_config.fb_lock);
574 list_del(&fb->head);
575 dev->mode_config.num_fb--;
576 mutex_unlock(&dev->mode_config.fb_lock);
577}
578EXPORT_SYMBOL(drm_framebuffer_cleanup);
579
580
581
582
583
584
585
586
587
588
589
590
591
592void drm_framebuffer_remove(struct drm_framebuffer *fb)
593{
594 struct drm_device *dev;
595 struct drm_crtc *crtc;
596 struct drm_plane *plane;
597 struct drm_mode_set set;
598 int ret;
599
600 if (!fb)
601 return;
602
603 dev = fb->dev;
604
605 WARN_ON(!list_empty(&fb->filp_head));
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622 if (atomic_read(&fb->refcount.refcount) > 1) {
623 drm_modeset_lock_all(dev);
624
625 drm_for_each_crtc(crtc, dev) {
626 if (crtc->primary->fb == fb) {
627
628 memset(&set, 0, sizeof(struct drm_mode_set));
629 set.crtc = crtc;
630 set.fb = NULL;
631 ret = drm_mode_set_config_internal(&set);
632 if (ret)
633 DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
634 }
635 }
636
637 drm_for_each_plane(plane, dev) {
638 if (plane->fb == fb)
639 drm_plane_force_disable(plane);
640 }
641 drm_modeset_unlock_all(dev);
642 }
643
644 drm_framebuffer_unreference(fb);
645}
646EXPORT_SYMBOL(drm_framebuffer_remove);
647
648DEFINE_WW_CLASS(crtc_ww_class);
649
650static unsigned int drm_num_crtcs(struct drm_device *dev)
651{
652 unsigned int num = 0;
653 struct drm_crtc *tmp;
654
655 drm_for_each_crtc(tmp, dev) {
656 num++;
657 }
658
659 return num;
660}
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
678 struct drm_plane *primary,
679 struct drm_plane *cursor,
680 const struct drm_crtc_funcs *funcs,
681 const char *name, ...)
682{
683 struct drm_mode_config *config = &dev->mode_config;
684 int ret;
685
686 WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY);
687 WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR);
688
689 crtc->dev = dev;
690 crtc->funcs = funcs;
691
692 drm_modeset_lock_init(&crtc->mutex);
693 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
694 if (ret)
695 return ret;
696
697 if (name) {
698 va_list ap;
699
700 va_start(ap, name);
701 crtc->name = kvasprintf(GFP_KERNEL, name, ap);
702 va_end(ap);
703 } else {
704 crtc->name = kasprintf(GFP_KERNEL, "crtc-%d",
705 drm_num_crtcs(dev));
706 }
707 if (!crtc->name) {
708 drm_mode_object_put(dev, &crtc->base);
709 return -ENOMEM;
710 }
711
712 crtc->base.properties = &crtc->properties;
713
714 list_add_tail(&crtc->head, &config->crtc_list);
715 config->num_crtc++;
716
717 crtc->primary = primary;
718 crtc->cursor = cursor;
719 if (primary)
720 primary->possible_crtcs = 1 << drm_crtc_index(crtc);
721 if (cursor)
722 cursor->possible_crtcs = 1 << drm_crtc_index(crtc);
723
724 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
725 drm_object_attach_property(&crtc->base, config->prop_active, 0);
726 drm_object_attach_property(&crtc->base, config->prop_mode_id, 0);
727 }
728
729 return 0;
730}
731EXPORT_SYMBOL(drm_crtc_init_with_planes);
732
733
734
735
736
737
738
739
740
741void drm_crtc_cleanup(struct drm_crtc *crtc)
742{
743 struct drm_device *dev = crtc->dev;
744
745 kfree(crtc->gamma_store);
746 crtc->gamma_store = NULL;
747
748 drm_modeset_lock_fini(&crtc->mutex);
749
750 drm_mode_object_put(dev, &crtc->base);
751 list_del(&crtc->head);
752 dev->mode_config.num_crtc--;
753
754 WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state);
755 if (crtc->state && crtc->funcs->atomic_destroy_state)
756 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
757
758 kfree(crtc->name);
759
760 memset(crtc, 0, sizeof(*crtc));
761}
762EXPORT_SYMBOL(drm_crtc_cleanup);
763
764
765
766
767
768
769
770
771unsigned int drm_crtc_index(struct drm_crtc *crtc)
772{
773 unsigned int index = 0;
774 struct drm_crtc *tmp;
775
776 drm_for_each_crtc(tmp, crtc->dev) {
777 if (tmp == crtc)
778 return index;
779
780 index++;
781 }
782
783 BUG();
784}
785EXPORT_SYMBOL(drm_crtc_index);
786
787
788
789
790
791
792
793
794static void drm_mode_remove(struct drm_connector *connector,
795 struct drm_display_mode *mode)
796{
797 list_del(&mode->head);
798 drm_mode_destroy(connector->dev, mode);
799}
800
801
802
803
804
805
806
807
808
809
810
811int drm_display_info_set_bus_formats(struct drm_display_info *info,
812 const u32 *formats,
813 unsigned int num_formats)
814{
815 u32 *fmts = NULL;
816
817 if (!formats && num_formats)
818 return -EINVAL;
819
820 if (formats && num_formats) {
821 fmts = kmemdup(formats, sizeof(*formats) * num_formats,
822 GFP_KERNEL);
823 if (!fmts)
824 return -ENOMEM;
825 }
826
827 kfree(info->bus_formats);
828 info->bus_formats = fmts;
829 info->num_bus_formats = num_formats;
830
831 return 0;
832}
833EXPORT_SYMBOL(drm_display_info_set_bus_formats);
834
835
836
837
838
839
840
841
842
843
844
845static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
846{
847 struct drm_cmdline_mode *mode = &connector->cmdline_mode;
848 char *option = NULL;
849
850 if (fb_get_options(connector->name, &option))
851 return;
852
853 if (!drm_mode_parse_command_line_for_connector(option,
854 connector,
855 mode))
856 return;
857
858 if (mode->force) {
859 const char *s;
860
861 switch (mode->force) {
862 case DRM_FORCE_OFF:
863 s = "OFF";
864 break;
865 case DRM_FORCE_ON_DIGITAL:
866 s = "ON - dig";
867 break;
868 default:
869 case DRM_FORCE_ON:
870 s = "ON";
871 break;
872 }
873
874 DRM_INFO("forcing %s connector %s\n", connector->name, s);
875 connector->force = mode->force;
876 }
877
878 DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
879 connector->name,
880 mode->xres, mode->yres,
881 mode->refresh_specified ? mode->refresh : 60,
882 mode->rb ? " reduced blanking" : "",
883 mode->margins ? " with margins" : "",
884 mode->interlace ? " interlaced" : "");
885}
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900int drm_connector_init(struct drm_device *dev,
901 struct drm_connector *connector,
902 const struct drm_connector_funcs *funcs,
903 int connector_type)
904{
905 struct drm_mode_config *config = &dev->mode_config;
906 int ret;
907 struct ida *connector_ida =
908 &drm_connector_enum_list[connector_type].ida;
909
910 drm_modeset_lock_all(dev);
911
912 ret = drm_mode_object_get_reg(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR, false);
913 if (ret)
914 goto out_unlock;
915
916 connector->base.properties = &connector->properties;
917 connector->dev = dev;
918 connector->funcs = funcs;
919
920 connector->connector_id = ida_simple_get(&config->connector_ida, 0, 0, GFP_KERNEL);
921 if (connector->connector_id < 0) {
922 ret = connector->connector_id;
923 goto out_put;
924 }
925
926 connector->connector_type = connector_type;
927 connector->connector_type_id =
928 ida_simple_get(connector_ida, 1, 0, GFP_KERNEL);
929 if (connector->connector_type_id < 0) {
930 ret = connector->connector_type_id;
931 goto out_put_id;
932 }
933 connector->name =
934 kasprintf(GFP_KERNEL, "%s-%d",
935 drm_connector_enum_list[connector_type].name,
936 connector->connector_type_id);
937 if (!connector->name) {
938 ret = -ENOMEM;
939 goto out_put_type_id;
940 }
941
942 INIT_LIST_HEAD(&connector->probed_modes);
943 INIT_LIST_HEAD(&connector->modes);
944 connector->edid_blob_ptr = NULL;
945 connector->status = connector_status_unknown;
946
947 drm_connector_get_cmdline_mode(connector);
948
949
950
951 list_add_tail(&connector->head, &config->connector_list);
952 config->num_connector++;
953
954 if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
955 drm_object_attach_property(&connector->base,
956 config->edid_property,
957 0);
958
959 drm_object_attach_property(&connector->base,
960 config->dpms_property, 0);
961
962 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
963 drm_object_attach_property(&connector->base, config->prop_crtc_id, 0);
964 }
965
966 connector->debugfs_entry = NULL;
967out_put_type_id:
968 if (ret)
969 ida_remove(connector_ida, connector->connector_type_id);
970out_put_id:
971 if (ret)
972 ida_remove(&config->connector_ida, connector->connector_id);
973out_put:
974 if (ret)
975 drm_mode_object_put(dev, &connector->base);
976
977out_unlock:
978 drm_modeset_unlock_all(dev);
979
980 return ret;
981}
982EXPORT_SYMBOL(drm_connector_init);
983
984
985
986
987
988
989
990void drm_connector_cleanup(struct drm_connector *connector)
991{
992 struct drm_device *dev = connector->dev;
993 struct drm_display_mode *mode, *t;
994
995 if (connector->tile_group) {
996 drm_mode_put_tile_group(dev, connector->tile_group);
997 connector->tile_group = NULL;
998 }
999
1000 list_for_each_entry_safe(mode, t, &connector->probed_modes, head)
1001 drm_mode_remove(connector, mode);
1002
1003 list_for_each_entry_safe(mode, t, &connector->modes, head)
1004 drm_mode_remove(connector, mode);
1005
1006 ida_remove(&drm_connector_enum_list[connector->connector_type].ida,
1007 connector->connector_type_id);
1008
1009 ida_remove(&dev->mode_config.connector_ida,
1010 connector->connector_id);
1011
1012 kfree(connector->display_info.bus_formats);
1013 drm_mode_object_put(dev, &connector->base);
1014 kfree(connector->name);
1015 connector->name = NULL;
1016 list_del(&connector->head);
1017 dev->mode_config.num_connector--;
1018
1019 WARN_ON(connector->state && !connector->funcs->atomic_destroy_state);
1020 if (connector->state && connector->funcs->atomic_destroy_state)
1021 connector->funcs->atomic_destroy_state(connector,
1022 connector->state);
1023
1024 memset(connector, 0, sizeof(*connector));
1025}
1026EXPORT_SYMBOL(drm_connector_cleanup);
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037int drm_connector_register(struct drm_connector *connector)
1038{
1039 int ret;
1040
1041 drm_mode_object_register(connector->dev, &connector->base);
1042
1043 ret = drm_sysfs_connector_add(connector);
1044 if (ret)
1045 return ret;
1046
1047 ret = drm_debugfs_connector_add(connector);
1048 if (ret) {
1049 drm_sysfs_connector_remove(connector);
1050 return ret;
1051 }
1052
1053 return 0;
1054}
1055EXPORT_SYMBOL(drm_connector_register);
1056
1057
1058
1059
1060
1061
1062
1063void drm_connector_unregister(struct drm_connector *connector)
1064{
1065 drm_sysfs_connector_remove(connector);
1066 drm_debugfs_connector_remove(connector);
1067}
1068EXPORT_SYMBOL(drm_connector_unregister);
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079void drm_connector_unplug_all(struct drm_device *dev)
1080{
1081 struct drm_connector *connector;
1082
1083
1084 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
1085 drm_connector_unregister(connector);
1086
1087}
1088EXPORT_SYMBOL(drm_connector_unplug_all);
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104int drm_encoder_init(struct drm_device *dev,
1105 struct drm_encoder *encoder,
1106 const struct drm_encoder_funcs *funcs,
1107 int encoder_type, const char *name, ...)
1108{
1109 int ret;
1110
1111 drm_modeset_lock_all(dev);
1112
1113 ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
1114 if (ret)
1115 goto out_unlock;
1116
1117 encoder->dev = dev;
1118 encoder->encoder_type = encoder_type;
1119 encoder->funcs = funcs;
1120 if (name) {
1121 va_list ap;
1122
1123 va_start(ap, name);
1124 encoder->name = kvasprintf(GFP_KERNEL, name, ap);
1125 va_end(ap);
1126 } else {
1127 encoder->name = kasprintf(GFP_KERNEL, "%s-%d",
1128 drm_encoder_enum_list[encoder_type].name,
1129 encoder->base.id);
1130 }
1131 if (!encoder->name) {
1132 ret = -ENOMEM;
1133 goto out_put;
1134 }
1135
1136 list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
1137 dev->mode_config.num_encoder++;
1138
1139out_put:
1140 if (ret)
1141 drm_mode_object_put(dev, &encoder->base);
1142
1143out_unlock:
1144 drm_modeset_unlock_all(dev);
1145
1146 return ret;
1147}
1148EXPORT_SYMBOL(drm_encoder_init);
1149
1150
1151
1152
1153
1154
1155
1156
1157unsigned int drm_encoder_index(struct drm_encoder *encoder)
1158{
1159 unsigned int index = 0;
1160 struct drm_encoder *tmp;
1161
1162 drm_for_each_encoder(tmp, encoder->dev) {
1163 if (tmp == encoder)
1164 return index;
1165
1166 index++;
1167 }
1168
1169 BUG();
1170}
1171EXPORT_SYMBOL(drm_encoder_index);
1172
1173
1174
1175
1176
1177
1178
1179void drm_encoder_cleanup(struct drm_encoder *encoder)
1180{
1181 struct drm_device *dev = encoder->dev;
1182
1183 drm_modeset_lock_all(dev);
1184 drm_mode_object_put(dev, &encoder->base);
1185 kfree(encoder->name);
1186 list_del(&encoder->head);
1187 dev->mode_config.num_encoder--;
1188 drm_modeset_unlock_all(dev);
1189
1190 memset(encoder, 0, sizeof(*encoder));
1191}
1192EXPORT_SYMBOL(drm_encoder_cleanup);
1193
1194static unsigned int drm_num_planes(struct drm_device *dev)
1195{
1196 unsigned int num = 0;
1197 struct drm_plane *tmp;
1198
1199 drm_for_each_plane(tmp, dev) {
1200 num++;
1201 }
1202
1203 return num;
1204}
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
1223 unsigned long possible_crtcs,
1224 const struct drm_plane_funcs *funcs,
1225 const uint32_t *formats, unsigned int format_count,
1226 enum drm_plane_type type,
1227 const char *name, ...)
1228{
1229 struct drm_mode_config *config = &dev->mode_config;
1230 int ret;
1231
1232 ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
1233 if (ret)
1234 return ret;
1235
1236 drm_modeset_lock_init(&plane->mutex);
1237
1238 plane->base.properties = &plane->properties;
1239 plane->dev = dev;
1240 plane->funcs = funcs;
1241 plane->format_types = kmalloc_array(format_count, sizeof(uint32_t),
1242 GFP_KERNEL);
1243 if (!plane->format_types) {
1244 DRM_DEBUG_KMS("out of memory when allocating plane\n");
1245 drm_mode_object_put(dev, &plane->base);
1246 return -ENOMEM;
1247 }
1248
1249 if (name) {
1250 va_list ap;
1251
1252 va_start(ap, name);
1253 plane->name = kvasprintf(GFP_KERNEL, name, ap);
1254 va_end(ap);
1255 } else {
1256 plane->name = kasprintf(GFP_KERNEL, "plane-%d",
1257 drm_num_planes(dev));
1258 }
1259 if (!plane->name) {
1260 kfree(plane->format_types);
1261 drm_mode_object_put(dev, &plane->base);
1262 return -ENOMEM;
1263 }
1264
1265 memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
1266 plane->format_count = format_count;
1267 plane->possible_crtcs = possible_crtcs;
1268 plane->type = type;
1269
1270 list_add_tail(&plane->head, &config->plane_list);
1271 config->num_total_plane++;
1272 if (plane->type == DRM_PLANE_TYPE_OVERLAY)
1273 config->num_overlay_plane++;
1274
1275 drm_object_attach_property(&plane->base,
1276 config->plane_type_property,
1277 plane->type);
1278
1279 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
1280 drm_object_attach_property(&plane->base, config->prop_fb_id, 0);
1281 drm_object_attach_property(&plane->base, config->prop_crtc_id, 0);
1282 drm_object_attach_property(&plane->base, config->prop_crtc_x, 0);
1283 drm_object_attach_property(&plane->base, config->prop_crtc_y, 0);
1284 drm_object_attach_property(&plane->base, config->prop_crtc_w, 0);
1285 drm_object_attach_property(&plane->base, config->prop_crtc_h, 0);
1286 drm_object_attach_property(&plane->base, config->prop_src_x, 0);
1287 drm_object_attach_property(&plane->base, config->prop_src_y, 0);
1288 drm_object_attach_property(&plane->base, config->prop_src_w, 0);
1289 drm_object_attach_property(&plane->base, config->prop_src_h, 0);
1290 }
1291
1292 return 0;
1293}
1294EXPORT_SYMBOL(drm_universal_plane_init);
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
1314 unsigned long possible_crtcs,
1315 const struct drm_plane_funcs *funcs,
1316 const uint32_t *formats, unsigned int format_count,
1317 bool is_primary)
1318{
1319 enum drm_plane_type type;
1320
1321 type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
1322 return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
1323 formats, format_count, type, NULL);
1324}
1325EXPORT_SYMBOL(drm_plane_init);
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335void drm_plane_cleanup(struct drm_plane *plane)
1336{
1337 struct drm_device *dev = plane->dev;
1338
1339 drm_modeset_lock_all(dev);
1340 kfree(plane->format_types);
1341 drm_mode_object_put(dev, &plane->base);
1342
1343 BUG_ON(list_empty(&plane->head));
1344
1345 list_del(&plane->head);
1346 dev->mode_config.num_total_plane--;
1347 if (plane->type == DRM_PLANE_TYPE_OVERLAY)
1348 dev->mode_config.num_overlay_plane--;
1349 drm_modeset_unlock_all(dev);
1350
1351 WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
1352 if (plane->state && plane->funcs->atomic_destroy_state)
1353 plane->funcs->atomic_destroy_state(plane, plane->state);
1354
1355 kfree(plane->name);
1356
1357 memset(plane, 0, sizeof(*plane));
1358}
1359EXPORT_SYMBOL(drm_plane_cleanup);
1360
1361
1362
1363
1364
1365
1366
1367
1368unsigned int drm_plane_index(struct drm_plane *plane)
1369{
1370 unsigned int index = 0;
1371 struct drm_plane *tmp;
1372
1373 drm_for_each_plane(tmp, plane->dev) {
1374 if (tmp == plane)
1375 return index;
1376
1377 index++;
1378 }
1379
1380 BUG();
1381}
1382EXPORT_SYMBOL(drm_plane_index);
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392struct drm_plane *
1393drm_plane_from_index(struct drm_device *dev, int idx)
1394{
1395 struct drm_plane *plane;
1396 unsigned int i = 0;
1397
1398 drm_for_each_plane(plane, dev) {
1399 if (i == idx)
1400 return plane;
1401 i++;
1402 }
1403 return NULL;
1404}
1405EXPORT_SYMBOL(drm_plane_from_index);
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416void drm_plane_force_disable(struct drm_plane *plane)
1417{
1418 int ret;
1419
1420 if (!plane->fb)
1421 return;
1422
1423 plane->old_fb = plane->fb;
1424 ret = plane->funcs->disable_plane(plane);
1425 if (ret) {
1426 DRM_ERROR("failed to disable plane with busy fb\n");
1427 plane->old_fb = NULL;
1428 return;
1429 }
1430
1431 drm_framebuffer_unreference(plane->old_fb);
1432 plane->old_fb = NULL;
1433 plane->fb = NULL;
1434 plane->crtc = NULL;
1435}
1436EXPORT_SYMBOL(drm_plane_force_disable);
1437
1438static int drm_mode_create_standard_properties(struct drm_device *dev)
1439{
1440 struct drm_property *prop;
1441
1442
1443
1444
1445 prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
1446 DRM_MODE_PROP_IMMUTABLE,
1447 "EDID", 0);
1448 if (!prop)
1449 return -ENOMEM;
1450 dev->mode_config.edid_property = prop;
1451
1452 prop = drm_property_create_enum(dev, 0,
1453 "DPMS", drm_dpms_enum_list,
1454 ARRAY_SIZE(drm_dpms_enum_list));
1455 if (!prop)
1456 return -ENOMEM;
1457 dev->mode_config.dpms_property = prop;
1458
1459 prop = drm_property_create(dev,
1460 DRM_MODE_PROP_BLOB |
1461 DRM_MODE_PROP_IMMUTABLE,
1462 "PATH", 0);
1463 if (!prop)
1464 return -ENOMEM;
1465 dev->mode_config.path_property = prop;
1466
1467 prop = drm_property_create(dev,
1468 DRM_MODE_PROP_BLOB |
1469 DRM_MODE_PROP_IMMUTABLE,
1470 "TILE", 0);
1471 if (!prop)
1472 return -ENOMEM;
1473 dev->mode_config.tile_property = prop;
1474
1475 prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1476 "type", drm_plane_type_enum_list,
1477 ARRAY_SIZE(drm_plane_type_enum_list));
1478 if (!prop)
1479 return -ENOMEM;
1480 dev->mode_config.plane_type_property = prop;
1481
1482 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
1483 "SRC_X", 0, UINT_MAX);
1484 if (!prop)
1485 return -ENOMEM;
1486 dev->mode_config.prop_src_x = prop;
1487
1488 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
1489 "SRC_Y", 0, UINT_MAX);
1490 if (!prop)
1491 return -ENOMEM;
1492 dev->mode_config.prop_src_y = prop;
1493
1494 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
1495 "SRC_W", 0, UINT_MAX);
1496 if (!prop)
1497 return -ENOMEM;
1498 dev->mode_config.prop_src_w = prop;
1499
1500 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
1501 "SRC_H", 0, UINT_MAX);
1502 if (!prop)
1503 return -ENOMEM;
1504 dev->mode_config.prop_src_h = prop;
1505
1506 prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
1507 "CRTC_X", INT_MIN, INT_MAX);
1508 if (!prop)
1509 return -ENOMEM;
1510 dev->mode_config.prop_crtc_x = prop;
1511
1512 prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
1513 "CRTC_Y", INT_MIN, INT_MAX);
1514 if (!prop)
1515 return -ENOMEM;
1516 dev->mode_config.prop_crtc_y = prop;
1517
1518 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
1519 "CRTC_W", 0, INT_MAX);
1520 if (!prop)
1521 return -ENOMEM;
1522 dev->mode_config.prop_crtc_w = prop;
1523
1524 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
1525 "CRTC_H", 0, INT_MAX);
1526 if (!prop)
1527 return -ENOMEM;
1528 dev->mode_config.prop_crtc_h = prop;
1529
1530 prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
1531 "FB_ID", DRM_MODE_OBJECT_FB);
1532 if (!prop)
1533 return -ENOMEM;
1534 dev->mode_config.prop_fb_id = prop;
1535
1536 prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
1537 "CRTC_ID", DRM_MODE_OBJECT_CRTC);
1538 if (!prop)
1539 return -ENOMEM;
1540 dev->mode_config.prop_crtc_id = prop;
1541
1542 prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
1543 "ACTIVE");
1544 if (!prop)
1545 return -ENOMEM;
1546 dev->mode_config.prop_active = prop;
1547
1548 prop = drm_property_create(dev,
1549 DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB,
1550 "MODE_ID", 0);
1551 if (!prop)
1552 return -ENOMEM;
1553 dev->mode_config.prop_mode_id = prop;
1554
1555 prop = drm_property_create(dev,
1556 DRM_MODE_PROP_BLOB,
1557 "DEGAMMA_LUT", 0);
1558 if (!prop)
1559 return -ENOMEM;
1560 dev->mode_config.degamma_lut_property = prop;
1561
1562 prop = drm_property_create_range(dev,
1563 DRM_MODE_PROP_IMMUTABLE,
1564 "DEGAMMA_LUT_SIZE", 0, UINT_MAX);
1565 if (!prop)
1566 return -ENOMEM;
1567 dev->mode_config.degamma_lut_size_property = prop;
1568
1569 prop = drm_property_create(dev,
1570 DRM_MODE_PROP_BLOB,
1571 "CTM", 0);
1572 if (!prop)
1573 return -ENOMEM;
1574 dev->mode_config.ctm_property = prop;
1575
1576 prop = drm_property_create(dev,
1577 DRM_MODE_PROP_BLOB,
1578 "GAMMA_LUT", 0);
1579 if (!prop)
1580 return -ENOMEM;
1581 dev->mode_config.gamma_lut_property = prop;
1582
1583 prop = drm_property_create_range(dev,
1584 DRM_MODE_PROP_IMMUTABLE,
1585 "GAMMA_LUT_SIZE", 0, UINT_MAX);
1586 if (!prop)
1587 return -ENOMEM;
1588 dev->mode_config.gamma_lut_size_property = prop;
1589
1590 return 0;
1591}
1592
1593
1594
1595
1596
1597
1598
1599int drm_mode_create_dvi_i_properties(struct drm_device *dev)
1600{
1601 struct drm_property *dvi_i_selector;
1602 struct drm_property *dvi_i_subconnector;
1603
1604 if (dev->mode_config.dvi_i_select_subconnector_property)
1605 return 0;
1606
1607 dvi_i_selector =
1608 drm_property_create_enum(dev, 0,
1609 "select subconnector",
1610 drm_dvi_i_select_enum_list,
1611 ARRAY_SIZE(drm_dvi_i_select_enum_list));
1612 dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector;
1613
1614 dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1615 "subconnector",
1616 drm_dvi_i_subconnector_enum_list,
1617 ARRAY_SIZE(drm_dvi_i_subconnector_enum_list));
1618 dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector;
1619
1620 return 0;
1621}
1622EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635int drm_mode_create_tv_properties(struct drm_device *dev,
1636 unsigned int num_modes,
1637 const char * const modes[])
1638{
1639 struct drm_property *tv_selector;
1640 struct drm_property *tv_subconnector;
1641 unsigned int i;
1642
1643 if (dev->mode_config.tv_select_subconnector_property)
1644 return 0;
1645
1646
1647
1648
1649 tv_selector = drm_property_create_enum(dev, 0,
1650 "select subconnector",
1651 drm_tv_select_enum_list,
1652 ARRAY_SIZE(drm_tv_select_enum_list));
1653 if (!tv_selector)
1654 goto nomem;
1655
1656 dev->mode_config.tv_select_subconnector_property = tv_selector;
1657
1658 tv_subconnector =
1659 drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1660 "subconnector",
1661 drm_tv_subconnector_enum_list,
1662 ARRAY_SIZE(drm_tv_subconnector_enum_list));
1663 if (!tv_subconnector)
1664 goto nomem;
1665 dev->mode_config.tv_subconnector_property = tv_subconnector;
1666
1667
1668
1669
1670 dev->mode_config.tv_left_margin_property =
1671 drm_property_create_range(dev, 0, "left margin", 0, 100);
1672 if (!dev->mode_config.tv_left_margin_property)
1673 goto nomem;
1674
1675 dev->mode_config.tv_right_margin_property =
1676 drm_property_create_range(dev, 0, "right margin", 0, 100);
1677 if (!dev->mode_config.tv_right_margin_property)
1678 goto nomem;
1679
1680 dev->mode_config.tv_top_margin_property =
1681 drm_property_create_range(dev, 0, "top margin", 0, 100);
1682 if (!dev->mode_config.tv_top_margin_property)
1683 goto nomem;
1684
1685 dev->mode_config.tv_bottom_margin_property =
1686 drm_property_create_range(dev, 0, "bottom margin", 0, 100);
1687 if (!dev->mode_config.tv_bottom_margin_property)
1688 goto nomem;
1689
1690 dev->mode_config.tv_mode_property =
1691 drm_property_create(dev, DRM_MODE_PROP_ENUM,
1692 "mode", num_modes);
1693 if (!dev->mode_config.tv_mode_property)
1694 goto nomem;
1695
1696 for (i = 0; i < num_modes; i++)
1697 drm_property_add_enum(dev->mode_config.tv_mode_property, i,
1698 i, modes[i]);
1699
1700 dev->mode_config.tv_brightness_property =
1701 drm_property_create_range(dev, 0, "brightness", 0, 100);
1702 if (!dev->mode_config.tv_brightness_property)
1703 goto nomem;
1704
1705 dev->mode_config.tv_contrast_property =
1706 drm_property_create_range(dev, 0, "contrast", 0, 100);
1707 if (!dev->mode_config.tv_contrast_property)
1708 goto nomem;
1709
1710 dev->mode_config.tv_flicker_reduction_property =
1711 drm_property_create_range(dev, 0, "flicker reduction", 0, 100);
1712 if (!dev->mode_config.tv_flicker_reduction_property)
1713 goto nomem;
1714
1715 dev->mode_config.tv_overscan_property =
1716 drm_property_create_range(dev, 0, "overscan", 0, 100);
1717 if (!dev->mode_config.tv_overscan_property)
1718 goto nomem;
1719
1720 dev->mode_config.tv_saturation_property =
1721 drm_property_create_range(dev, 0, "saturation", 0, 100);
1722 if (!dev->mode_config.tv_saturation_property)
1723 goto nomem;
1724
1725 dev->mode_config.tv_hue_property =
1726 drm_property_create_range(dev, 0, "hue", 0, 100);
1727 if (!dev->mode_config.tv_hue_property)
1728 goto nomem;
1729
1730 return 0;
1731nomem:
1732 return -ENOMEM;
1733}
1734EXPORT_SYMBOL(drm_mode_create_tv_properties);
1735
1736
1737
1738
1739
1740
1741
1742
1743int drm_mode_create_scaling_mode_property(struct drm_device *dev)
1744{
1745 struct drm_property *scaling_mode;
1746
1747 if (dev->mode_config.scaling_mode_property)
1748 return 0;
1749
1750 scaling_mode =
1751 drm_property_create_enum(dev, 0, "scaling mode",
1752 drm_scaling_mode_enum_list,
1753 ARRAY_SIZE(drm_scaling_mode_enum_list));
1754
1755 dev->mode_config.scaling_mode_property = scaling_mode;
1756
1757 return 0;
1758}
1759EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771int drm_mode_create_aspect_ratio_property(struct drm_device *dev)
1772{
1773 if (dev->mode_config.aspect_ratio_property)
1774 return 0;
1775
1776 dev->mode_config.aspect_ratio_property =
1777 drm_property_create_enum(dev, 0, "aspect ratio",
1778 drm_aspect_ratio_enum_list,
1779 ARRAY_SIZE(drm_aspect_ratio_enum_list));
1780
1781 if (dev->mode_config.aspect_ratio_property == NULL)
1782 return -ENOMEM;
1783
1784 return 0;
1785}
1786EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
1787
1788
1789
1790
1791
1792
1793
1794
1795int drm_mode_create_dirty_info_property(struct drm_device *dev)
1796{
1797 struct drm_property *dirty_info;
1798
1799 if (dev->mode_config.dirty_info_property)
1800 return 0;
1801
1802 dirty_info =
1803 drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1804 "dirty",
1805 drm_dirty_info_enum_list,
1806 ARRAY_SIZE(drm_dirty_info_enum_list));
1807 dev->mode_config.dirty_info_property = dirty_info;
1808
1809 return 0;
1810}
1811EXPORT_SYMBOL(drm_mode_create_dirty_info_property);
1812
1813
1814
1815
1816
1817
1818
1819int drm_mode_create_suggested_offset_properties(struct drm_device *dev)
1820{
1821 if (dev->mode_config.suggested_x_property && dev->mode_config.suggested_y_property)
1822 return 0;
1823
1824 dev->mode_config.suggested_x_property =
1825 drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested X", 0, 0xffffffff);
1826
1827 dev->mode_config.suggested_y_property =
1828 drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested Y", 0, 0xffffffff);
1829
1830 if (dev->mode_config.suggested_x_property == NULL ||
1831 dev->mode_config.suggested_y_property == NULL)
1832 return -ENOMEM;
1833 return 0;
1834}
1835EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties);
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851int drm_mode_getresources(struct drm_device *dev, void *data,
1852 struct drm_file *file_priv)
1853{
1854 struct drm_mode_card_res *card_res = data;
1855 struct list_head *lh;
1856 struct drm_framebuffer *fb;
1857 struct drm_connector *connector;
1858 struct drm_crtc *crtc;
1859 struct drm_encoder *encoder;
1860 int ret = 0;
1861 int connector_count = 0;
1862 int crtc_count = 0;
1863 int fb_count = 0;
1864 int encoder_count = 0;
1865 int copied = 0;
1866 uint32_t __user *fb_id;
1867 uint32_t __user *crtc_id;
1868 uint32_t __user *connector_id;
1869 uint32_t __user *encoder_id;
1870
1871 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1872 return -EINVAL;
1873
1874
1875 mutex_lock(&file_priv->fbs_lock);
1876
1877
1878
1879
1880 list_for_each(lh, &file_priv->fbs)
1881 fb_count++;
1882
1883
1884
1885 if (card_res->count_fbs >= fb_count) {
1886 copied = 0;
1887 fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
1888 list_for_each_entry(fb, &file_priv->fbs, filp_head) {
1889 if (put_user(fb->base.id, fb_id + copied)) {
1890 mutex_unlock(&file_priv->fbs_lock);
1891 return -EFAULT;
1892 }
1893 copied++;
1894 }
1895 }
1896 card_res->count_fbs = fb_count;
1897 mutex_unlock(&file_priv->fbs_lock);
1898
1899
1900
1901 mutex_lock(&dev->mode_config.mutex);
1902 drm_for_each_crtc(crtc, dev)
1903 crtc_count++;
1904
1905 drm_for_each_connector(connector, dev)
1906 connector_count++;
1907
1908 drm_for_each_encoder(encoder, dev)
1909 encoder_count++;
1910
1911 card_res->max_height = dev->mode_config.max_height;
1912 card_res->min_height = dev->mode_config.min_height;
1913 card_res->max_width = dev->mode_config.max_width;
1914 card_res->min_width = dev->mode_config.min_width;
1915
1916
1917 if (card_res->count_crtcs >= crtc_count) {
1918 copied = 0;
1919 crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
1920 drm_for_each_crtc(crtc, dev) {
1921 DRM_DEBUG_KMS("[CRTC:%d:%s]\n",
1922 crtc->base.id, crtc->name);
1923 if (put_user(crtc->base.id, crtc_id + copied)) {
1924 ret = -EFAULT;
1925 goto out;
1926 }
1927 copied++;
1928 }
1929 }
1930 card_res->count_crtcs = crtc_count;
1931
1932
1933 if (card_res->count_encoders >= encoder_count) {
1934 copied = 0;
1935 encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
1936 drm_for_each_encoder(encoder, dev) {
1937 DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id,
1938 encoder->name);
1939 if (put_user(encoder->base.id, encoder_id +
1940 copied)) {
1941 ret = -EFAULT;
1942 goto out;
1943 }
1944 copied++;
1945 }
1946 }
1947 card_res->count_encoders = encoder_count;
1948
1949
1950 if (card_res->count_connectors >= connector_count) {
1951 copied = 0;
1952 connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
1953 drm_for_each_connector(connector, dev) {
1954 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
1955 connector->base.id,
1956 connector->name);
1957 if (put_user(connector->base.id,
1958 connector_id + copied)) {
1959 ret = -EFAULT;
1960 goto out;
1961 }
1962 copied++;
1963 }
1964 }
1965 card_res->count_connectors = connector_count;
1966
1967 DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs,
1968 card_res->count_connectors, card_res->count_encoders);
1969
1970out:
1971 mutex_unlock(&dev->mode_config.mutex);
1972 return ret;
1973}
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988int drm_mode_getcrtc(struct drm_device *dev,
1989 void *data, struct drm_file *file_priv)
1990{
1991 struct drm_mode_crtc *crtc_resp = data;
1992 struct drm_crtc *crtc;
1993
1994 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1995 return -EINVAL;
1996
1997 crtc = drm_crtc_find(dev, crtc_resp->crtc_id);
1998 if (!crtc)
1999 return -ENOENT;
2000
2001 drm_modeset_lock_crtc(crtc, crtc->primary);
2002 crtc_resp->gamma_size = crtc->gamma_size;
2003 if (crtc->primary->fb)
2004 crtc_resp->fb_id = crtc->primary->fb->base.id;
2005 else
2006 crtc_resp->fb_id = 0;
2007
2008 if (crtc->state) {
2009 crtc_resp->x = crtc->primary->state->src_x >> 16;
2010 crtc_resp->y = crtc->primary->state->src_y >> 16;
2011 if (crtc->state->enable) {
2012 drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
2013 crtc_resp->mode_valid = 1;
2014
2015 } else {
2016 crtc_resp->mode_valid = 0;
2017 }
2018 } else {
2019 crtc_resp->x = crtc->x;
2020 crtc_resp->y = crtc->y;
2021 if (crtc->enabled) {
2022 drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode);
2023 crtc_resp->mode_valid = 1;
2024
2025 } else {
2026 crtc_resp->mode_valid = 0;
2027 }
2028 }
2029 drm_modeset_unlock_crtc(crtc);
2030
2031 return 0;
2032}
2033
2034static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
2035 const struct drm_file *file_priv)
2036{
2037
2038
2039
2040
2041 if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode))
2042 return false;
2043
2044 return true;
2045}
2046
2047static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector)
2048{
2049
2050
2051 if (connector->state)
2052 return connector->state->best_encoder;
2053 return connector->encoder;
2054}
2055
2056
2057static int get_properties(struct drm_mode_object *obj, bool atomic,
2058 uint32_t __user *prop_ptr, uint64_t __user *prop_values,
2059 uint32_t *arg_count_props)
2060{
2061 int props_count;
2062 int i, ret, copied;
2063
2064 props_count = obj->properties->count;
2065 if (!atomic)
2066 props_count -= obj->properties->atomic_count;
2067
2068 if ((*arg_count_props >= props_count) && props_count) {
2069 for (i = 0, copied = 0; copied < props_count; i++) {
2070 struct drm_property *prop = obj->properties->properties[i];
2071 uint64_t val;
2072
2073 if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic)
2074 continue;
2075
2076 ret = drm_object_property_get_value(obj, prop, &val);
2077 if (ret)
2078 return ret;
2079
2080 if (put_user(prop->base.id, prop_ptr + copied))
2081 return -EFAULT;
2082
2083 if (put_user(val, prop_values + copied))
2084 return -EFAULT;
2085
2086 copied++;
2087 }
2088 }
2089 *arg_count_props = props_count;
2090
2091 return 0;
2092}
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107int drm_mode_getconnector(struct drm_device *dev, void *data,
2108 struct drm_file *file_priv)
2109{
2110 struct drm_mode_get_connector *out_resp = data;
2111 struct drm_connector *connector;
2112 struct drm_encoder *encoder;
2113 struct drm_display_mode *mode;
2114 int mode_count = 0;
2115 int encoders_count = 0;
2116 int ret = 0;
2117 int copied = 0;
2118 int i;
2119 struct drm_mode_modeinfo u_mode;
2120 struct drm_mode_modeinfo __user *mode_ptr;
2121 uint32_t __user *encoder_ptr;
2122
2123 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2124 return -EINVAL;
2125
2126 memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
2127
2128 DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
2129
2130 mutex_lock(&dev->mode_config.mutex);
2131
2132 connector = drm_connector_find(dev, out_resp->connector_id);
2133 if (!connector) {
2134 ret = -ENOENT;
2135 goto out_unlock;
2136 }
2137
2138 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
2139 if (connector->encoder_ids[i] != 0)
2140 encoders_count++;
2141
2142 if (out_resp->count_modes == 0) {
2143 connector->funcs->fill_modes(connector,
2144 dev->mode_config.max_width,
2145 dev->mode_config.max_height);
2146 }
2147
2148
2149 list_for_each_entry(mode, &connector->modes, head)
2150 if (drm_mode_expose_to_userspace(mode, file_priv))
2151 mode_count++;
2152
2153 out_resp->connector_id = connector->base.id;
2154 out_resp->connector_type = connector->connector_type;
2155 out_resp->connector_type_id = connector->connector_type_id;
2156 out_resp->mm_width = connector->display_info.width_mm;
2157 out_resp->mm_height = connector->display_info.height_mm;
2158 out_resp->subpixel = connector->display_info.subpixel_order;
2159 out_resp->connection = connector->status;
2160
2161 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
2162 encoder = drm_connector_get_encoder(connector);
2163 if (encoder)
2164 out_resp->encoder_id = encoder->base.id;
2165 else
2166 out_resp->encoder_id = 0;
2167
2168
2169
2170
2171
2172 if ((out_resp->count_modes >= mode_count) && mode_count) {
2173 copied = 0;
2174 mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
2175 list_for_each_entry(mode, &connector->modes, head) {
2176 if (!drm_mode_expose_to_userspace(mode, file_priv))
2177 continue;
2178
2179 drm_mode_convert_to_umode(&u_mode, mode);
2180 if (copy_to_user(mode_ptr + copied,
2181 &u_mode, sizeof(u_mode))) {
2182 ret = -EFAULT;
2183 goto out;
2184 }
2185 copied++;
2186 }
2187 }
2188 out_resp->count_modes = mode_count;
2189
2190 ret = get_properties(&connector->base, file_priv->atomic,
2191 (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
2192 (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
2193 &out_resp->count_props);
2194 if (ret)
2195 goto out;
2196
2197 if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
2198 copied = 0;
2199 encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
2200 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
2201 if (connector->encoder_ids[i] != 0) {
2202 if (put_user(connector->encoder_ids[i],
2203 encoder_ptr + copied)) {
2204 ret = -EFAULT;
2205 goto out;
2206 }
2207 copied++;
2208 }
2209 }
2210 }
2211 out_resp->count_encoders = encoders_count;
2212
2213out:
2214 drm_modeset_unlock(&dev->mode_config.connection_mutex);
2215
2216out_unlock:
2217 mutex_unlock(&dev->mode_config.mutex);
2218
2219 return ret;
2220}
2221
2222static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
2223{
2224 struct drm_connector *connector;
2225 struct drm_device *dev = encoder->dev;
2226 bool uses_atomic = false;
2227
2228
2229
2230 drm_for_each_connector(connector, dev) {
2231 if (!connector->state)
2232 continue;
2233
2234 uses_atomic = true;
2235
2236 if (connector->state->best_encoder != encoder)
2237 continue;
2238
2239 return connector->state->crtc;
2240 }
2241
2242
2243 if (uses_atomic)
2244 return NULL;
2245
2246 return encoder->crtc;
2247}
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262int drm_mode_getencoder(struct drm_device *dev, void *data,
2263 struct drm_file *file_priv)
2264{
2265 struct drm_mode_get_encoder *enc_resp = data;
2266 struct drm_encoder *encoder;
2267 struct drm_crtc *crtc;
2268
2269 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2270 return -EINVAL;
2271
2272 encoder = drm_encoder_find(dev, enc_resp->encoder_id);
2273 if (!encoder)
2274 return -ENOENT;
2275
2276 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
2277 crtc = drm_encoder_get_crtc(encoder);
2278 if (crtc)
2279 enc_resp->crtc_id = crtc->base.id;
2280 else
2281 enc_resp->crtc_id = 0;
2282 drm_modeset_unlock(&dev->mode_config.connection_mutex);
2283
2284 enc_resp->encoder_type = encoder->encoder_type;
2285 enc_resp->encoder_id = encoder->base.id;
2286 enc_resp->possible_crtcs = encoder->possible_crtcs;
2287 enc_resp->possible_clones = encoder->possible_clones;
2288
2289 return 0;
2290}
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305int drm_mode_getplane_res(struct drm_device *dev, void *data,
2306 struct drm_file *file_priv)
2307{
2308 struct drm_mode_get_plane_res *plane_resp = data;
2309 struct drm_mode_config *config;
2310 struct drm_plane *plane;
2311 uint32_t __user *plane_ptr;
2312 int copied = 0;
2313 unsigned num_planes;
2314
2315 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2316 return -EINVAL;
2317
2318 config = &dev->mode_config;
2319
2320 if (file_priv->universal_planes)
2321 num_planes = config->num_total_plane;
2322 else
2323 num_planes = config->num_overlay_plane;
2324
2325
2326
2327
2328
2329 if (num_planes &&
2330 (plane_resp->count_planes >= num_planes)) {
2331 plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
2332
2333
2334 drm_for_each_plane(plane, dev) {
2335
2336
2337
2338
2339 if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
2340 !file_priv->universal_planes)
2341 continue;
2342
2343 if (put_user(plane->base.id, plane_ptr + copied))
2344 return -EFAULT;
2345 copied++;
2346 }
2347 }
2348 plane_resp->count_planes = num_planes;
2349
2350 return 0;
2351}
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366int drm_mode_getplane(struct drm_device *dev, void *data,
2367 struct drm_file *file_priv)
2368{
2369 struct drm_mode_get_plane *plane_resp = data;
2370 struct drm_plane *plane;
2371 uint32_t __user *format_ptr;
2372
2373 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2374 return -EINVAL;
2375
2376 plane = drm_plane_find(dev, plane_resp->plane_id);
2377 if (!plane)
2378 return -ENOENT;
2379
2380 drm_modeset_lock(&plane->mutex, NULL);
2381 if (plane->crtc)
2382 plane_resp->crtc_id = plane->crtc->base.id;
2383 else
2384 plane_resp->crtc_id = 0;
2385
2386 if (plane->fb)
2387 plane_resp->fb_id = plane->fb->base.id;
2388 else
2389 plane_resp->fb_id = 0;
2390 drm_modeset_unlock(&plane->mutex);
2391
2392 plane_resp->plane_id = plane->base.id;
2393 plane_resp->possible_crtcs = plane->possible_crtcs;
2394 plane_resp->gamma_size = 0;
2395
2396
2397
2398
2399
2400 if (plane->format_count &&
2401 (plane_resp->count_format_types >= plane->format_count)) {
2402 format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
2403 if (copy_to_user(format_ptr,
2404 plane->format_types,
2405 sizeof(uint32_t) * plane->format_count)) {
2406 return -EFAULT;
2407 }
2408 }
2409 plane_resp->count_format_types = plane->format_count;
2410
2411 return 0;
2412}
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format)
2424{
2425 unsigned int i;
2426
2427 for (i = 0; i < plane->format_count; i++) {
2428 if (format == plane->format_types[i])
2429 return 0;
2430 }
2431
2432 return -EINVAL;
2433}
2434
2435static int check_src_coords(uint32_t src_x, uint32_t src_y,
2436 uint32_t src_w, uint32_t src_h,
2437 const struct drm_framebuffer *fb)
2438{
2439 unsigned int fb_width, fb_height;
2440
2441 fb_width = fb->width << 16;
2442 fb_height = fb->height << 16;
2443
2444
2445 if (src_w > fb_width ||
2446 src_x > fb_width - src_w ||
2447 src_h > fb_height ||
2448 src_y > fb_height - src_h) {
2449 DRM_DEBUG_KMS("Invalid source coordinates "
2450 "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
2451 src_w >> 16, ((src_w & 0xffff) * 15625) >> 10,
2452 src_h >> 16, ((src_h & 0xffff) * 15625) >> 10,
2453 src_x >> 16, ((src_x & 0xffff) * 15625) >> 10,
2454 src_y >> 16, ((src_y & 0xffff) * 15625) >> 10);
2455 return -ENOSPC;
2456 }
2457
2458 return 0;
2459}
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470static int __setplane_internal(struct drm_plane *plane,
2471 struct drm_crtc *crtc,
2472 struct drm_framebuffer *fb,
2473 int32_t crtc_x, int32_t crtc_y,
2474 uint32_t crtc_w, uint32_t crtc_h,
2475
2476 uint32_t src_x, uint32_t src_y,
2477 uint32_t src_w, uint32_t src_h)
2478{
2479 int ret = 0;
2480
2481
2482 if (!fb) {
2483 plane->old_fb = plane->fb;
2484 ret = plane->funcs->disable_plane(plane);
2485 if (!ret) {
2486 plane->crtc = NULL;
2487 plane->fb = NULL;
2488 } else {
2489 plane->old_fb = NULL;
2490 }
2491 goto out;
2492 }
2493
2494
2495 if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
2496 DRM_DEBUG_KMS("Invalid crtc for plane\n");
2497 ret = -EINVAL;
2498 goto out;
2499 }
2500
2501
2502 ret = drm_plane_check_pixel_format(plane, fb->pixel_format);
2503 if (ret) {
2504 DRM_DEBUG_KMS("Invalid pixel format %s\n",
2505 drm_get_format_name(fb->pixel_format));
2506 goto out;
2507 }
2508
2509
2510 if (crtc_w > INT_MAX ||
2511 crtc_x > INT_MAX - (int32_t) crtc_w ||
2512 crtc_h > INT_MAX ||
2513 crtc_y > INT_MAX - (int32_t) crtc_h) {
2514 DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
2515 crtc_w, crtc_h, crtc_x, crtc_y);
2516 ret = -ERANGE;
2517 goto out;
2518 }
2519
2520 ret = check_src_coords(src_x, src_y, src_w, src_h, fb);
2521 if (ret)
2522 goto out;
2523
2524 plane->old_fb = plane->fb;
2525 ret = plane->funcs->update_plane(plane, crtc, fb,
2526 crtc_x, crtc_y, crtc_w, crtc_h,
2527 src_x, src_y, src_w, src_h);
2528 if (!ret) {
2529 plane->crtc = crtc;
2530 plane->fb = fb;
2531 fb = NULL;
2532 } else {
2533 plane->old_fb = NULL;
2534 }
2535
2536out:
2537 if (fb)
2538 drm_framebuffer_unreference(fb);
2539 if (plane->old_fb)
2540 drm_framebuffer_unreference(plane->old_fb);
2541 plane->old_fb = NULL;
2542
2543 return ret;
2544}
2545
2546static int setplane_internal(struct drm_plane *plane,
2547 struct drm_crtc *crtc,
2548 struct drm_framebuffer *fb,
2549 int32_t crtc_x, int32_t crtc_y,
2550 uint32_t crtc_w, uint32_t crtc_h,
2551
2552 uint32_t src_x, uint32_t src_y,
2553 uint32_t src_w, uint32_t src_h)
2554{
2555 int ret;
2556
2557 drm_modeset_lock_all(plane->dev);
2558 ret = __setplane_internal(plane, crtc, fb,
2559 crtc_x, crtc_y, crtc_w, crtc_h,
2560 src_x, src_y, src_w, src_h);
2561 drm_modeset_unlock_all(plane->dev);
2562
2563 return ret;
2564}
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579int drm_mode_setplane(struct drm_device *dev, void *data,
2580 struct drm_file *file_priv)
2581{
2582 struct drm_mode_set_plane *plane_req = data;
2583 struct drm_plane *plane;
2584 struct drm_crtc *crtc = NULL;
2585 struct drm_framebuffer *fb = NULL;
2586
2587 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2588 return -EINVAL;
2589
2590
2591
2592
2593
2594 plane = drm_plane_find(dev, plane_req->plane_id);
2595 if (!plane) {
2596 DRM_DEBUG_KMS("Unknown plane ID %d\n",
2597 plane_req->plane_id);
2598 return -ENOENT;
2599 }
2600
2601 if (plane_req->fb_id) {
2602 fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
2603 if (!fb) {
2604 DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
2605 plane_req->fb_id);
2606 return -ENOENT;
2607 }
2608
2609 crtc = drm_crtc_find(dev, plane_req->crtc_id);
2610 if (!crtc) {
2611 DRM_DEBUG_KMS("Unknown crtc ID %d\n",
2612 plane_req->crtc_id);
2613 return -ENOENT;
2614 }
2615 }
2616
2617
2618
2619
2620
2621 return setplane_internal(plane, crtc, fb,
2622 plane_req->crtc_x, plane_req->crtc_y,
2623 plane_req->crtc_w, plane_req->crtc_h,
2624 plane_req->src_x, plane_req->src_y,
2625 plane_req->src_w, plane_req->src_h);
2626}
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638int drm_mode_set_config_internal(struct drm_mode_set *set)
2639{
2640 struct drm_crtc *crtc = set->crtc;
2641 struct drm_framebuffer *fb;
2642 struct drm_crtc *tmp;
2643 int ret;
2644
2645
2646
2647
2648
2649
2650 drm_for_each_crtc(tmp, crtc->dev)
2651 tmp->primary->old_fb = tmp->primary->fb;
2652
2653 fb = set->fb;
2654
2655 ret = crtc->funcs->set_config(set);
2656 if (ret == 0) {
2657 crtc->primary->crtc = crtc;
2658 crtc->primary->fb = fb;
2659 }
2660
2661 drm_for_each_crtc(tmp, crtc->dev) {
2662 if (tmp->primary->fb)
2663 drm_framebuffer_reference(tmp->primary->fb);
2664 if (tmp->primary->old_fb)
2665 drm_framebuffer_unreference(tmp->primary->old_fb);
2666 tmp->primary->old_fb = NULL;
2667 }
2668
2669 return ret;
2670}
2671EXPORT_SYMBOL(drm_mode_set_config_internal);
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682void drm_crtc_get_hv_timing(const struct drm_display_mode *mode,
2683 int *hdisplay, int *vdisplay)
2684{
2685 struct drm_display_mode adjusted;
2686
2687 drm_mode_copy(&adjusted, mode);
2688 drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY);
2689 *hdisplay = adjusted.crtc_hdisplay;
2690 *vdisplay = adjusted.crtc_vdisplay;
2691}
2692EXPORT_SYMBOL(drm_crtc_get_hv_timing);
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703int drm_crtc_check_viewport(const struct drm_crtc *crtc,
2704 int x, int y,
2705 const struct drm_display_mode *mode,
2706 const struct drm_framebuffer *fb)
2707
2708{
2709 int hdisplay, vdisplay;
2710
2711 drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay);
2712
2713 if (crtc->state &&
2714 crtc->primary->state->rotation & (BIT(DRM_ROTATE_90) |
2715 BIT(DRM_ROTATE_270)))
2716 swap(hdisplay, vdisplay);
2717
2718 return check_src_coords(x << 16, y << 16,
2719 hdisplay << 16, vdisplay << 16, fb);
2720}
2721EXPORT_SYMBOL(drm_crtc_check_viewport);
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736int drm_mode_setcrtc(struct drm_device *dev, void *data,
2737 struct drm_file *file_priv)
2738{
2739 struct drm_mode_config *config = &dev->mode_config;
2740 struct drm_mode_crtc *crtc_req = data;
2741 struct drm_crtc *crtc;
2742 struct drm_connector **connector_set = NULL, *connector;
2743 struct drm_framebuffer *fb = NULL;
2744 struct drm_display_mode *mode = NULL;
2745 struct drm_mode_set set;
2746 uint32_t __user *set_connectors_ptr;
2747 int ret;
2748 int i;
2749
2750 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2751 return -EINVAL;
2752
2753
2754
2755
2756
2757 if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
2758 return -ERANGE;
2759
2760 drm_modeset_lock_all(dev);
2761 crtc = drm_crtc_find(dev, crtc_req->crtc_id);
2762 if (!crtc) {
2763 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
2764 ret = -ENOENT;
2765 goto out;
2766 }
2767 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
2768
2769 if (crtc_req->mode_valid) {
2770
2771
2772 if (crtc_req->fb_id == -1) {
2773 if (!crtc->primary->fb) {
2774 DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
2775 ret = -EINVAL;
2776 goto out;
2777 }
2778 fb = crtc->primary->fb;
2779
2780 drm_framebuffer_reference(fb);
2781 } else {
2782 fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
2783 if (!fb) {
2784 DRM_DEBUG_KMS("Unknown FB ID%d\n",
2785 crtc_req->fb_id);
2786 ret = -ENOENT;
2787 goto out;
2788 }
2789 }
2790
2791 mode = drm_mode_create(dev);
2792 if (!mode) {
2793 ret = -ENOMEM;
2794 goto out;
2795 }
2796
2797 ret = drm_mode_convert_umode(mode, &crtc_req->mode);
2798 if (ret) {
2799 DRM_DEBUG_KMS("Invalid mode\n");
2800 goto out;
2801 }
2802
2803 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
2804
2805
2806
2807
2808
2809
2810
2811
2812 if (!crtc->primary->format_default) {
2813 ret = drm_plane_check_pixel_format(crtc->primary,
2814 fb->pixel_format);
2815 if (ret) {
2816 DRM_DEBUG_KMS("Invalid pixel format %s\n",
2817 drm_get_format_name(fb->pixel_format));
2818 goto out;
2819 }
2820 }
2821
2822 ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
2823 mode, fb);
2824 if (ret)
2825 goto out;
2826
2827 }
2828
2829 if (crtc_req->count_connectors == 0 && mode) {
2830 DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
2831 ret = -EINVAL;
2832 goto out;
2833 }
2834
2835 if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
2836 DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
2837 crtc_req->count_connectors);
2838 ret = -EINVAL;
2839 goto out;
2840 }
2841
2842 if (crtc_req->count_connectors > 0) {
2843 u32 out_id;
2844
2845
2846 if (crtc_req->count_connectors > config->num_connector) {
2847 ret = -EINVAL;
2848 goto out;
2849 }
2850
2851 connector_set = kmalloc_array(crtc_req->count_connectors,
2852 sizeof(struct drm_connector *),
2853 GFP_KERNEL);
2854 if (!connector_set) {
2855 ret = -ENOMEM;
2856 goto out;
2857 }
2858
2859 for (i = 0; i < crtc_req->count_connectors; i++) {
2860 set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
2861 if (get_user(out_id, &set_connectors_ptr[i])) {
2862 ret = -EFAULT;
2863 goto out;
2864 }
2865
2866 connector = drm_connector_find(dev, out_id);
2867 if (!connector) {
2868 DRM_DEBUG_KMS("Connector id %d unknown\n",
2869 out_id);
2870 ret = -ENOENT;
2871 goto out;
2872 }
2873 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
2874 connector->base.id,
2875 connector->name);
2876
2877 connector_set[i] = connector;
2878 }
2879 }
2880
2881 set.crtc = crtc;
2882 set.x = crtc_req->x;
2883 set.y = crtc_req->y;
2884 set.mode = mode;
2885 set.connectors = connector_set;
2886 set.num_connectors = crtc_req->count_connectors;
2887 set.fb = fb;
2888 ret = drm_mode_set_config_internal(&set);
2889
2890out:
2891 if (fb)
2892 drm_framebuffer_unreference(fb);
2893
2894 kfree(connector_set);
2895 drm_mode_destroy(dev, mode);
2896 drm_modeset_unlock_all(dev);
2897 return ret;
2898}
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919static int drm_mode_cursor_universal(struct drm_crtc *crtc,
2920 struct drm_mode_cursor2 *req,
2921 struct drm_file *file_priv)
2922{
2923 struct drm_device *dev = crtc->dev;
2924 struct drm_framebuffer *fb = NULL;
2925 struct drm_mode_fb_cmd2 fbreq = {
2926 .width = req->width,
2927 .height = req->height,
2928 .pixel_format = DRM_FORMAT_ARGB8888,
2929 .pitches = { req->width * 4 },
2930 .handles = { req->handle },
2931 };
2932 int32_t crtc_x, crtc_y;
2933 uint32_t crtc_w = 0, crtc_h = 0;
2934 uint32_t src_w = 0, src_h = 0;
2935 int ret = 0;
2936
2937 BUG_ON(!crtc->cursor);
2938 WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL);
2939
2940
2941
2942
2943
2944
2945 if (req->flags & DRM_MODE_CURSOR_BO) {
2946 if (req->handle) {
2947 fb = internal_framebuffer_create(dev, &fbreq, file_priv);
2948 if (IS_ERR(fb)) {
2949 DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
2950 return PTR_ERR(fb);
2951 }
2952 } else {
2953 fb = NULL;
2954 }
2955 } else {
2956 fb = crtc->cursor->fb;
2957 if (fb)
2958 drm_framebuffer_reference(fb);
2959 }
2960
2961 if (req->flags & DRM_MODE_CURSOR_MOVE) {
2962 crtc_x = req->x;
2963 crtc_y = req->y;
2964 } else {
2965 crtc_x = crtc->cursor_x;
2966 crtc_y = crtc->cursor_y;
2967 }
2968
2969 if (fb) {
2970 crtc_w = fb->width;
2971 crtc_h = fb->height;
2972 src_w = fb->width << 16;
2973 src_h = fb->height << 16;
2974 }
2975
2976
2977
2978
2979
2980 ret = __setplane_internal(crtc->cursor, crtc, fb,
2981 crtc_x, crtc_y, crtc_w, crtc_h,
2982 0, 0, src_w, src_h);
2983
2984
2985 if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
2986 crtc->cursor_x = req->x;
2987 crtc->cursor_y = req->y;
2988 }
2989
2990 return ret;
2991}
2992
2993static int drm_mode_cursor_common(struct drm_device *dev,
2994 struct drm_mode_cursor2 *req,
2995 struct drm_file *file_priv)
2996{
2997 struct drm_crtc *crtc;
2998 int ret = 0;
2999
3000 if (!drm_core_check_feature(dev, DRIVER_MODESET))
3001 return -EINVAL;
3002
3003 if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
3004 return -EINVAL;
3005
3006 crtc = drm_crtc_find(dev, req->crtc_id);
3007 if (!crtc) {
3008 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
3009 return -ENOENT;
3010 }
3011
3012
3013
3014
3015
3016 drm_modeset_lock_crtc(crtc, crtc->cursor);
3017 if (crtc->cursor) {
3018 ret = drm_mode_cursor_universal(crtc, req, file_priv);
3019 goto out;
3020 }
3021
3022 if (req->flags & DRM_MODE_CURSOR_BO) {
3023 if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
3024 ret = -ENXIO;
3025 goto out;
3026 }
3027
3028 if (crtc->funcs->cursor_set2)
3029 ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle,
3030 req->width, req->height, req->hot_x, req->hot_y);
3031 else
3032 ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
3033 req->width, req->height);
3034 }
3035
3036 if (req->flags & DRM_MODE_CURSOR_MOVE) {
3037 if (crtc->funcs->cursor_move) {
3038 ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
3039 } else {
3040 ret = -EFAULT;
3041 goto out;
3042 }
3043 }
3044out:
3045 drm_modeset_unlock_crtc(crtc);
3046
3047 return ret;
3048
3049}
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065int drm_mode_cursor_ioctl(struct drm_device *dev,
3066 void *data, struct drm_file *file_priv)
3067{
3068 struct drm_mode_cursor *req = data;
3069 struct drm_mode_cursor2 new_req;
3070
3071 memcpy(&new_req, req, sizeof(struct drm_mode_cursor));
3072 new_req.hot_x = new_req.hot_y = 0;
3073
3074 return drm_mode_cursor_common(dev, &new_req, file_priv);
3075}
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092int drm_mode_cursor2_ioctl(struct drm_device *dev,
3093 void *data, struct drm_file *file_priv)
3094{
3095 struct drm_mode_cursor2 *req = data;
3096
3097 return drm_mode_cursor_common(dev, req, file_priv);
3098}
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
3109{
3110 uint32_t fmt;
3111
3112 switch (bpp) {
3113 case 8:
3114 fmt = DRM_FORMAT_C8;
3115 break;
3116 case 16:
3117 if (depth == 15)
3118 fmt = DRM_FORMAT_XRGB1555;
3119 else
3120 fmt = DRM_FORMAT_RGB565;
3121 break;
3122 case 24:
3123 fmt = DRM_FORMAT_RGB888;
3124 break;
3125 case 32:
3126 if (depth == 24)
3127 fmt = DRM_FORMAT_XRGB8888;
3128 else if (depth == 30)
3129 fmt = DRM_FORMAT_XRGB2101010;
3130 else
3131 fmt = DRM_FORMAT_ARGB8888;
3132 break;
3133 default:
3134 DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n");
3135 fmt = DRM_FORMAT_XRGB8888;
3136 break;
3137 }
3138
3139 return fmt;
3140}
3141EXPORT_SYMBOL(drm_mode_legacy_fb_format);
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157int drm_mode_addfb(struct drm_device *dev,
3158 void *data, struct drm_file *file_priv)
3159{
3160 struct drm_mode_fb_cmd *or = data;
3161 struct drm_mode_fb_cmd2 r = {};
3162 int ret;
3163
3164
3165 r.fb_id = or->fb_id;
3166 r.width = or->width;
3167 r.height = or->height;
3168 r.pitches[0] = or->pitch;
3169 r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
3170 r.handles[0] = or->handle;
3171
3172 ret = drm_mode_addfb2(dev, &r, file_priv);
3173 if (ret)
3174 return ret;
3175
3176 or->fb_id = r.fb_id;
3177
3178 return 0;
3179}
3180
3181static int format_check(const struct drm_mode_fb_cmd2 *r)
3182{
3183 uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
3184
3185 switch (format) {
3186 case DRM_FORMAT_C8:
3187 case DRM_FORMAT_RGB332:
3188 case DRM_FORMAT_BGR233:
3189 case DRM_FORMAT_XRGB4444:
3190 case DRM_FORMAT_XBGR4444:
3191 case DRM_FORMAT_RGBX4444:
3192 case DRM_FORMAT_BGRX4444:
3193 case DRM_FORMAT_ARGB4444:
3194 case DRM_FORMAT_ABGR4444:
3195 case DRM_FORMAT_RGBA4444:
3196 case DRM_FORMAT_BGRA4444:
3197 case DRM_FORMAT_XRGB1555:
3198 case DRM_FORMAT_XBGR1555:
3199 case DRM_FORMAT_RGBX5551:
3200 case DRM_FORMAT_BGRX5551:
3201 case DRM_FORMAT_ARGB1555:
3202 case DRM_FORMAT_ABGR1555:
3203 case DRM_FORMAT_RGBA5551:
3204 case DRM_FORMAT_BGRA5551:
3205 case DRM_FORMAT_RGB565:
3206 case DRM_FORMAT_BGR565:
3207 case DRM_FORMAT_RGB888:
3208 case DRM_FORMAT_BGR888:
3209 case DRM_FORMAT_XRGB8888:
3210 case DRM_FORMAT_XBGR8888:
3211 case DRM_FORMAT_RGBX8888:
3212 case DRM_FORMAT_BGRX8888:
3213 case DRM_FORMAT_ARGB8888:
3214 case DRM_FORMAT_ABGR8888:
3215 case DRM_FORMAT_RGBA8888:
3216 case DRM_FORMAT_BGRA8888:
3217 case DRM_FORMAT_XRGB2101010:
3218 case DRM_FORMAT_XBGR2101010:
3219 case DRM_FORMAT_RGBX1010102:
3220 case DRM_FORMAT_BGRX1010102:
3221 case DRM_FORMAT_ARGB2101010:
3222 case DRM_FORMAT_ABGR2101010:
3223 case DRM_FORMAT_RGBA1010102:
3224 case DRM_FORMAT_BGRA1010102:
3225 case DRM_FORMAT_YUYV:
3226 case DRM_FORMAT_YVYU:
3227 case DRM_FORMAT_UYVY:
3228 case DRM_FORMAT_VYUY:
3229 case DRM_FORMAT_AYUV:
3230 case DRM_FORMAT_NV12:
3231 case DRM_FORMAT_NV21:
3232 case DRM_FORMAT_NV16:
3233 case DRM_FORMAT_NV61:
3234 case DRM_FORMAT_NV24:
3235 case DRM_FORMAT_NV42:
3236 case DRM_FORMAT_YUV410:
3237 case DRM_FORMAT_YVU410:
3238 case DRM_FORMAT_YUV411:
3239 case DRM_FORMAT_YVU411:
3240 case DRM_FORMAT_YUV420:
3241 case DRM_FORMAT_YVU420:
3242 case DRM_FORMAT_YUV422:
3243 case DRM_FORMAT_YVU422:
3244 case DRM_FORMAT_YUV444:
3245 case DRM_FORMAT_YVU444:
3246 return 0;
3247 default:
3248 DRM_DEBUG_KMS("invalid pixel format %s\n",
3249 drm_get_format_name(r->pixel_format));
3250 return -EINVAL;
3251 }
3252}
3253
3254static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
3255{
3256 int ret, hsub, vsub, num_planes, i;
3257
3258 ret = format_check(r);
3259 if (ret) {
3260 DRM_DEBUG_KMS("bad framebuffer format %s\n",
3261 drm_get_format_name(r->pixel_format));
3262 return ret;
3263 }
3264
3265 hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
3266 vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
3267 num_planes = drm_format_num_planes(r->pixel_format);
3268
3269 if (r->width == 0 || r->width % hsub) {
3270 DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
3271 return -EINVAL;
3272 }
3273
3274 if (r->height == 0 || r->height % vsub) {
3275 DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
3276 return -EINVAL;
3277 }
3278
3279 for (i = 0; i < num_planes; i++) {
3280 unsigned int width = r->width / (i != 0 ? hsub : 1);
3281 unsigned int height = r->height / (i != 0 ? vsub : 1);
3282 unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
3283
3284 if (!r->handles[i]) {
3285 DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
3286 return -EINVAL;
3287 }
3288
3289 if ((uint64_t) width * cpp > UINT_MAX)
3290 return -ERANGE;
3291
3292 if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)
3293 return -ERANGE;
3294
3295 if (r->pitches[i] < width * cpp) {
3296 DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
3297 return -EINVAL;
3298 }
3299
3300 if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) {
3301 DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
3302 r->modifier[i], i);
3303 return -EINVAL;
3304 }
3305
3306
3307 switch (r->modifier[i]) {
3308 case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
3309
3310
3311
3312 if (r->pixel_format != DRM_FORMAT_NV12 ||
3313 width % 128 || height % 32 ||
3314 r->pitches[i] % 128) {
3315 DRM_DEBUG_KMS("bad modifier data for plane %d\n", i);
3316 return -EINVAL;
3317 }
3318 break;
3319
3320 default:
3321 break;
3322 }
3323 }
3324
3325 for (i = num_planes; i < 4; i++) {
3326 if (r->modifier[i]) {
3327 DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i);
3328 return -EINVAL;
3329 }
3330
3331
3332 if (!(r->flags & DRM_MODE_FB_MODIFIERS))
3333 continue;
3334
3335 if (r->handles[i]) {
3336 DRM_DEBUG_KMS("buffer object handle for unused plane %d\n", i);
3337 return -EINVAL;
3338 }
3339
3340 if (r->pitches[i]) {
3341 DRM_DEBUG_KMS("non-zero pitch for unused plane %d\n", i);
3342 return -EINVAL;
3343 }
3344
3345 if (r->offsets[i]) {
3346 DRM_DEBUG_KMS("non-zero offset for unused plane %d\n", i);
3347 return -EINVAL;
3348 }
3349 }
3350
3351 return 0;
3352}
3353
3354static struct drm_framebuffer *
3355internal_framebuffer_create(struct drm_device *dev,
3356 const struct drm_mode_fb_cmd2 *r,
3357 struct drm_file *file_priv)
3358{
3359 struct drm_mode_config *config = &dev->mode_config;
3360 struct drm_framebuffer *fb;
3361 int ret;
3362
3363 if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) {
3364 DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
3365 return ERR_PTR(-EINVAL);
3366 }
3367
3368 if ((config->min_width > r->width) || (r->width > config->max_width)) {
3369 DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
3370 r->width, config->min_width, config->max_width);
3371 return ERR_PTR(-EINVAL);
3372 }
3373 if ((config->min_height > r->height) || (r->height > config->max_height)) {
3374 DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
3375 r->height, config->min_height, config->max_height);
3376 return ERR_PTR(-EINVAL);
3377 }
3378
3379 if (r->flags & DRM_MODE_FB_MODIFIERS &&
3380 !dev->mode_config.allow_fb_modifiers) {
3381 DRM_DEBUG_KMS("driver does not support fb modifiers\n");
3382 return ERR_PTR(-EINVAL);
3383 }
3384
3385 ret = framebuffer_check(r);
3386 if (ret)
3387 return ERR_PTR(ret);
3388
3389 fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
3390 if (IS_ERR(fb)) {
3391 DRM_DEBUG_KMS("could not create framebuffer\n");
3392 return fb;
3393 }
3394
3395 return fb;
3396}
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413int drm_mode_addfb2(struct drm_device *dev,
3414 void *data, struct drm_file *file_priv)
3415{
3416 struct drm_mode_fb_cmd2 *r = data;
3417 struct drm_framebuffer *fb;
3418
3419 if (!drm_core_check_feature(dev, DRIVER_MODESET))
3420 return -EINVAL;
3421
3422 fb = internal_framebuffer_create(dev, r, file_priv);
3423 if (IS_ERR(fb))
3424 return PTR_ERR(fb);
3425
3426
3427
3428 DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
3429 mutex_lock(&file_priv->fbs_lock);
3430 r->fb_id = fb->base.id;
3431 list_add(&fb->filp_head, &file_priv->fbs);
3432 mutex_unlock(&file_priv->fbs_lock);
3433
3434 return 0;
3435}
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450int drm_mode_rmfb(struct drm_device *dev,
3451 void *data, struct drm_file *file_priv)
3452{
3453 struct drm_framebuffer *fb = NULL;
3454 struct drm_framebuffer *fbl = NULL;
3455 uint32_t *id = data;
3456 int found = 0;
3457
3458 if (!drm_core_check_feature(dev, DRIVER_MODESET))
3459 return -EINVAL;
3460
3461 mutex_lock(&file_priv->fbs_lock);
3462 mutex_lock(&dev->mode_config.fb_lock);
3463 fb = __drm_framebuffer_lookup(dev, *id);
3464 if (!fb)
3465 goto fail_lookup;
3466
3467 list_for_each_entry(fbl, &file_priv->fbs, filp_head)
3468 if (fb == fbl)
3469 found = 1;
3470 if (!found)
3471 goto fail_lookup;
3472
3473 list_del_init(&fb->filp_head);
3474 mutex_unlock(&dev->mode_config.fb_lock);
3475 mutex_unlock(&file_priv->fbs_lock);
3476
3477 drm_framebuffer_unreference(fb);
3478
3479 return 0;
3480
3481fail_lookup:
3482 mutex_unlock(&dev->mode_config.fb_lock);
3483 mutex_unlock(&file_priv->fbs_lock);
3484
3485 return -ENOENT;
3486}
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501int drm_mode_getfb(struct drm_device *dev,
3502 void *data, struct drm_file *file_priv)
3503{
3504 struct drm_mode_fb_cmd *r = data;
3505 struct drm_framebuffer *fb;
3506 int ret;
3507
3508 if (!drm_core_check_feature(dev, DRIVER_MODESET))
3509 return -EINVAL;
3510
3511 fb = drm_framebuffer_lookup(dev, r->fb_id);
3512 if (!fb)
3513 return -ENOENT;
3514
3515 r->height = fb->height;
3516 r->width = fb->width;
3517 r->depth = fb->depth;
3518 r->bpp = fb->bits_per_pixel;
3519 r->pitch = fb->pitches[0];
3520 if (fb->funcs->create_handle) {
3521 if (file_priv->is_master || capable(CAP_SYS_ADMIN) ||
3522 drm_is_control_client(file_priv)) {
3523 ret = fb->funcs->create_handle(fb, file_priv,
3524 &r->handle);
3525 } else {
3526
3527
3528
3529
3530
3531 r->handle = 0;
3532 ret = 0;
3533 }
3534 } else {
3535 ret = -ENODEV;
3536 }
3537
3538 drm_framebuffer_unreference(fb);
3539
3540 return ret;
3541}
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
3563 void *data, struct drm_file *file_priv)
3564{
3565 struct drm_clip_rect __user *clips_ptr;
3566 struct drm_clip_rect *clips = NULL;
3567 struct drm_mode_fb_dirty_cmd *r = data;
3568 struct drm_framebuffer *fb;
3569 unsigned flags;
3570 int num_clips;
3571 int ret;
3572
3573 if (!drm_core_check_feature(dev, DRIVER_MODESET))
3574 return -EINVAL;
3575
3576 fb = drm_framebuffer_lookup(dev, r->fb_id);
3577 if (!fb)
3578 return -ENOENT;
3579
3580 num_clips = r->num_clips;
3581 clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
3582
3583 if (!num_clips != !clips_ptr) {
3584 ret = -EINVAL;
3585 goto out_err1;
3586 }
3587
3588 flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
3589
3590
3591 if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
3592 ret = -EINVAL;
3593 goto out_err1;
3594 }
3595
3596 if (num_clips && clips_ptr) {
3597 if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
3598 ret = -EINVAL;
3599 goto out_err1;
3600 }
3601 clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
3602 if (!clips) {
3603 ret = -ENOMEM;
3604 goto out_err1;
3605 }
3606
3607 ret = copy_from_user(clips, clips_ptr,
3608 num_clips * sizeof(*clips));
3609 if (ret) {
3610 ret = -EFAULT;
3611 goto out_err2;
3612 }
3613 }
3614
3615 if (fb->funcs->dirty) {
3616 ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
3617 clips, num_clips);
3618 } else {
3619 ret = -ENOSYS;
3620 }
3621
3622out_err2:
3623 kfree(clips);
3624out_err1:
3625 drm_framebuffer_unreference(fb);
3626
3627 return ret;
3628}
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642void drm_fb_release(struct drm_file *priv)
3643{
3644 struct drm_framebuffer *fb, *tfb;
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
3657 list_del_init(&fb->filp_head);
3658
3659
3660 drm_framebuffer_unreference(fb);
3661 }
3662}
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682struct drm_property *drm_property_create(struct drm_device *dev, int flags,
3683 const char *name, int num_values)
3684{
3685 struct drm_property *property = NULL;
3686 int ret;
3687
3688 property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
3689 if (!property)
3690 return NULL;
3691
3692 property->dev = dev;
3693
3694 if (num_values) {
3695 property->values = kcalloc(num_values, sizeof(uint64_t),
3696 GFP_KERNEL);
3697 if (!property->values)
3698 goto fail;
3699 }
3700
3701 ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
3702 if (ret)
3703 goto fail;
3704
3705 property->flags = flags;
3706 property->num_values = num_values;
3707 INIT_LIST_HEAD(&property->enum_list);
3708
3709 if (name) {
3710 strncpy(property->name, name, DRM_PROP_NAME_LEN);
3711 property->name[DRM_PROP_NAME_LEN-1] = '\0';
3712 }
3713
3714 list_add_tail(&property->head, &dev->mode_config.property_list);
3715
3716 WARN_ON(!drm_property_type_valid(property));
3717
3718 return property;
3719fail:
3720 kfree(property->values);
3721 kfree(property);
3722 return NULL;
3723}
3724EXPORT_SYMBOL(drm_property_create);
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
3745 const char *name,
3746 const struct drm_prop_enum_list *props,
3747 int num_values)
3748{
3749 struct drm_property *property;
3750 int i, ret;
3751
3752 flags |= DRM_MODE_PROP_ENUM;
3753
3754 property = drm_property_create(dev, flags, name, num_values);
3755 if (!property)
3756 return NULL;
3757
3758 for (i = 0; i < num_values; i++) {
3759 ret = drm_property_add_enum(property, i,
3760 props[i].type,
3761 props[i].name);
3762 if (ret) {
3763 drm_property_destroy(dev, property);
3764 return NULL;
3765 }
3766 }
3767
3768 return property;
3769}
3770EXPORT_SYMBOL(drm_property_create_enum);
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
3792 int flags, const char *name,
3793 const struct drm_prop_enum_list *props,
3794 int num_props,
3795 uint64_t supported_bits)
3796{
3797 struct drm_property *property;
3798 int i, ret, index = 0;
3799 int num_values = hweight64(supported_bits);
3800
3801 flags |= DRM_MODE_PROP_BITMASK;
3802
3803 property = drm_property_create(dev, flags, name, num_values);
3804 if (!property)
3805 return NULL;
3806 for (i = 0; i < num_props; i++) {
3807 if (!(supported_bits & (1ULL << props[i].type)))
3808 continue;
3809
3810 if (WARN_ON(index >= num_values)) {
3811 drm_property_destroy(dev, property);
3812 return NULL;
3813 }
3814
3815 ret = drm_property_add_enum(property, index++,
3816 props[i].type,
3817 props[i].name);
3818 if (ret) {
3819 drm_property_destroy(dev, property);
3820 return NULL;
3821 }
3822 }
3823
3824 return property;
3825}
3826EXPORT_SYMBOL(drm_property_create_bitmask);
3827
3828static struct drm_property *property_create_range(struct drm_device *dev,
3829 int flags, const char *name,
3830 uint64_t min, uint64_t max)
3831{
3832 struct drm_property *property;
3833
3834 property = drm_property_create(dev, flags, name, 2);
3835 if (!property)
3836 return NULL;
3837
3838 property->values[0] = min;
3839 property->values[1] = max;
3840
3841 return property;
3842}
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
3863 const char *name,
3864 uint64_t min, uint64_t max)
3865{
3866 return property_create_range(dev, DRM_MODE_PROP_RANGE | flags,
3867 name, min, max);
3868}
3869EXPORT_SYMBOL(drm_property_create_range);
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
3890 int flags, const char *name,
3891 int64_t min, int64_t max)
3892{
3893 return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags,
3894 name, I642U64(min), I642U64(max));
3895}
3896EXPORT_SYMBOL(drm_property_create_signed_range);
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915struct drm_property *drm_property_create_object(struct drm_device *dev,
3916 int flags, const char *name, uint32_t type)
3917{
3918 struct drm_property *property;
3919
3920 flags |= DRM_MODE_PROP_OBJECT;
3921
3922 if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
3923 return NULL;
3924
3925 property = drm_property_create(dev, flags, name, 1);
3926 if (!property)
3927 return NULL;
3928
3929 property->values[0] = type;
3930
3931 return property;
3932}
3933EXPORT_SYMBOL(drm_property_create_object);
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
3951 const char *name)
3952{
3953 return drm_property_create_range(dev, flags, name, 0, 1);
3954}
3955EXPORT_SYMBOL(drm_property_create_bool);
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972int drm_property_add_enum(struct drm_property *property, int index,
3973 uint64_t value, const char *name)
3974{
3975 struct drm_property_enum *prop_enum;
3976
3977 if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
3978 drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
3979 return -EINVAL;
3980
3981
3982
3983
3984
3985 if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
3986 (value > 63))
3987 return -EINVAL;
3988
3989 if (!list_empty(&property->enum_list)) {
3990 list_for_each_entry(prop_enum, &property->enum_list, head) {
3991 if (prop_enum->value == value) {
3992 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
3993 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
3994 return 0;
3995 }
3996 }
3997 }
3998
3999 prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
4000 if (!prop_enum)
4001 return -ENOMEM;
4002
4003 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
4004 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
4005 prop_enum->value = value;
4006
4007 property->values[index] = value;
4008 list_add_tail(&prop_enum->head, &property->enum_list);
4009 return 0;
4010}
4011EXPORT_SYMBOL(drm_property_add_enum);
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
4022{
4023 struct drm_property_enum *prop_enum, *pt;
4024
4025 list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
4026 list_del(&prop_enum->head);
4027 kfree(prop_enum);
4028 }
4029
4030 if (property->num_values)
4031 kfree(property->values);
4032 drm_mode_object_put(dev, &property->base);
4033 list_del(&property->head);
4034 kfree(property);
4035}
4036EXPORT_SYMBOL(drm_property_destroy);
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048void drm_object_attach_property(struct drm_mode_object *obj,
4049 struct drm_property *property,
4050 uint64_t init_val)
4051{
4052 int count = obj->properties->count;
4053
4054 if (count == DRM_OBJECT_MAX_PROPERTY) {
4055 WARN(1, "Failed to attach object property (type: 0x%x). Please "
4056 "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
4057 "you see this message on the same object type.\n",
4058 obj->type);
4059 return;
4060 }
4061
4062 obj->properties->properties[count] = property;
4063 obj->properties->values[count] = init_val;
4064 obj->properties->count++;
4065 if (property->flags & DRM_MODE_PROP_ATOMIC)
4066 obj->properties->atomic_count++;
4067}
4068EXPORT_SYMBOL(drm_object_attach_property);
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083int drm_object_property_set_value(struct drm_mode_object *obj,
4084 struct drm_property *property, uint64_t val)
4085{
4086 int i;
4087
4088 for (i = 0; i < obj->properties->count; i++) {
4089 if (obj->properties->properties[i] == property) {
4090 obj->properties->values[i] = val;
4091 return 0;
4092 }
4093 }
4094
4095 return -EINVAL;
4096}
4097EXPORT_SYMBOL(drm_object_property_set_value);
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113int drm_object_property_get_value(struct drm_mode_object *obj,
4114 struct drm_property *property, uint64_t *val)
4115{
4116 int i;
4117
4118
4119
4120
4121
4122 if (drm_core_check_feature(property->dev, DRIVER_ATOMIC) &&
4123 !(property->flags & DRM_MODE_PROP_IMMUTABLE))
4124 return drm_atomic_get_property(obj, property, val);
4125
4126 for (i = 0; i < obj->properties->count; i++) {
4127 if (obj->properties->properties[i] == property) {
4128 *val = obj->properties->values[i];
4129 return 0;
4130 }
4131 }
4132
4133 return -EINVAL;
4134}
4135EXPORT_SYMBOL(drm_object_property_get_value);
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153int drm_mode_getproperty_ioctl(struct drm_device *dev,
4154 void *data, struct drm_file *file_priv)
4155{
4156 struct drm_mode_get_property *out_resp = data;
4157 struct drm_property *property;
4158 int enum_count = 0;
4159 int value_count = 0;
4160 int ret = 0, i;
4161 int copied;
4162 struct drm_property_enum *prop_enum;
4163 struct drm_mode_property_enum __user *enum_ptr;
4164 uint64_t __user *values_ptr;
4165
4166 if (!drm_core_check_feature(dev, DRIVER_MODESET))
4167 return -EINVAL;
4168
4169 drm_modeset_lock_all(dev);
4170 property = drm_property_find(dev, out_resp->prop_id);
4171 if (!property) {
4172 ret = -ENOENT;
4173 goto done;
4174 }
4175
4176 if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
4177 drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
4178 list_for_each_entry(prop_enum, &property->enum_list, head)
4179 enum_count++;
4180 }
4181
4182 value_count = property->num_values;
4183
4184 strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
4185 out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
4186 out_resp->flags = property->flags;
4187
4188 if ((out_resp->count_values >= value_count) && value_count) {
4189 values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
4190 for (i = 0; i < value_count; i++) {
4191 if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
4192 ret = -EFAULT;
4193 goto done;
4194 }
4195 }
4196 }
4197 out_resp->count_values = value_count;
4198
4199 if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
4200 drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
4201 if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
4202 copied = 0;
4203 enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
4204 list_for_each_entry(prop_enum, &property->enum_list, head) {
4205
4206 if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
4207 ret = -EFAULT;
4208 goto done;
4209 }
4210
4211 if (copy_to_user(&enum_ptr[copied].name,
4212 &prop_enum->name, DRM_PROP_NAME_LEN)) {
4213 ret = -EFAULT;
4214 goto done;
4215 }
4216 copied++;
4217 }
4218 }
4219 out_resp->count_enum_blobs = enum_count;
4220 }
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230 if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
4231 out_resp->count_enum_blobs = 0;
4232done:
4233 drm_modeset_unlock_all(dev);
4234 return ret;
4235}
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251struct drm_property_blob *
4252drm_property_create_blob(struct drm_device *dev, size_t length,
4253 const void *data)
4254{
4255 struct drm_property_blob *blob;
4256 int ret;
4257
4258 if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob))
4259 return ERR_PTR(-EINVAL);
4260
4261 blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
4262 if (!blob)
4263 return ERR_PTR(-ENOMEM);
4264
4265
4266
4267 INIT_LIST_HEAD(&blob->head_file);
4268 blob->length = length;
4269 blob->dev = dev;
4270
4271 if (data)
4272 memcpy(blob->data, data, length);
4273
4274 mutex_lock(&dev->mode_config.blob_lock);
4275
4276 ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB);
4277 if (ret) {
4278 kfree(blob);
4279 mutex_unlock(&dev->mode_config.blob_lock);
4280 return ERR_PTR(-EINVAL);
4281 }
4282
4283 kref_init(&blob->refcount);
4284
4285 list_add_tail(&blob->head_global,
4286 &dev->mode_config.property_blob_list);
4287
4288 mutex_unlock(&dev->mode_config.blob_lock);
4289
4290 return blob;
4291}
4292EXPORT_SYMBOL(drm_property_create_blob);
4293
4294
4295
4296
4297
4298
4299
4300
4301static void drm_property_free_blob(struct kref *kref)
4302{
4303 struct drm_property_blob *blob =
4304 container_of(kref, struct drm_property_blob, refcount);
4305
4306 WARN_ON(!mutex_is_locked(&blob->dev->mode_config.blob_lock));
4307
4308 list_del(&blob->head_global);
4309 list_del(&blob->head_file);
4310 drm_mode_object_put(blob->dev, &blob->base);
4311
4312 kfree(blob);
4313}
4314
4315
4316
4317
4318
4319
4320
4321
4322void drm_property_unreference_blob(struct drm_property_blob *blob)
4323{
4324 struct drm_device *dev;
4325
4326 if (!blob)
4327 return;
4328
4329 dev = blob->dev;
4330
4331 DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, atomic_read(&blob->refcount.refcount));
4332
4333 if (kref_put_mutex(&blob->refcount, drm_property_free_blob,
4334 &dev->mode_config.blob_lock))
4335 mutex_unlock(&dev->mode_config.blob_lock);
4336 else
4337 might_lock(&dev->mode_config.blob_lock);
4338}
4339EXPORT_SYMBOL(drm_property_unreference_blob);
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349static void drm_property_unreference_blob_locked(struct drm_property_blob *blob)
4350{
4351 if (!blob)
4352 return;
4353
4354 DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, atomic_read(&blob->refcount.refcount));
4355
4356 kref_put(&blob->refcount, drm_property_free_blob);
4357}
4358
4359
4360
4361
4362
4363
4364void drm_property_destroy_user_blobs(struct drm_device *dev,
4365 struct drm_file *file_priv)
4366{
4367 struct drm_property_blob *blob, *bt;
4368
4369 mutex_lock(&dev->mode_config.blob_lock);
4370
4371 list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
4372 list_del_init(&blob->head_file);
4373 drm_property_unreference_blob_locked(blob);
4374 }
4375
4376 mutex_unlock(&dev->mode_config.blob_lock);
4377}
4378
4379
4380
4381
4382
4383
4384
4385
4386struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob)
4387{
4388 DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, atomic_read(&blob->refcount.refcount));
4389 kref_get(&blob->refcount);
4390 return blob;
4391}
4392EXPORT_SYMBOL(drm_property_reference_blob);
4393
4394
4395
4396
4397
4398static struct drm_property_blob *__drm_property_lookup_blob(struct drm_device *dev,
4399 uint32_t id)
4400{
4401 struct drm_mode_object *obj = NULL;
4402 struct drm_property_blob *blob;
4403
4404 WARN_ON(!mutex_is_locked(&dev->mode_config.blob_lock));
4405
4406 mutex_lock(&dev->mode_config.idr_mutex);
4407 obj = idr_find(&dev->mode_config.crtc_idr, id);
4408 if (!obj || (obj->type != DRM_MODE_OBJECT_BLOB) || (obj->id != id))
4409 blob = NULL;
4410 else
4411 blob = obj_to_blob(obj);
4412 mutex_unlock(&dev->mode_config.idr_mutex);
4413
4414 return blob;
4415}
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
4427 uint32_t id)
4428{
4429 struct drm_property_blob *blob;
4430
4431 mutex_lock(&dev->mode_config.blob_lock);
4432 blob = __drm_property_lookup_blob(dev, id);
4433 if (blob) {
4434 if (!kref_get_unless_zero(&blob->refcount))
4435 blob = NULL;
4436 }
4437 mutex_unlock(&dev->mode_config.blob_lock);
4438
4439 return blob;
4440}
4441EXPORT_SYMBOL(drm_property_lookup_blob);
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473static int drm_property_replace_global_blob(struct drm_device *dev,
4474 struct drm_property_blob **replace,
4475 size_t length,
4476 const void *data,
4477 struct drm_mode_object *obj_holds_id,
4478 struct drm_property *prop_holds_id)
4479{
4480 struct drm_property_blob *new_blob = NULL;
4481 struct drm_property_blob *old_blob = NULL;
4482 int ret;
4483
4484 WARN_ON(replace == NULL);
4485
4486 old_blob = *replace;
4487
4488 if (length && data) {
4489 new_blob = drm_property_create_blob(dev, length, data);
4490 if (IS_ERR(new_blob))
4491 return PTR_ERR(new_blob);
4492 }
4493
4494
4495
4496
4497
4498
4499 if (obj_holds_id) {
4500 ret = drm_object_property_set_value(obj_holds_id,
4501 prop_holds_id,
4502 new_blob ?
4503 new_blob->base.id : 0);
4504 if (ret != 0)
4505 goto err_created;
4506 }
4507
4508 drm_property_unreference_blob(old_blob);
4509 *replace = new_blob;
4510
4511 return 0;
4512
4513err_created:
4514 drm_property_unreference_blob(new_blob);
4515 return ret;
4516}
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532int drm_mode_getblob_ioctl(struct drm_device *dev,
4533 void *data, struct drm_file *file_priv)
4534{
4535 struct drm_mode_get_blob *out_resp = data;
4536 struct drm_property_blob *blob;
4537 int ret = 0;
4538 void __user *blob_ptr;
4539
4540 if (!drm_core_check_feature(dev, DRIVER_MODESET))
4541 return -EINVAL;
4542
4543 drm_modeset_lock_all(dev);
4544 mutex_lock(&dev->mode_config.blob_lock);
4545 blob = __drm_property_lookup_blob(dev, out_resp->blob_id);
4546 if (!blob) {
4547 ret = -ENOENT;
4548 goto done;
4549 }
4550
4551 if (out_resp->length == blob->length) {
4552 blob_ptr = (void __user *)(unsigned long)out_resp->data;
4553 if (copy_to_user(blob_ptr, blob->data, blob->length)) {
4554 ret = -EFAULT;
4555 goto done;
4556 }
4557 }
4558 out_resp->length = blob->length;
4559
4560done:
4561 mutex_unlock(&dev->mode_config.blob_lock);
4562 drm_modeset_unlock_all(dev);
4563 return ret;
4564}
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581int drm_mode_createblob_ioctl(struct drm_device *dev,
4582 void *data, struct drm_file *file_priv)
4583{
4584 struct drm_mode_create_blob *out_resp = data;
4585 struct drm_property_blob *blob;
4586 void __user *blob_ptr;
4587 int ret = 0;
4588
4589 if (!drm_core_check_feature(dev, DRIVER_MODESET))
4590 return -EINVAL;
4591
4592 blob = drm_property_create_blob(dev, out_resp->length, NULL);
4593 if (IS_ERR(blob))
4594 return PTR_ERR(blob);
4595
4596 blob_ptr = (void __user *)(unsigned long)out_resp->data;
4597 if (copy_from_user(blob->data, blob_ptr, out_resp->length)) {
4598 ret = -EFAULT;
4599 goto out_blob;
4600 }
4601
4602
4603
4604
4605 mutex_lock(&dev->mode_config.blob_lock);
4606 out_resp->blob_id = blob->base.id;
4607 list_add_tail(&blob->head_file, &file_priv->blobs);
4608 mutex_unlock(&dev->mode_config.blob_lock);
4609
4610 return 0;
4611
4612out_blob:
4613 drm_property_unreference_blob(blob);
4614 return ret;
4615}
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630int drm_mode_destroyblob_ioctl(struct drm_device *dev,
4631 void *data, struct drm_file *file_priv)
4632{
4633 struct drm_mode_destroy_blob *out_resp = data;
4634 struct drm_property_blob *blob = NULL, *bt;
4635 bool found = false;
4636 int ret = 0;
4637
4638 if (!drm_core_check_feature(dev, DRIVER_MODESET))
4639 return -EINVAL;
4640
4641 mutex_lock(&dev->mode_config.blob_lock);
4642 blob = __drm_property_lookup_blob(dev, out_resp->blob_id);
4643 if (!blob) {
4644 ret = -ENOENT;
4645 goto err;
4646 }
4647
4648
4649 list_for_each_entry(bt, &file_priv->blobs, head_file) {
4650 if (bt == blob) {
4651 found = true;
4652 break;
4653 }
4654 }
4655
4656 if (!found) {
4657 ret = -EPERM;
4658 goto err;
4659 }
4660
4661
4662
4663 list_del_init(&blob->head_file);
4664 drm_property_unreference_blob_locked(blob);
4665 mutex_unlock(&dev->mode_config.blob_lock);
4666
4667 return 0;
4668
4669err:
4670 mutex_unlock(&dev->mode_config.blob_lock);
4671 return ret;
4672}
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687int drm_mode_connector_set_path_property(struct drm_connector *connector,
4688 const char *path)
4689{
4690 struct drm_device *dev = connector->dev;
4691 int ret;
4692
4693 ret = drm_property_replace_global_blob(dev,
4694 &connector->path_blob_ptr,
4695 strlen(path) + 1,
4696 path,
4697 &connector->base,
4698 dev->mode_config.path_property);
4699 return ret;
4700}
4701EXPORT_SYMBOL(drm_mode_connector_set_path_property);
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714int drm_mode_connector_set_tile_property(struct drm_connector *connector)
4715{
4716 struct drm_device *dev = connector->dev;
4717 char tile[256];
4718 int ret;
4719
4720 if (!connector->has_tile) {
4721 ret = drm_property_replace_global_blob(dev,
4722 &connector->tile_blob_ptr,
4723 0,
4724 NULL,
4725 &connector->base,
4726 dev->mode_config.tile_property);
4727 return ret;
4728 }
4729
4730 snprintf(tile, 256, "%d:%d:%d:%d:%d:%d:%d:%d",
4731 connector->tile_group->id, connector->tile_is_single_monitor,
4732 connector->num_h_tile, connector->num_v_tile,
4733 connector->tile_h_loc, connector->tile_v_loc,
4734 connector->tile_h_size, connector->tile_v_size);
4735
4736 ret = drm_property_replace_global_blob(dev,
4737 &connector->tile_blob_ptr,
4738 strlen(tile) + 1,
4739 tile,
4740 &connector->base,
4741 dev->mode_config.tile_property);
4742 return ret;
4743}
4744EXPORT_SYMBOL(drm_mode_connector_set_tile_property);
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757int drm_mode_connector_update_edid_property(struct drm_connector *connector,
4758 const struct edid *edid)
4759{
4760 struct drm_device *dev = connector->dev;
4761 size_t size = 0;
4762 int ret;
4763
4764
4765 if (connector->override_edid)
4766 return 0;
4767
4768 if (edid)
4769 size = EDID_LENGTH * (1 + edid->extensions);
4770
4771 ret = drm_property_replace_global_blob(dev,
4772 &connector->edid_blob_ptr,
4773 size,
4774 edid,
4775 &connector->base,
4776 dev->mode_config.edid_property);
4777 return ret;
4778}
4779EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789bool drm_property_change_valid_get(struct drm_property *property,
4790 uint64_t value, struct drm_mode_object **ref)
4791{
4792 int i;
4793
4794 if (property->flags & DRM_MODE_PROP_IMMUTABLE)
4795 return false;
4796
4797 *ref = NULL;
4798
4799 if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
4800 if (value < property->values[0] || value > property->values[1])
4801 return false;
4802 return true;
4803 } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
4804 int64_t svalue = U642I64(value);
4805
4806 if (svalue < U642I64(property->values[0]) ||
4807 svalue > U642I64(property->values[1]))
4808 return false;
4809 return true;
4810 } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
4811 uint64_t valid_mask = 0;
4812
4813 for (i = 0; i < property->num_values; i++)
4814 valid_mask |= (1ULL << property->values[i]);
4815 return !(value & ~valid_mask);
4816 } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
4817 struct drm_property_blob *blob;
4818
4819 if (value == 0)
4820 return true;
4821
4822 blob = drm_property_lookup_blob(property->dev, value);
4823 if (blob) {
4824 *ref = &blob->base;
4825 return true;
4826 } else {
4827 return false;
4828 }
4829 } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
4830
4831 if (value == 0)
4832 return true;
4833
4834
4835 if (property->values[0] == DRM_MODE_OBJECT_FB) {
4836 struct drm_framebuffer *fb;
4837 fb = drm_framebuffer_lookup(property->dev, value);
4838 if (fb) {
4839 *ref = &fb->base;
4840 return true;
4841 } else {
4842 return false;
4843 }
4844 } else {
4845 return _object_find(property->dev, value, property->values[0]) != NULL;
4846 }
4847 }
4848
4849 for (i = 0; i < property->num_values; i++)
4850 if (property->values[i] == value)
4851 return true;
4852 return false;
4853}
4854
4855void drm_property_change_valid_put(struct drm_property *property,
4856 struct drm_mode_object *ref)
4857{
4858 if (!ref)
4859 return;
4860
4861 if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
4862 if (property->values[0] == DRM_MODE_OBJECT_FB)
4863 drm_framebuffer_unreference(obj_to_fb(ref));
4864 } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
4865 drm_property_unreference_blob(obj_to_blob(ref));
4866}
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
4883 void *data, struct drm_file *file_priv)
4884{
4885 struct drm_mode_connector_set_property *conn_set_prop = data;
4886 struct drm_mode_obj_set_property obj_set_prop = {
4887 .value = conn_set_prop->value,
4888 .prop_id = conn_set_prop->prop_id,
4889 .obj_id = conn_set_prop->connector_id,
4890 .obj_type = DRM_MODE_OBJECT_CONNECTOR
4891 };
4892
4893
4894 return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv);
4895}
4896
4897static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
4898 struct drm_property *property,
4899 uint64_t value)
4900{
4901 int ret = -EINVAL;
4902 struct drm_connector *connector = obj_to_connector(obj);
4903
4904
4905 if (property == connector->dev->mode_config.dpms_property) {
4906 ret = (*connector->funcs->dpms)(connector, (int)value);
4907 } else if (connector->funcs->set_property)
4908 ret = connector->funcs->set_property(connector, property, value);
4909
4910
4911 if (!ret)
4912 drm_object_property_set_value(&connector->base, property, value);
4913 return ret;
4914}
4915
4916static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
4917 struct drm_property *property,
4918 uint64_t value)
4919{
4920 int ret = -EINVAL;
4921 struct drm_crtc *crtc = obj_to_crtc(obj);
4922
4923 if (crtc->funcs->set_property)
4924 ret = crtc->funcs->set_property(crtc, property, value);
4925 if (!ret)
4926 drm_object_property_set_value(obj, property, value);
4927
4928 return ret;
4929}
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
4945 struct drm_property *property,
4946 uint64_t value)
4947{
4948 int ret = -EINVAL;
4949 struct drm_mode_object *obj = &plane->base;
4950
4951 if (plane->funcs->set_property)
4952 ret = plane->funcs->set_property(plane, property, value);
4953 if (!ret)
4954 drm_object_property_set_value(obj, property, value);
4955
4956 return ret;
4957}
4958EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
4976 struct drm_file *file_priv)
4977{
4978 struct drm_mode_obj_get_properties *arg = data;
4979 struct drm_mode_object *obj;
4980 int ret = 0;
4981
4982 if (!drm_core_check_feature(dev, DRIVER_MODESET))
4983 return -EINVAL;
4984
4985 drm_modeset_lock_all(dev);
4986
4987 obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
4988 if (!obj) {
4989 ret = -ENOENT;
4990 goto out;
4991 }
4992 if (!obj->properties) {
4993 ret = -EINVAL;
4994 goto out;
4995 }
4996
4997 ret = get_properties(obj, file_priv->atomic,
4998 (uint32_t __user *)(unsigned long)(arg->props_ptr),
4999 (uint64_t __user *)(unsigned long)(arg->prop_values_ptr),
5000 &arg->count_props);
5001
5002out:
5003 drm_modeset_unlock_all(dev);
5004 return ret;
5005}
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
5024 struct drm_file *file_priv)
5025{
5026 struct drm_mode_obj_set_property *arg = data;
5027 struct drm_mode_object *arg_obj;
5028 struct drm_mode_object *prop_obj;
5029 struct drm_property *property;
5030 int i, ret = -EINVAL;
5031 struct drm_mode_object *ref;
5032
5033 if (!drm_core_check_feature(dev, DRIVER_MODESET))
5034 return -EINVAL;
5035
5036 drm_modeset_lock_all(dev);
5037
5038 arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
5039 if (!arg_obj) {
5040 ret = -ENOENT;
5041 goto out;
5042 }
5043 if (!arg_obj->properties)
5044 goto out;
5045
5046 for (i = 0; i < arg_obj->properties->count; i++)
5047 if (arg_obj->properties->properties[i]->base.id == arg->prop_id)
5048 break;
5049
5050 if (i == arg_obj->properties->count)
5051 goto out;
5052
5053 prop_obj = drm_mode_object_find(dev, arg->prop_id,
5054 DRM_MODE_OBJECT_PROPERTY);
5055 if (!prop_obj) {
5056 ret = -ENOENT;
5057 goto out;
5058 }
5059 property = obj_to_property(prop_obj);
5060
5061 if (!drm_property_change_valid_get(property, arg->value, &ref))
5062 goto out;
5063
5064 switch (arg_obj->type) {
5065 case DRM_MODE_OBJECT_CONNECTOR:
5066 ret = drm_mode_connector_set_obj_prop(arg_obj, property,
5067 arg->value);
5068 break;
5069 case DRM_MODE_OBJECT_CRTC:
5070 ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
5071 break;
5072 case DRM_MODE_OBJECT_PLANE:
5073 ret = drm_mode_plane_set_obj_prop(obj_to_plane(arg_obj),
5074 property, arg->value);
5075 break;
5076 }
5077
5078 drm_property_change_valid_put(property, ref);
5079
5080out:
5081 drm_modeset_unlock_all(dev);
5082 return ret;
5083}
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097int drm_mode_connector_attach_encoder(struct drm_connector *connector,
5098 struct drm_encoder *encoder)
5099{
5100 int i;
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113 if (WARN_ON(connector->encoder))
5114 return -EINVAL;
5115
5116 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
5117 if (connector->encoder_ids[i] == 0) {
5118 connector->encoder_ids[i] = encoder->base.id;
5119 return 0;
5120 }
5121 }
5122 return -ENOMEM;
5123}
5124EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
5139 int gamma_size)
5140{
5141 crtc->gamma_size = gamma_size;
5142
5143 crtc->gamma_store = kcalloc(gamma_size, sizeof(uint16_t) * 3,
5144 GFP_KERNEL);
5145 if (!crtc->gamma_store) {
5146 crtc->gamma_size = 0;
5147 return -ENOMEM;
5148 }
5149
5150 return 0;
5151}
5152EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168int drm_mode_gamma_set_ioctl(struct drm_device *dev,
5169 void *data, struct drm_file *file_priv)
5170{
5171 struct drm_mode_crtc_lut *crtc_lut = data;
5172 struct drm_crtc *crtc;
5173 void *r_base, *g_base, *b_base;
5174 int size;
5175 int ret = 0;
5176
5177 if (!drm_core_check_feature(dev, DRIVER_MODESET))
5178 return -EINVAL;
5179
5180 drm_modeset_lock_all(dev);
5181 crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
5182 if (!crtc) {
5183 ret = -ENOENT;
5184 goto out;
5185 }
5186
5187 if (crtc->funcs->gamma_set == NULL) {
5188 ret = -ENOSYS;
5189 goto out;
5190 }
5191
5192
5193 if (crtc_lut->gamma_size != crtc->gamma_size) {
5194 ret = -EINVAL;
5195 goto out;
5196 }
5197
5198 size = crtc_lut->gamma_size * (sizeof(uint16_t));
5199 r_base = crtc->gamma_store;
5200 if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) {
5201 ret = -EFAULT;
5202 goto out;
5203 }
5204
5205 g_base = r_base + size;
5206 if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) {
5207 ret = -EFAULT;
5208 goto out;
5209 }
5210
5211 b_base = g_base + size;
5212 if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) {
5213 ret = -EFAULT;
5214 goto out;
5215 }
5216
5217 crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
5218
5219out:
5220 drm_modeset_unlock_all(dev);
5221 return ret;
5222
5223}
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240int drm_mode_gamma_get_ioctl(struct drm_device *dev,
5241 void *data, struct drm_file *file_priv)
5242{
5243 struct drm_mode_crtc_lut *crtc_lut = data;
5244 struct drm_crtc *crtc;
5245 void *r_base, *g_base, *b_base;
5246 int size;
5247 int ret = 0;
5248
5249 if (!drm_core_check_feature(dev, DRIVER_MODESET))
5250 return -EINVAL;
5251
5252 drm_modeset_lock_all(dev);
5253 crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
5254 if (!crtc) {
5255 ret = -ENOENT;
5256 goto out;
5257 }
5258
5259
5260 if (crtc_lut->gamma_size != crtc->gamma_size) {
5261 ret = -EINVAL;
5262 goto out;
5263 }
5264
5265 size = crtc_lut->gamma_size * (sizeof(uint16_t));
5266 r_base = crtc->gamma_store;
5267 if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) {
5268 ret = -EFAULT;
5269 goto out;
5270 }
5271
5272 g_base = r_base + size;
5273 if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) {
5274 ret = -EFAULT;
5275 goto out;
5276 }
5277
5278 b_base = g_base + size;
5279 if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) {
5280 ret = -EFAULT;
5281 goto out;
5282 }
5283out:
5284 drm_modeset_unlock_all(dev);
5285 return ret;
5286}
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306int drm_mode_page_flip_ioctl(struct drm_device *dev,
5307 void *data, struct drm_file *file_priv)
5308{
5309 struct drm_mode_crtc_page_flip *page_flip = data;
5310 struct drm_crtc *crtc;
5311 struct drm_framebuffer *fb = NULL;
5312 struct drm_pending_vblank_event *e = NULL;
5313 int ret = -EINVAL;
5314
5315 if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
5316 page_flip->reserved != 0)
5317 return -EINVAL;
5318
5319 if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
5320 return -EINVAL;
5321
5322 crtc = drm_crtc_find(dev, page_flip->crtc_id);
5323 if (!crtc)
5324 return -ENOENT;
5325
5326 drm_modeset_lock_crtc(crtc, crtc->primary);
5327 if (crtc->primary->fb == NULL) {
5328
5329
5330
5331
5332 ret = -EBUSY;
5333 goto out;
5334 }
5335
5336 if (crtc->funcs->page_flip == NULL)
5337 goto out;
5338
5339 fb = drm_framebuffer_lookup(dev, page_flip->fb_id);
5340 if (!fb) {
5341 ret = -ENOENT;
5342 goto out;
5343 }
5344
5345 if (crtc->state) {
5346 const struct drm_plane_state *state = crtc->primary->state;
5347
5348 ret = check_src_coords(state->src_x, state->src_y,
5349 state->src_w, state->src_h, fb);
5350 } else {
5351 ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, &crtc->mode, fb);
5352 }
5353 if (ret)
5354 goto out;
5355
5356 if (crtc->primary->fb->pixel_format != fb->pixel_format) {
5357 DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
5358 ret = -EINVAL;
5359 goto out;
5360 }
5361
5362 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
5363 e = kzalloc(sizeof *e, GFP_KERNEL);
5364 if (!e) {
5365 ret = -ENOMEM;
5366 goto out;
5367 }
5368 e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
5369 e->event.base.length = sizeof(e->event);
5370 e->event.user_data = page_flip->user_data;
5371 ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
5372 if (ret) {
5373 kfree(e);
5374 goto out;
5375 }
5376 }
5377
5378 crtc->primary->old_fb = crtc->primary->fb;
5379 ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
5380 if (ret) {
5381 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
5382 drm_event_cancel_free(dev, &e->base);
5383
5384 crtc->primary->old_fb = NULL;
5385 } else {
5386 crtc->primary->fb = fb;
5387
5388 fb = NULL;
5389 }
5390
5391out:
5392 if (fb)
5393 drm_framebuffer_unreference(fb);
5394 if (crtc->primary->old_fb)
5395 drm_framebuffer_unreference(crtc->primary->old_fb);
5396 crtc->primary->old_fb = NULL;
5397 drm_modeset_unlock_crtc(crtc);
5398
5399 return ret;
5400}
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410void drm_mode_config_reset(struct drm_device *dev)
5411{
5412 struct drm_crtc *crtc;
5413 struct drm_plane *plane;
5414 struct drm_encoder *encoder;
5415 struct drm_connector *connector;
5416
5417 drm_for_each_plane(plane, dev)
5418 if (plane->funcs->reset)
5419 plane->funcs->reset(plane);
5420
5421 drm_for_each_crtc(crtc, dev)
5422 if (crtc->funcs->reset)
5423 crtc->funcs->reset(crtc);
5424
5425 drm_for_each_encoder(encoder, dev)
5426 if (encoder->funcs->reset)
5427 encoder->funcs->reset(encoder);
5428
5429 mutex_lock(&dev->mode_config.mutex);
5430 drm_for_each_connector(connector, dev)
5431 if (connector->funcs->reset)
5432 connector->funcs->reset(connector);
5433 mutex_unlock(&dev->mode_config.mutex);
5434}
5435EXPORT_SYMBOL(drm_mode_config_reset);
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456int drm_mode_create_dumb_ioctl(struct drm_device *dev,
5457 void *data, struct drm_file *file_priv)
5458{
5459 struct drm_mode_create_dumb *args = data;
5460 u32 cpp, stride, size;
5461
5462 if (!dev->driver->dumb_create)
5463 return -ENOSYS;
5464 if (!args->width || !args->height || !args->bpp)
5465 return -EINVAL;
5466
5467
5468
5469 cpp = DIV_ROUND_UP(args->bpp, 8);
5470 if (!cpp || cpp > 0xffffffffU / args->width)
5471 return -EINVAL;
5472 stride = cpp * args->width;
5473 if (args->height > 0xffffffffU / stride)
5474 return -EINVAL;
5475
5476
5477 size = args->height * stride;
5478 if (PAGE_ALIGN(size) == 0)
5479 return -EINVAL;
5480
5481
5482
5483
5484
5485
5486
5487 args->handle = 0;
5488 args->pitch = 0;
5489 args->size = 0;
5490
5491 return dev->driver->dumb_create(file_priv, dev, args);
5492}
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
5509 void *data, struct drm_file *file_priv)
5510{
5511 struct drm_mode_map_dumb *args = data;
5512
5513
5514 if (!dev->driver->dumb_map_offset)
5515 return -ENOSYS;
5516
5517 return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
5518}
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
5536 void *data, struct drm_file *file_priv)
5537{
5538 struct drm_mode_destroy_dumb *args = data;
5539
5540 if (!dev->driver->dumb_destroy)
5541 return -ENOSYS;
5542
5543 return dev->driver->dumb_destroy(file_priv, dev, args->handle);
5544}
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
5556 int *bpp)
5557{
5558 switch (format) {
5559 case DRM_FORMAT_C8:
5560 case DRM_FORMAT_RGB332:
5561 case DRM_FORMAT_BGR233:
5562 *depth = 8;
5563 *bpp = 8;
5564 break;
5565 case DRM_FORMAT_XRGB1555:
5566 case DRM_FORMAT_XBGR1555:
5567 case DRM_FORMAT_RGBX5551:
5568 case DRM_FORMAT_BGRX5551:
5569 case DRM_FORMAT_ARGB1555:
5570 case DRM_FORMAT_ABGR1555:
5571 case DRM_FORMAT_RGBA5551:
5572 case DRM_FORMAT_BGRA5551:
5573 *depth = 15;
5574 *bpp = 16;
5575 break;
5576 case DRM_FORMAT_RGB565:
5577 case DRM_FORMAT_BGR565:
5578 *depth = 16;
5579 *bpp = 16;
5580 break;
5581 case DRM_FORMAT_RGB888:
5582 case DRM_FORMAT_BGR888:
5583 *depth = 24;
5584 *bpp = 24;
5585 break;
5586 case DRM_FORMAT_XRGB8888:
5587 case DRM_FORMAT_XBGR8888:
5588 case DRM_FORMAT_RGBX8888:
5589 case DRM_FORMAT_BGRX8888:
5590 *depth = 24;
5591 *bpp = 32;
5592 break;
5593 case DRM_FORMAT_XRGB2101010:
5594 case DRM_FORMAT_XBGR2101010:
5595 case DRM_FORMAT_RGBX1010102:
5596 case DRM_FORMAT_BGRX1010102:
5597 case DRM_FORMAT_ARGB2101010:
5598 case DRM_FORMAT_ABGR2101010:
5599 case DRM_FORMAT_RGBA1010102:
5600 case DRM_FORMAT_BGRA1010102:
5601 *depth = 30;
5602 *bpp = 32;
5603 break;
5604 case DRM_FORMAT_ARGB8888:
5605 case DRM_FORMAT_ABGR8888:
5606 case DRM_FORMAT_RGBA8888:
5607 case DRM_FORMAT_BGRA8888:
5608 *depth = 32;
5609 *bpp = 32;
5610 break;
5611 default:
5612 DRM_DEBUG_KMS("unsupported pixel format %s\n",
5613 drm_get_format_name(format));
5614 *depth = 0;
5615 *bpp = 0;
5616 break;
5617 }
5618}
5619EXPORT_SYMBOL(drm_fb_get_bpp_depth);
5620
5621
5622
5623
5624
5625
5626
5627
5628int drm_format_num_planes(uint32_t format)
5629{
5630 switch (format) {
5631 case DRM_FORMAT_YUV410:
5632 case DRM_FORMAT_YVU410:
5633 case DRM_FORMAT_YUV411:
5634 case DRM_FORMAT_YVU411:
5635 case DRM_FORMAT_YUV420:
5636 case DRM_FORMAT_YVU420:
5637 case DRM_FORMAT_YUV422:
5638 case DRM_FORMAT_YVU422:
5639 case DRM_FORMAT_YUV444:
5640 case DRM_FORMAT_YVU444:
5641 return 3;
5642 case DRM_FORMAT_NV12:
5643 case DRM_FORMAT_NV21:
5644 case DRM_FORMAT_NV16:
5645 case DRM_FORMAT_NV61:
5646 case DRM_FORMAT_NV24:
5647 case DRM_FORMAT_NV42:
5648 return 2;
5649 default:
5650 return 1;
5651 }
5652}
5653EXPORT_SYMBOL(drm_format_num_planes);
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663int drm_format_plane_cpp(uint32_t format, int plane)
5664{
5665 unsigned int depth;
5666 int bpp;
5667
5668 if (plane >= drm_format_num_planes(format))
5669 return 0;
5670
5671 switch (format) {
5672 case DRM_FORMAT_YUYV:
5673 case DRM_FORMAT_YVYU:
5674 case DRM_FORMAT_UYVY:
5675 case DRM_FORMAT_VYUY:
5676 return 2;
5677 case DRM_FORMAT_NV12:
5678 case DRM_FORMAT_NV21:
5679 case DRM_FORMAT_NV16:
5680 case DRM_FORMAT_NV61:
5681 case DRM_FORMAT_NV24:
5682 case DRM_FORMAT_NV42:
5683 return plane ? 2 : 1;
5684 case DRM_FORMAT_YUV410:
5685 case DRM_FORMAT_YVU410:
5686 case DRM_FORMAT_YUV411:
5687 case DRM_FORMAT_YVU411:
5688 case DRM_FORMAT_YUV420:
5689 case DRM_FORMAT_YVU420:
5690 case DRM_FORMAT_YUV422:
5691 case DRM_FORMAT_YVU422:
5692 case DRM_FORMAT_YUV444:
5693 case DRM_FORMAT_YVU444:
5694 return 1;
5695 default:
5696 drm_fb_get_bpp_depth(format, &depth, &bpp);
5697 return bpp >> 3;
5698 }
5699}
5700EXPORT_SYMBOL(drm_format_plane_cpp);
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710int drm_format_horz_chroma_subsampling(uint32_t format)
5711{
5712 switch (format) {
5713 case DRM_FORMAT_YUV411:
5714 case DRM_FORMAT_YVU411:
5715 case DRM_FORMAT_YUV410:
5716 case DRM_FORMAT_YVU410:
5717 return 4;
5718 case DRM_FORMAT_YUYV:
5719 case DRM_FORMAT_YVYU:
5720 case DRM_FORMAT_UYVY:
5721 case DRM_FORMAT_VYUY:
5722 case DRM_FORMAT_NV12:
5723 case DRM_FORMAT_NV21:
5724 case DRM_FORMAT_NV16:
5725 case DRM_FORMAT_NV61:
5726 case DRM_FORMAT_YUV422:
5727 case DRM_FORMAT_YVU422:
5728 case DRM_FORMAT_YUV420:
5729 case DRM_FORMAT_YVU420:
5730 return 2;
5731 default:
5732 return 1;
5733 }
5734}
5735EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745int drm_format_vert_chroma_subsampling(uint32_t format)
5746{
5747 switch (format) {
5748 case DRM_FORMAT_YUV410:
5749 case DRM_FORMAT_YVU410:
5750 return 4;
5751 case DRM_FORMAT_YUV420:
5752 case DRM_FORMAT_YVU420:
5753 case DRM_FORMAT_NV12:
5754 case DRM_FORMAT_NV21:
5755 return 2;
5756 default:
5757 return 1;
5758 }
5759}
5760EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771int drm_format_plane_width(int width, uint32_t format, int plane)
5772{
5773 if (plane >= drm_format_num_planes(format))
5774 return 0;
5775
5776 if (plane == 0)
5777 return width;
5778
5779 return width / drm_format_horz_chroma_subsampling(format);
5780}
5781EXPORT_SYMBOL(drm_format_plane_width);
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792int drm_format_plane_height(int height, uint32_t format, int plane)
5793{
5794 if (plane >= drm_format_num_planes(format))
5795 return 0;
5796
5797 if (plane == 0)
5798 return height;
5799
5800 return height / drm_format_vert_chroma_subsampling(format);
5801}
5802EXPORT_SYMBOL(drm_format_plane_height);
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822unsigned int drm_rotation_simplify(unsigned int rotation,
5823 unsigned int supported_rotations)
5824{
5825 if (rotation & ~supported_rotations) {
5826 rotation ^= BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y);
5827 rotation = (rotation & DRM_REFLECT_MASK) |
5828 BIT((ffs(rotation & DRM_ROTATE_MASK) + 1) % 4);
5829 }
5830
5831 return rotation;
5832}
5833EXPORT_SYMBOL(drm_rotation_simplify);
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847void drm_mode_config_init(struct drm_device *dev)
5848{
5849 mutex_init(&dev->mode_config.mutex);
5850 drm_modeset_lock_init(&dev->mode_config.connection_mutex);
5851 mutex_init(&dev->mode_config.idr_mutex);
5852 mutex_init(&dev->mode_config.fb_lock);
5853 mutex_init(&dev->mode_config.blob_lock);
5854 INIT_LIST_HEAD(&dev->mode_config.fb_list);
5855 INIT_LIST_HEAD(&dev->mode_config.crtc_list);
5856 INIT_LIST_HEAD(&dev->mode_config.connector_list);
5857 INIT_LIST_HEAD(&dev->mode_config.encoder_list);
5858 INIT_LIST_HEAD(&dev->mode_config.property_list);
5859 INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
5860 INIT_LIST_HEAD(&dev->mode_config.plane_list);
5861 idr_init(&dev->mode_config.crtc_idr);
5862 idr_init(&dev->mode_config.tile_idr);
5863 ida_init(&dev->mode_config.connector_ida);
5864
5865 drm_modeset_lock_all(dev);
5866 drm_mode_create_standard_properties(dev);
5867 drm_modeset_unlock_all(dev);
5868
5869
5870 dev->mode_config.num_fb = 0;
5871 dev->mode_config.num_connector = 0;
5872 dev->mode_config.num_crtc = 0;
5873 dev->mode_config.num_encoder = 0;
5874 dev->mode_config.num_overlay_plane = 0;
5875 dev->mode_config.num_total_plane = 0;
5876}
5877EXPORT_SYMBOL(drm_mode_config_init);
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892void drm_mode_config_cleanup(struct drm_device *dev)
5893{
5894 struct drm_connector *connector, *ot;
5895 struct drm_crtc *crtc, *ct;
5896 struct drm_encoder *encoder, *enct;
5897 struct drm_framebuffer *fb, *fbt;
5898 struct drm_property *property, *pt;
5899 struct drm_property_blob *blob, *bt;
5900 struct drm_plane *plane, *plt;
5901
5902 list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
5903 head) {
5904 encoder->funcs->destroy(encoder);
5905 }
5906
5907 list_for_each_entry_safe(connector, ot,
5908 &dev->mode_config.connector_list, head) {
5909 connector->funcs->destroy(connector);
5910 }
5911
5912 list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
5913 head) {
5914 drm_property_destroy(dev, property);
5915 }
5916
5917 list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
5918 head_global) {
5919 drm_property_unreference_blob(blob);
5920 }
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930 WARN_ON(!list_empty(&dev->mode_config.fb_list));
5931 list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
5932 drm_framebuffer_free(&fb->refcount);
5933 }
5934
5935 list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
5936 head) {
5937 plane->funcs->destroy(plane);
5938 }
5939
5940 list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
5941 crtc->funcs->destroy(crtc);
5942 }
5943
5944 ida_destroy(&dev->mode_config.connector_ida);
5945 idr_destroy(&dev->mode_config.tile_idr);
5946 idr_destroy(&dev->mode_config.crtc_idr);
5947 drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
5948}
5949EXPORT_SYMBOL(drm_mode_config_cleanup);
5950
5951struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
5952 unsigned int supported_rotations)
5953{
5954 static const struct drm_prop_enum_list props[] = {
5955 { DRM_ROTATE_0, "rotate-0" },
5956 { DRM_ROTATE_90, "rotate-90" },
5957 { DRM_ROTATE_180, "rotate-180" },
5958 { DRM_ROTATE_270, "rotate-270" },
5959 { DRM_REFLECT_X, "reflect-x" },
5960 { DRM_REFLECT_Y, "reflect-y" },
5961 };
5962
5963 return drm_property_create_bitmask(dev, 0, "rotation",
5964 props, ARRAY_SIZE(props),
5965 supported_rotations);
5966}
5967EXPORT_SYMBOL(drm_mode_create_rotation_property);
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977static void drm_tile_group_free(struct kref *kref)
5978{
5979 struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
5980 struct drm_device *dev = tg->dev;
5981 mutex_lock(&dev->mode_config.idr_mutex);
5982 idr_remove(&dev->mode_config.tile_idr, tg->id);
5983 mutex_unlock(&dev->mode_config.idr_mutex);
5984 kfree(tg);
5985}
5986
5987
5988
5989
5990
5991
5992
5993
5994void drm_mode_put_tile_group(struct drm_device *dev,
5995 struct drm_tile_group *tg)
5996{
5997 kref_put(&tg->refcount, drm_tile_group_free);
5998}
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
6011 char topology[8])
6012{
6013 struct drm_tile_group *tg;
6014 int id;
6015 mutex_lock(&dev->mode_config.idr_mutex);
6016 idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
6017 if (!memcmp(tg->group_data, topology, 8)) {
6018 if (!kref_get_unless_zero(&tg->refcount))
6019 tg = NULL;
6020 mutex_unlock(&dev->mode_config.idr_mutex);
6021 return tg;
6022 }
6023 }
6024 mutex_unlock(&dev->mode_config.idr_mutex);
6025 return NULL;
6026}
6027EXPORT_SYMBOL(drm_mode_get_tile_group);
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
6041 char topology[8])
6042{
6043 struct drm_tile_group *tg;
6044 int ret;
6045
6046 tg = kzalloc(sizeof(*tg), GFP_KERNEL);
6047 if (!tg)
6048 return ERR_PTR(-ENOMEM);
6049
6050 kref_init(&tg->refcount);
6051 memcpy(tg->group_data, topology, 8);
6052 tg->dev = dev;
6053
6054 mutex_lock(&dev->mode_config.idr_mutex);
6055 ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL);
6056 if (ret >= 0) {
6057 tg->id = ret;
6058 } else {
6059 kfree(tg);
6060 tg = ERR_PTR(ret);
6061 }
6062
6063 mutex_unlock(&dev->mode_config.idr_mutex);
6064 return tg;
6065}
6066EXPORT_SYMBOL(drm_mode_create_tile_group);
6067