1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <drm/drm_auth.h>
24#include <drm/drm_connector.h>
25#include <drm/drm_edid.h>
26#include <drm/drm_encoder.h>
27#include <drm/drm_utils.h>
28#include <drm/drm_print.h>
29#include <drm/drm_drv.h>
30#include <drm/drm_file.h>
31#include <drm/drm_sysfs.h>
32
33#include <linux/uaccess.h>
34
35#include "drm_crtc_internal.h"
36#include "drm_internal.h"
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68struct drm_conn_prop_enum_list {
69 int type;
70 const char *name;
71 struct ida ida;
72};
73
74
75
76
77static struct drm_conn_prop_enum_list drm_connector_enum_list[] = {
78 { DRM_MODE_CONNECTOR_Unknown, "Unknown" },
79 { DRM_MODE_CONNECTOR_VGA, "VGA" },
80 { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
81 { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
82 { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
83 { DRM_MODE_CONNECTOR_Composite, "Composite" },
84 { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" },
85 { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
86 { DRM_MODE_CONNECTOR_Component, "Component" },
87 { DRM_MODE_CONNECTOR_9PinDIN, "DIN" },
88 { DRM_MODE_CONNECTOR_DisplayPort, "DP" },
89 { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
90 { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
91 { DRM_MODE_CONNECTOR_TV, "TV" },
92 { DRM_MODE_CONNECTOR_eDP, "eDP" },
93 { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
94 { DRM_MODE_CONNECTOR_DSI, "DSI" },
95 { DRM_MODE_CONNECTOR_DPI, "DPI" },
96 { DRM_MODE_CONNECTOR_WRITEBACK, "Writeback" },
97 { DRM_MODE_CONNECTOR_SPI, "SPI" },
98 { DRM_MODE_CONNECTOR_USB, "USB" },
99};
100
101void drm_connector_ida_init(void)
102{
103 int i;
104
105 for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
106 ida_init(&drm_connector_enum_list[i].ida);
107}
108
109void drm_connector_ida_destroy(void)
110{
111 int i;
112
113 for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
114 ida_destroy(&drm_connector_enum_list[i].ida);
115}
116
117
118
119
120
121
122
123const char *drm_get_connector_type_name(unsigned int type)
124{
125 if (type < ARRAY_SIZE(drm_connector_enum_list))
126 return drm_connector_enum_list[type].name;
127
128 return NULL;
129}
130EXPORT_SYMBOL(drm_get_connector_type_name);
131
132
133
134
135
136
137
138
139
140
141
142static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
143{
144 struct drm_cmdline_mode *mode = &connector->cmdline_mode;
145 char *option = NULL;
146
147 if (fb_get_options(connector->name, &option))
148 return;
149
150 if (!drm_mode_parse_command_line_for_connector(option,
151 connector,
152 mode))
153 return;
154
155 if (mode->force) {
156 DRM_INFO("forcing %s connector %s\n", connector->name,
157 drm_get_connector_force_name(mode->force));
158 connector->force = mode->force;
159 }
160
161 if (mode->panel_orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) {
162 DRM_INFO("cmdline forces connector %s panel_orientation to %d\n",
163 connector->name, mode->panel_orientation);
164 drm_connector_set_panel_orientation(connector,
165 mode->panel_orientation);
166 }
167
168 DRM_DEBUG_KMS("cmdline mode for connector %s %s %dx%d@%dHz%s%s%s\n",
169 connector->name, mode->name,
170 mode->xres, mode->yres,
171 mode->refresh_specified ? mode->refresh : 60,
172 mode->rb ? " reduced blanking" : "",
173 mode->margins ? " with margins" : "",
174 mode->interlace ? " interlaced" : "");
175}
176
177static void drm_connector_free(struct kref *kref)
178{
179 struct drm_connector *connector =
180 container_of(kref, struct drm_connector, base.refcount);
181 struct drm_device *dev = connector->dev;
182
183 drm_mode_object_unregister(dev, &connector->base);
184 connector->funcs->destroy(connector);
185}
186
187void drm_connector_free_work_fn(struct work_struct *work)
188{
189 struct drm_connector *connector, *n;
190 struct drm_device *dev =
191 container_of(work, struct drm_device, mode_config.connector_free_work);
192 struct drm_mode_config *config = &dev->mode_config;
193 unsigned long flags;
194 struct llist_node *freed;
195
196 spin_lock_irqsave(&config->connector_list_lock, flags);
197 freed = llist_del_all(&config->connector_free_list);
198 spin_unlock_irqrestore(&config->connector_list_lock, flags);
199
200 llist_for_each_entry_safe(connector, n, freed, free_node) {
201 drm_mode_object_unregister(dev, &connector->base);
202 connector->funcs->destroy(connector);
203 }
204}
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219int drm_connector_init(struct drm_device *dev,
220 struct drm_connector *connector,
221 const struct drm_connector_funcs *funcs,
222 int connector_type)
223{
224 struct drm_mode_config *config = &dev->mode_config;
225 int ret;
226 struct ida *connector_ida =
227 &drm_connector_enum_list[connector_type].ida;
228
229 WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
230 (!funcs->atomic_destroy_state ||
231 !funcs->atomic_duplicate_state));
232
233 ret = __drm_mode_object_add(dev, &connector->base,
234 DRM_MODE_OBJECT_CONNECTOR,
235 false, drm_connector_free);
236 if (ret)
237 return ret;
238
239 connector->base.properties = &connector->properties;
240 connector->dev = dev;
241 connector->funcs = funcs;
242
243
244 ret = ida_simple_get(&config->connector_ida, 0, 32, GFP_KERNEL);
245 if (ret < 0) {
246 DRM_DEBUG_KMS("Failed to allocate %s connector index: %d\n",
247 drm_connector_enum_list[connector_type].name,
248 ret);
249 goto out_put;
250 }
251 connector->index = ret;
252 ret = 0;
253
254 connector->connector_type = connector_type;
255 connector->connector_type_id =
256 ida_simple_get(connector_ida, 1, 0, GFP_KERNEL);
257 if (connector->connector_type_id < 0) {
258 ret = connector->connector_type_id;
259 goto out_put_id;
260 }
261 connector->name =
262 kasprintf(GFP_KERNEL, "%s-%d",
263 drm_connector_enum_list[connector_type].name,
264 connector->connector_type_id);
265 if (!connector->name) {
266 ret = -ENOMEM;
267 goto out_put_type_id;
268 }
269
270 INIT_LIST_HEAD(&connector->probed_modes);
271 INIT_LIST_HEAD(&connector->modes);
272 mutex_init(&connector->mutex);
273 connector->edid_blob_ptr = NULL;
274 connector->epoch_counter = 0;
275 connector->tile_blob_ptr = NULL;
276 connector->status = connector_status_unknown;
277 connector->display_info.panel_orientation =
278 DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
279
280 drm_connector_get_cmdline_mode(connector);
281
282
283
284
285 spin_lock_irq(&config->connector_list_lock);
286 list_add_tail(&connector->head, &config->connector_list);
287 config->num_connector++;
288 spin_unlock_irq(&config->connector_list_lock);
289
290 if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL &&
291 connector_type != DRM_MODE_CONNECTOR_WRITEBACK)
292 drm_connector_attach_edid_property(connector);
293
294 drm_object_attach_property(&connector->base,
295 config->dpms_property, 0);
296
297 drm_object_attach_property(&connector->base,
298 config->link_status_property,
299 0);
300
301 drm_object_attach_property(&connector->base,
302 config->non_desktop_property,
303 0);
304 drm_object_attach_property(&connector->base,
305 config->tile_property,
306 0);
307
308 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
309 drm_object_attach_property(&connector->base, config->prop_crtc_id, 0);
310 }
311
312 connector->debugfs_entry = NULL;
313out_put_type_id:
314 if (ret)
315 ida_simple_remove(connector_ida, connector->connector_type_id);
316out_put_id:
317 if (ret)
318 ida_simple_remove(&config->connector_ida, connector->index);
319out_put:
320 if (ret)
321 drm_mode_object_unregister(dev, &connector->base);
322
323 return ret;
324}
325EXPORT_SYMBOL(drm_connector_init);
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343int drm_connector_init_with_ddc(struct drm_device *dev,
344 struct drm_connector *connector,
345 const struct drm_connector_funcs *funcs,
346 int connector_type,
347 struct i2c_adapter *ddc)
348{
349 int ret;
350
351 ret = drm_connector_init(dev, connector, funcs, connector_type);
352 if (ret)
353 return ret;
354
355
356 connector->ddc = ddc;
357
358 return ret;
359}
360EXPORT_SYMBOL(drm_connector_init_with_ddc);
361
362
363
364
365
366
367
368
369
370void drm_connector_attach_edid_property(struct drm_connector *connector)
371{
372 struct drm_mode_config *config = &connector->dev->mode_config;
373
374 drm_object_attach_property(&connector->base,
375 config->edid_property,
376 0);
377}
378EXPORT_SYMBOL(drm_connector_attach_edid_property);
379
380
381
382
383
384
385
386
387
388
389
390
391
392int drm_connector_attach_encoder(struct drm_connector *connector,
393 struct drm_encoder *encoder)
394{
395
396
397
398
399
400
401
402
403
404
405
406 if (WARN_ON(connector->encoder))
407 return -EINVAL;
408
409 connector->possible_encoders |= drm_encoder_mask(encoder);
410
411 return 0;
412}
413EXPORT_SYMBOL(drm_connector_attach_encoder);
414
415
416
417
418
419
420
421
422
423
424bool drm_connector_has_possible_encoder(struct drm_connector *connector,
425 struct drm_encoder *encoder)
426{
427 return connector->possible_encoders & drm_encoder_mask(encoder);
428}
429EXPORT_SYMBOL(drm_connector_has_possible_encoder);
430
431static void drm_mode_remove(struct drm_connector *connector,
432 struct drm_display_mode *mode)
433{
434 list_del(&mode->head);
435 drm_mode_destroy(connector->dev, mode);
436}
437
438
439
440
441
442
443
444void drm_connector_cleanup(struct drm_connector *connector)
445{
446 struct drm_device *dev = connector->dev;
447 struct drm_display_mode *mode, *t;
448
449
450
451
452 if (WARN_ON(connector->registration_state ==
453 DRM_CONNECTOR_REGISTERED))
454 drm_connector_unregister(connector);
455
456 if (connector->tile_group) {
457 drm_mode_put_tile_group(dev, connector->tile_group);
458 connector->tile_group = NULL;
459 }
460
461 list_for_each_entry_safe(mode, t, &connector->probed_modes, head)
462 drm_mode_remove(connector, mode);
463
464 list_for_each_entry_safe(mode, t, &connector->modes, head)
465 drm_mode_remove(connector, mode);
466
467 ida_simple_remove(&drm_connector_enum_list[connector->connector_type].ida,
468 connector->connector_type_id);
469
470 ida_simple_remove(&dev->mode_config.connector_ida,
471 connector->index);
472
473 kfree(connector->display_info.bus_formats);
474 drm_mode_object_unregister(dev, &connector->base);
475 kfree(connector->name);
476 connector->name = NULL;
477 spin_lock_irq(&dev->mode_config.connector_list_lock);
478 list_del(&connector->head);
479 dev->mode_config.num_connector--;
480 spin_unlock_irq(&dev->mode_config.connector_list_lock);
481
482 WARN_ON(connector->state && !connector->funcs->atomic_destroy_state);
483 if (connector->state && connector->funcs->atomic_destroy_state)
484 connector->funcs->atomic_destroy_state(connector,
485 connector->state);
486
487 mutex_destroy(&connector->mutex);
488
489 memset(connector, 0, sizeof(*connector));
490}
491EXPORT_SYMBOL(drm_connector_cleanup);
492
493
494
495
496
497
498
499
500
501
502
503
504
505int drm_connector_register(struct drm_connector *connector)
506{
507 int ret = 0;
508
509 if (!connector->dev->registered)
510 return 0;
511
512 mutex_lock(&connector->mutex);
513 if (connector->registration_state != DRM_CONNECTOR_INITIALIZING)
514 goto unlock;
515
516 ret = drm_sysfs_connector_add(connector);
517 if (ret)
518 goto unlock;
519
520 drm_debugfs_connector_add(connector);
521
522 if (connector->funcs->late_register) {
523 ret = connector->funcs->late_register(connector);
524 if (ret)
525 goto err_debugfs;
526 }
527
528 drm_mode_object_register(connector->dev, &connector->base);
529
530 connector->registration_state = DRM_CONNECTOR_REGISTERED;
531
532
533 drm_sysfs_hotplug_event(connector->dev);
534
535 goto unlock;
536
537err_debugfs:
538 drm_debugfs_connector_remove(connector);
539 drm_sysfs_connector_remove(connector);
540unlock:
541 mutex_unlock(&connector->mutex);
542 return ret;
543}
544EXPORT_SYMBOL(drm_connector_register);
545
546
547
548
549
550
551
552
553
554
555void drm_connector_unregister(struct drm_connector *connector)
556{
557 mutex_lock(&connector->mutex);
558 if (connector->registration_state != DRM_CONNECTOR_REGISTERED) {
559 mutex_unlock(&connector->mutex);
560 return;
561 }
562
563 if (connector->funcs->early_unregister)
564 connector->funcs->early_unregister(connector);
565
566 drm_sysfs_connector_remove(connector);
567 drm_debugfs_connector_remove(connector);
568
569 connector->registration_state = DRM_CONNECTOR_UNREGISTERED;
570 mutex_unlock(&connector->mutex);
571}
572EXPORT_SYMBOL(drm_connector_unregister);
573
574void drm_connector_unregister_all(struct drm_device *dev)
575{
576 struct drm_connector *connector;
577 struct drm_connector_list_iter conn_iter;
578
579 drm_connector_list_iter_begin(dev, &conn_iter);
580 drm_for_each_connector_iter(connector, &conn_iter)
581 drm_connector_unregister(connector);
582 drm_connector_list_iter_end(&conn_iter);
583}
584
585int drm_connector_register_all(struct drm_device *dev)
586{
587 struct drm_connector *connector;
588 struct drm_connector_list_iter conn_iter;
589 int ret = 0;
590
591 drm_connector_list_iter_begin(dev, &conn_iter);
592 drm_for_each_connector_iter(connector, &conn_iter) {
593 ret = drm_connector_register(connector);
594 if (ret)
595 break;
596 }
597 drm_connector_list_iter_end(&conn_iter);
598
599 if (ret)
600 drm_connector_unregister_all(dev);
601 return ret;
602}
603
604
605
606
607
608
609
610
611const char *drm_get_connector_status_name(enum drm_connector_status status)
612{
613 if (status == connector_status_connected)
614 return "connected";
615 else if (status == connector_status_disconnected)
616 return "disconnected";
617 else
618 return "unknown";
619}
620EXPORT_SYMBOL(drm_get_connector_status_name);
621
622
623
624
625
626
627
628const char *drm_get_connector_force_name(enum drm_connector_force force)
629{
630 switch (force) {
631 case DRM_FORCE_UNSPECIFIED:
632 return "unspecified";
633 case DRM_FORCE_OFF:
634 return "off";
635 case DRM_FORCE_ON:
636 return "on";
637 case DRM_FORCE_ON_DIGITAL:
638 return "digital";
639 default:
640 return "unknown";
641 }
642}
643
644#ifdef CONFIG_LOCKDEP
645static struct lockdep_map connector_list_iter_dep_map = {
646 .name = "drm_connector_list_iter"
647};
648#endif
649
650
651
652
653
654
655
656
657
658
659
660void drm_connector_list_iter_begin(struct drm_device *dev,
661 struct drm_connector_list_iter *iter)
662{
663 iter->dev = dev;
664 iter->conn = NULL;
665 lock_acquire_shared_recursive(&connector_list_iter_dep_map, 0, 1, NULL, _RET_IP_);
666}
667EXPORT_SYMBOL(drm_connector_list_iter_begin);
668
669
670
671
672
673
674static void
675__drm_connector_put_safe(struct drm_connector *conn)
676{
677 struct drm_mode_config *config = &conn->dev->mode_config;
678
679 lockdep_assert_held(&config->connector_list_lock);
680
681 if (!refcount_dec_and_test(&conn->base.refcount.refcount))
682 return;
683
684 llist_add(&conn->free_node, &config->connector_free_list);
685 schedule_work(&config->connector_free_work);
686}
687
688
689
690
691
692
693
694
695struct drm_connector *
696drm_connector_list_iter_next(struct drm_connector_list_iter *iter)
697{
698 struct drm_connector *old_conn = iter->conn;
699 struct drm_mode_config *config = &iter->dev->mode_config;
700 struct list_head *lhead;
701 unsigned long flags;
702
703 spin_lock_irqsave(&config->connector_list_lock, flags);
704 lhead = old_conn ? &old_conn->head : &config->connector_list;
705
706 do {
707 if (lhead->next == &config->connector_list) {
708 iter->conn = NULL;
709 break;
710 }
711
712 lhead = lhead->next;
713 iter->conn = list_entry(lhead, struct drm_connector, head);
714
715
716 } while (!kref_get_unless_zero(&iter->conn->base.refcount));
717
718 if (old_conn)
719 __drm_connector_put_safe(old_conn);
720 spin_unlock_irqrestore(&config->connector_list_lock, flags);
721
722 return iter->conn;
723}
724EXPORT_SYMBOL(drm_connector_list_iter_next);
725
726
727
728
729
730
731
732
733
734
735void drm_connector_list_iter_end(struct drm_connector_list_iter *iter)
736{
737 struct drm_mode_config *config = &iter->dev->mode_config;
738 unsigned long flags;
739
740 iter->dev = NULL;
741 if (iter->conn) {
742 spin_lock_irqsave(&config->connector_list_lock, flags);
743 __drm_connector_put_safe(iter->conn);
744 spin_unlock_irqrestore(&config->connector_list_lock, flags);
745 }
746 lock_release(&connector_list_iter_dep_map, _RET_IP_);
747}
748EXPORT_SYMBOL(drm_connector_list_iter_end);
749
750static const struct drm_prop_enum_list drm_subpixel_enum_list[] = {
751 { SubPixelUnknown, "Unknown" },
752 { SubPixelHorizontalRGB, "Horizontal RGB" },
753 { SubPixelHorizontalBGR, "Horizontal BGR" },
754 { SubPixelVerticalRGB, "Vertical RGB" },
755 { SubPixelVerticalBGR, "Vertical BGR" },
756 { SubPixelNone, "None" },
757};
758
759
760
761
762
763
764
765
766const char *drm_get_subpixel_order_name(enum subpixel_order order)
767{
768 return drm_subpixel_enum_list[order].name;
769}
770EXPORT_SYMBOL(drm_get_subpixel_order_name);
771
772static const struct drm_prop_enum_list drm_dpms_enum_list[] = {
773 { DRM_MODE_DPMS_ON, "On" },
774 { DRM_MODE_DPMS_STANDBY, "Standby" },
775 { DRM_MODE_DPMS_SUSPEND, "Suspend" },
776 { DRM_MODE_DPMS_OFF, "Off" }
777};
778DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
779
780static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
781 { DRM_MODE_LINK_STATUS_GOOD, "Good" },
782 { DRM_MODE_LINK_STATUS_BAD, "Bad" },
783};
784
785
786
787
788
789
790
791
792
793
794
795int drm_display_info_set_bus_formats(struct drm_display_info *info,
796 const u32 *formats,
797 unsigned int num_formats)
798{
799 u32 *fmts = NULL;
800
801 if (!formats && num_formats)
802 return -EINVAL;
803
804 if (formats && num_formats) {
805 fmts = kmemdup(formats, sizeof(*formats) * num_formats,
806 GFP_KERNEL);
807 if (!fmts)
808 return -ENOMEM;
809 }
810
811 kfree(info->bus_formats);
812 info->bus_formats = fmts;
813 info->num_bus_formats = num_formats;
814
815 return 0;
816}
817EXPORT_SYMBOL(drm_display_info_set_bus_formats);
818
819
820static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = {
821 { DRM_MODE_SCALE_NONE, "None" },
822 { DRM_MODE_SCALE_FULLSCREEN, "Full" },
823 { DRM_MODE_SCALE_CENTER, "Center" },
824 { DRM_MODE_SCALE_ASPECT, "Full aspect" },
825};
826
827static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = {
828 { DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" },
829 { DRM_MODE_PICTURE_ASPECT_4_3, "4:3" },
830 { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" },
831};
832
833static const struct drm_prop_enum_list drm_content_type_enum_list[] = {
834 { DRM_MODE_CONTENT_TYPE_NO_DATA, "No Data" },
835 { DRM_MODE_CONTENT_TYPE_GRAPHICS, "Graphics" },
836 { DRM_MODE_CONTENT_TYPE_PHOTO, "Photo" },
837 { DRM_MODE_CONTENT_TYPE_CINEMA, "Cinema" },
838 { DRM_MODE_CONTENT_TYPE_GAME, "Game" },
839};
840
841static const struct drm_prop_enum_list drm_panel_orientation_enum_list[] = {
842 { DRM_MODE_PANEL_ORIENTATION_NORMAL, "Normal" },
843 { DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP, "Upside Down" },
844 { DRM_MODE_PANEL_ORIENTATION_LEFT_UP, "Left Side Up" },
845 { DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, "Right Side Up" },
846};
847
848static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = {
849 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" },
850 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" },
851 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" },
852};
853DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list)
854
855static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = {
856 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" },
857 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" },
858 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" },
859};
860DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
861 drm_dvi_i_subconnector_enum_list)
862
863static const struct drm_prop_enum_list drm_tv_select_enum_list[] = {
864 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" },
865 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" },
866 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" },
867 { DRM_MODE_SUBCONNECTOR_Component, "Component" },
868 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" },
869};
870DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
871
872static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = {
873 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" },
874 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" },
875 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" },
876 { DRM_MODE_SUBCONNECTOR_Component, "Component" },
877 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" },
878};
879DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
880 drm_tv_subconnector_enum_list)
881
882static const struct drm_prop_enum_list drm_dp_subconnector_enum_list[] = {
883 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" },
884 { DRM_MODE_SUBCONNECTOR_VGA, "VGA" },
885 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" },
886 { DRM_MODE_SUBCONNECTOR_HDMIA, "HDMI" },
887 { DRM_MODE_SUBCONNECTOR_DisplayPort, "DP" },
888 { DRM_MODE_SUBCONNECTOR_Wireless, "Wireless" },
889 { DRM_MODE_SUBCONNECTOR_Native, "Native" },
890};
891
892DRM_ENUM_NAME_FN(drm_get_dp_subconnector_name,
893 drm_dp_subconnector_enum_list)
894
895static const struct drm_prop_enum_list hdmi_colorspaces[] = {
896
897 { DRM_MODE_COLORIMETRY_DEFAULT, "Default" },
898
899 { DRM_MODE_COLORIMETRY_SMPTE_170M_YCC, "SMPTE_170M_YCC" },
900 { DRM_MODE_COLORIMETRY_BT709_YCC, "BT709_YCC" },
901
902 { DRM_MODE_COLORIMETRY_XVYCC_601, "XVYCC_601" },
903
904 { DRM_MODE_COLORIMETRY_XVYCC_709, "XVYCC_709" },
905
906 { DRM_MODE_COLORIMETRY_SYCC_601, "SYCC_601" },
907
908 { DRM_MODE_COLORIMETRY_OPYCC_601, "opYCC_601" },
909
910 { DRM_MODE_COLORIMETRY_OPRGB, "opRGB" },
911
912 { DRM_MODE_COLORIMETRY_BT2020_CYCC, "BT2020_CYCC" },
913
914 { DRM_MODE_COLORIMETRY_BT2020_RGB, "BT2020_RGB" },
915
916 { DRM_MODE_COLORIMETRY_BT2020_YCC, "BT2020_YCC" },
917
918 { DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65, "DCI-P3_RGB_D65" },
919 { DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER, "DCI-P3_RGB_Theater" },
920};
921
922
923
924
925
926static const struct drm_prop_enum_list dp_colorspaces[] = {
927
928 { DRM_MODE_COLORIMETRY_DEFAULT, "Default" },
929 { DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED, "RGB_Wide_Gamut_Fixed_Point" },
930
931 { DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT, "RGB_Wide_Gamut_Floating_Point" },
932
933 { DRM_MODE_COLORIMETRY_OPRGB, "opRGB" },
934
935 { DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65, "DCI-P3_RGB_D65" },
936
937 { DRM_MODE_COLORIMETRY_BT2020_RGB, "BT2020_RGB" },
938 { DRM_MODE_COLORIMETRY_BT601_YCC, "BT601_YCC" },
939 { DRM_MODE_COLORIMETRY_BT709_YCC, "BT709_YCC" },
940
941 { DRM_MODE_COLORIMETRY_XVYCC_601, "XVYCC_601" },
942
943 { DRM_MODE_COLORIMETRY_XVYCC_709, "XVYCC_709" },
944
945 { DRM_MODE_COLORIMETRY_SYCC_601, "SYCC_601" },
946
947 { DRM_MODE_COLORIMETRY_OPYCC_601, "opYCC_601" },
948
949 { DRM_MODE_COLORIMETRY_BT2020_CYCC, "BT2020_CYCC" },
950
951 { DRM_MODE_COLORIMETRY_BT2020_YCC, "BT2020_YCC" },
952};
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251int drm_connector_create_standard_properties(struct drm_device *dev)
1252{
1253 struct drm_property *prop;
1254
1255 prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
1256 DRM_MODE_PROP_IMMUTABLE,
1257 "EDID", 0);
1258 if (!prop)
1259 return -ENOMEM;
1260 dev->mode_config.edid_property = prop;
1261
1262 prop = drm_property_create_enum(dev, 0,
1263 "DPMS", drm_dpms_enum_list,
1264 ARRAY_SIZE(drm_dpms_enum_list));
1265 if (!prop)
1266 return -ENOMEM;
1267 dev->mode_config.dpms_property = prop;
1268
1269 prop = drm_property_create(dev,
1270 DRM_MODE_PROP_BLOB |
1271 DRM_MODE_PROP_IMMUTABLE,
1272 "PATH", 0);
1273 if (!prop)
1274 return -ENOMEM;
1275 dev->mode_config.path_property = prop;
1276
1277 prop = drm_property_create(dev,
1278 DRM_MODE_PROP_BLOB |
1279 DRM_MODE_PROP_IMMUTABLE,
1280 "TILE", 0);
1281 if (!prop)
1282 return -ENOMEM;
1283 dev->mode_config.tile_property = prop;
1284
1285 prop = drm_property_create_enum(dev, 0, "link-status",
1286 drm_link_status_enum_list,
1287 ARRAY_SIZE(drm_link_status_enum_list));
1288 if (!prop)
1289 return -ENOMEM;
1290 dev->mode_config.link_status_property = prop;
1291
1292 prop = drm_property_create_bool(dev, DRM_MODE_PROP_IMMUTABLE, "non-desktop");
1293 if (!prop)
1294 return -ENOMEM;
1295 dev->mode_config.non_desktop_property = prop;
1296
1297 prop = drm_property_create(dev, DRM_MODE_PROP_BLOB,
1298 "HDR_OUTPUT_METADATA", 0);
1299 if (!prop)
1300 return -ENOMEM;
1301 dev->mode_config.hdr_output_metadata_property = prop;
1302
1303 return 0;
1304}
1305
1306
1307
1308
1309
1310
1311
1312int drm_mode_create_dvi_i_properties(struct drm_device *dev)
1313{
1314 struct drm_property *dvi_i_selector;
1315 struct drm_property *dvi_i_subconnector;
1316
1317 if (dev->mode_config.dvi_i_select_subconnector_property)
1318 return 0;
1319
1320 dvi_i_selector =
1321 drm_property_create_enum(dev, 0,
1322 "select subconnector",
1323 drm_dvi_i_select_enum_list,
1324 ARRAY_SIZE(drm_dvi_i_select_enum_list));
1325 dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector;
1326
1327 dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1328 "subconnector",
1329 drm_dvi_i_subconnector_enum_list,
1330 ARRAY_SIZE(drm_dvi_i_subconnector_enum_list));
1331 dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector;
1332
1333 return 0;
1334}
1335EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
1336
1337
1338
1339
1340
1341
1342
1343void drm_connector_attach_dp_subconnector_property(struct drm_connector *connector)
1344{
1345 struct drm_mode_config *mode_config = &connector->dev->mode_config;
1346
1347 if (!mode_config->dp_subconnector_property)
1348 mode_config->dp_subconnector_property =
1349 drm_property_create_enum(connector->dev,
1350 DRM_MODE_PROP_IMMUTABLE,
1351 "subconnector",
1352 drm_dp_subconnector_enum_list,
1353 ARRAY_SIZE(drm_dp_subconnector_enum_list));
1354
1355 drm_object_attach_property(&connector->base,
1356 mode_config->dp_subconnector_property,
1357 DRM_MODE_SUBCONNECTOR_Unknown);
1358}
1359EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property);
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393int drm_connector_attach_content_type_property(struct drm_connector *connector)
1394{
1395 if (!drm_mode_create_content_type_property(connector->dev))
1396 drm_object_attach_property(&connector->base,
1397 connector->dev->mode_config.content_type_property,
1398 DRM_MODE_CONTENT_TYPE_NO_DATA);
1399 return 0;
1400}
1401EXPORT_SYMBOL(drm_connector_attach_content_type_property);
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame,
1413 const struct drm_connector_state *conn_state)
1414{
1415 switch (conn_state->content_type) {
1416 case DRM_MODE_CONTENT_TYPE_GRAPHICS:
1417 frame->content_type = HDMI_CONTENT_TYPE_GRAPHICS;
1418 break;
1419 case DRM_MODE_CONTENT_TYPE_CINEMA:
1420 frame->content_type = HDMI_CONTENT_TYPE_CINEMA;
1421 break;
1422 case DRM_MODE_CONTENT_TYPE_GAME:
1423 frame->content_type = HDMI_CONTENT_TYPE_GAME;
1424 break;
1425 case DRM_MODE_CONTENT_TYPE_PHOTO:
1426 frame->content_type = HDMI_CONTENT_TYPE_PHOTO;
1427 break;
1428 default:
1429
1430 frame->content_type = HDMI_CONTENT_TYPE_GRAPHICS;
1431 }
1432
1433 frame->itc = conn_state->content_type != DRM_MODE_CONTENT_TYPE_NO_DATA;
1434}
1435EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445void drm_connector_attach_tv_margin_properties(struct drm_connector *connector)
1446{
1447 struct drm_device *dev = connector->dev;
1448
1449 drm_object_attach_property(&connector->base,
1450 dev->mode_config.tv_left_margin_property,
1451 0);
1452 drm_object_attach_property(&connector->base,
1453 dev->mode_config.tv_right_margin_property,
1454 0);
1455 drm_object_attach_property(&connector->base,
1456 dev->mode_config.tv_top_margin_property,
1457 0);
1458 drm_object_attach_property(&connector->base,
1459 dev->mode_config.tv_bottom_margin_property,
1460 0);
1461}
1462EXPORT_SYMBOL(drm_connector_attach_tv_margin_properties);
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473int drm_mode_create_tv_margin_properties(struct drm_device *dev)
1474{
1475 if (dev->mode_config.tv_left_margin_property)
1476 return 0;
1477
1478 dev->mode_config.tv_left_margin_property =
1479 drm_property_create_range(dev, 0, "left margin", 0, 100);
1480 if (!dev->mode_config.tv_left_margin_property)
1481 return -ENOMEM;
1482
1483 dev->mode_config.tv_right_margin_property =
1484 drm_property_create_range(dev, 0, "right margin", 0, 100);
1485 if (!dev->mode_config.tv_right_margin_property)
1486 return -ENOMEM;
1487
1488 dev->mode_config.tv_top_margin_property =
1489 drm_property_create_range(dev, 0, "top margin", 0, 100);
1490 if (!dev->mode_config.tv_top_margin_property)
1491 return -ENOMEM;
1492
1493 dev->mode_config.tv_bottom_margin_property =
1494 drm_property_create_range(dev, 0, "bottom margin", 0, 100);
1495 if (!dev->mode_config.tv_bottom_margin_property)
1496 return -ENOMEM;
1497
1498 return 0;
1499}
1500EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513int drm_mode_create_tv_properties(struct drm_device *dev,
1514 unsigned int num_modes,
1515 const char * const modes[])
1516{
1517 struct drm_property *tv_selector;
1518 struct drm_property *tv_subconnector;
1519 unsigned int i;
1520
1521 if (dev->mode_config.tv_select_subconnector_property)
1522 return 0;
1523
1524
1525
1526
1527 tv_selector = drm_property_create_enum(dev, 0,
1528 "select subconnector",
1529 drm_tv_select_enum_list,
1530 ARRAY_SIZE(drm_tv_select_enum_list));
1531 if (!tv_selector)
1532 goto nomem;
1533
1534 dev->mode_config.tv_select_subconnector_property = tv_selector;
1535
1536 tv_subconnector =
1537 drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1538 "subconnector",
1539 drm_tv_subconnector_enum_list,
1540 ARRAY_SIZE(drm_tv_subconnector_enum_list));
1541 if (!tv_subconnector)
1542 goto nomem;
1543 dev->mode_config.tv_subconnector_property = tv_subconnector;
1544
1545
1546
1547
1548 if (drm_mode_create_tv_margin_properties(dev))
1549 goto nomem;
1550
1551 dev->mode_config.tv_mode_property =
1552 drm_property_create(dev, DRM_MODE_PROP_ENUM,
1553 "mode", num_modes);
1554 if (!dev->mode_config.tv_mode_property)
1555 goto nomem;
1556
1557 for (i = 0; i < num_modes; i++)
1558 drm_property_add_enum(dev->mode_config.tv_mode_property,
1559 i, modes[i]);
1560
1561 dev->mode_config.tv_brightness_property =
1562 drm_property_create_range(dev, 0, "brightness", 0, 100);
1563 if (!dev->mode_config.tv_brightness_property)
1564 goto nomem;
1565
1566 dev->mode_config.tv_contrast_property =
1567 drm_property_create_range(dev, 0, "contrast", 0, 100);
1568 if (!dev->mode_config.tv_contrast_property)
1569 goto nomem;
1570
1571 dev->mode_config.tv_flicker_reduction_property =
1572 drm_property_create_range(dev, 0, "flicker reduction", 0, 100);
1573 if (!dev->mode_config.tv_flicker_reduction_property)
1574 goto nomem;
1575
1576 dev->mode_config.tv_overscan_property =
1577 drm_property_create_range(dev, 0, "overscan", 0, 100);
1578 if (!dev->mode_config.tv_overscan_property)
1579 goto nomem;
1580
1581 dev->mode_config.tv_saturation_property =
1582 drm_property_create_range(dev, 0, "saturation", 0, 100);
1583 if (!dev->mode_config.tv_saturation_property)
1584 goto nomem;
1585
1586 dev->mode_config.tv_hue_property =
1587 drm_property_create_range(dev, 0, "hue", 0, 100);
1588 if (!dev->mode_config.tv_hue_property)
1589 goto nomem;
1590
1591 return 0;
1592nomem:
1593 return -ENOMEM;
1594}
1595EXPORT_SYMBOL(drm_mode_create_tv_properties);
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608int drm_mode_create_scaling_mode_property(struct drm_device *dev)
1609{
1610 struct drm_property *scaling_mode;
1611
1612 if (dev->mode_config.scaling_mode_property)
1613 return 0;
1614
1615 scaling_mode =
1616 drm_property_create_enum(dev, 0, "scaling mode",
1617 drm_scaling_mode_enum_list,
1618 ARRAY_SIZE(drm_scaling_mode_enum_list));
1619
1620 dev->mode_config.scaling_mode_property = scaling_mode;
1621
1622 return 0;
1623}
1624EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699int drm_connector_attach_vrr_capable_property(
1700 struct drm_connector *connector)
1701{
1702 struct drm_device *dev = connector->dev;
1703 struct drm_property *prop;
1704
1705 if (!connector->vrr_capable_property) {
1706 prop = drm_property_create_bool(dev, DRM_MODE_PROP_IMMUTABLE,
1707 "vrr_capable");
1708 if (!prop)
1709 return -ENOMEM;
1710
1711 connector->vrr_capable_property = prop;
1712 drm_object_attach_property(&connector->base, prop, 0);
1713 }
1714
1715 return 0;
1716}
1717EXPORT_SYMBOL(drm_connector_attach_vrr_capable_property);
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
1734 u32 scaling_mode_mask)
1735{
1736 struct drm_device *dev = connector->dev;
1737 struct drm_property *scaling_mode_property;
1738 int i;
1739 const unsigned valid_scaling_mode_mask =
1740 (1U << ARRAY_SIZE(drm_scaling_mode_enum_list)) - 1;
1741
1742 if (WARN_ON(hweight32(scaling_mode_mask) < 2 ||
1743 scaling_mode_mask & ~valid_scaling_mode_mask))
1744 return -EINVAL;
1745
1746 scaling_mode_property =
1747 drm_property_create(dev, DRM_MODE_PROP_ENUM, "scaling mode",
1748 hweight32(scaling_mode_mask));
1749
1750 if (!scaling_mode_property)
1751 return -ENOMEM;
1752
1753 for (i = 0; i < ARRAY_SIZE(drm_scaling_mode_enum_list); i++) {
1754 int ret;
1755
1756 if (!(BIT(i) & scaling_mode_mask))
1757 continue;
1758
1759 ret = drm_property_add_enum(scaling_mode_property,
1760 drm_scaling_mode_enum_list[i].type,
1761 drm_scaling_mode_enum_list[i].name);
1762
1763 if (ret) {
1764 drm_property_destroy(dev, scaling_mode_property);
1765
1766 return ret;
1767 }
1768 }
1769
1770 drm_object_attach_property(&connector->base,
1771 scaling_mode_property, 0);
1772
1773 connector->scaling_mode_property = scaling_mode_property;
1774
1775 return 0;
1776}
1777EXPORT_SYMBOL(drm_connector_attach_scaling_mode_property);
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789int drm_mode_create_aspect_ratio_property(struct drm_device *dev)
1790{
1791 if (dev->mode_config.aspect_ratio_property)
1792 return 0;
1793
1794 dev->mode_config.aspect_ratio_property =
1795 drm_property_create_enum(dev, 0, "aspect ratio",
1796 drm_aspect_ratio_enum_list,
1797 ARRAY_SIZE(drm_aspect_ratio_enum_list));
1798
1799 if (dev->mode_config.aspect_ratio_property == NULL)
1800 return -ENOMEM;
1801
1802 return 0;
1803}
1804EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector)
1845{
1846 struct drm_device *dev = connector->dev;
1847
1848 if (connector->colorspace_property)
1849 return 0;
1850
1851 connector->colorspace_property =
1852 drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "Colorspace",
1853 hdmi_colorspaces,
1854 ARRAY_SIZE(hdmi_colorspaces));
1855
1856 if (!connector->colorspace_property)
1857 return -ENOMEM;
1858
1859 return 0;
1860}
1861EXPORT_SYMBOL(drm_mode_create_hdmi_colorspace_property);
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873int drm_mode_create_dp_colorspace_property(struct drm_connector *connector)
1874{
1875 struct drm_device *dev = connector->dev;
1876
1877 if (connector->colorspace_property)
1878 return 0;
1879
1880 connector->colorspace_property =
1881 drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "Colorspace",
1882 dp_colorspaces,
1883 ARRAY_SIZE(dp_colorspaces));
1884
1885 if (!connector->colorspace_property)
1886 return -ENOMEM;
1887
1888 return 0;
1889}
1890EXPORT_SYMBOL(drm_mode_create_dp_colorspace_property);
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902int drm_mode_create_content_type_property(struct drm_device *dev)
1903{
1904 if (dev->mode_config.content_type_property)
1905 return 0;
1906
1907 dev->mode_config.content_type_property =
1908 drm_property_create_enum(dev, 0, "content type",
1909 drm_content_type_enum_list,
1910 ARRAY_SIZE(drm_content_type_enum_list));
1911
1912 if (dev->mode_config.content_type_property == NULL)
1913 return -ENOMEM;
1914
1915 return 0;
1916}
1917EXPORT_SYMBOL(drm_mode_create_content_type_property);
1918
1919
1920
1921
1922
1923
1924
1925int drm_mode_create_suggested_offset_properties(struct drm_device *dev)
1926{
1927 if (dev->mode_config.suggested_x_property && dev->mode_config.suggested_y_property)
1928 return 0;
1929
1930 dev->mode_config.suggested_x_property =
1931 drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested X", 0, 0xffffffff);
1932
1933 dev->mode_config.suggested_y_property =
1934 drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested Y", 0, 0xffffffff);
1935
1936 if (dev->mode_config.suggested_x_property == NULL ||
1937 dev->mode_config.suggested_y_property == NULL)
1938 return -ENOMEM;
1939 return 0;
1940}
1941EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties);
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956int drm_connector_set_path_property(struct drm_connector *connector,
1957 const char *path)
1958{
1959 struct drm_device *dev = connector->dev;
1960 int ret;
1961
1962 ret = drm_property_replace_global_blob(dev,
1963 &connector->path_blob_ptr,
1964 strlen(path) + 1,
1965 path,
1966 &connector->base,
1967 dev->mode_config.path_property);
1968 return ret;
1969}
1970EXPORT_SYMBOL(drm_connector_set_path_property);
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985int drm_connector_set_tile_property(struct drm_connector *connector)
1986{
1987 struct drm_device *dev = connector->dev;
1988 char tile[256];
1989 int ret;
1990
1991 if (!connector->has_tile) {
1992 ret = drm_property_replace_global_blob(dev,
1993 &connector->tile_blob_ptr,
1994 0,
1995 NULL,
1996 &connector->base,
1997 dev->mode_config.tile_property);
1998 return ret;
1999 }
2000
2001 snprintf(tile, 256, "%d:%d:%d:%d:%d:%d:%d:%d",
2002 connector->tile_group->id, connector->tile_is_single_monitor,
2003 connector->num_h_tile, connector->num_v_tile,
2004 connector->tile_h_loc, connector->tile_v_loc,
2005 connector->tile_h_size, connector->tile_v_size);
2006
2007 ret = drm_property_replace_global_blob(dev,
2008 &connector->tile_blob_ptr,
2009 strlen(tile) + 1,
2010 tile,
2011 &connector->base,
2012 dev->mode_config.tile_property);
2013 return ret;
2014}
2015EXPORT_SYMBOL(drm_connector_set_tile_property);
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031int drm_connector_update_edid_property(struct drm_connector *connector,
2032 const struct edid *edid)
2033{
2034 struct drm_device *dev = connector->dev;
2035 size_t size = 0;
2036 int ret;
2037 const struct edid *old_edid;
2038
2039
2040 if (connector->override_edid)
2041 return 0;
2042
2043 if (edid)
2044 size = EDID_LENGTH * (1 + edid->extensions);
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054 if (edid)
2055 drm_add_display_info(connector, edid);
2056 else
2057 drm_reset_display_info(connector);
2058
2059 drm_update_tile_info(connector, edid);
2060
2061 if (connector->edid_blob_ptr) {
2062 old_edid = (const struct edid *)connector->edid_blob_ptr->data;
2063 if (old_edid) {
2064 if (!drm_edid_are_equal(edid, old_edid)) {
2065 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Edid was changed.\n",
2066 connector->base.id, connector->name);
2067
2068 connector->epoch_counter += 1;
2069 DRM_DEBUG_KMS("Updating change counter to %llu\n",
2070 connector->epoch_counter);
2071 }
2072 }
2073 }
2074
2075 drm_object_property_set_value(&connector->base,
2076 dev->mode_config.non_desktop_property,
2077 connector->display_info.non_desktop);
2078
2079 ret = drm_property_replace_global_blob(dev,
2080 &connector->edid_blob_ptr,
2081 size,
2082 edid,
2083 &connector->base,
2084 dev->mode_config.edid_property);
2085 if (ret)
2086 return ret;
2087 return drm_connector_set_tile_property(connector);
2088}
2089EXPORT_SYMBOL(drm_connector_update_edid_property);
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110void drm_connector_set_link_status_property(struct drm_connector *connector,
2111 uint64_t link_status)
2112{
2113 struct drm_device *dev = connector->dev;
2114
2115 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
2116 connector->state->link_status = link_status;
2117 drm_modeset_unlock(&dev->mode_config.connection_mutex);
2118}
2119EXPORT_SYMBOL(drm_connector_set_link_status_property);
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132int drm_connector_attach_max_bpc_property(struct drm_connector *connector,
2133 int min, int max)
2134{
2135 struct drm_device *dev = connector->dev;
2136 struct drm_property *prop;
2137
2138 prop = connector->max_bpc_property;
2139 if (!prop) {
2140 prop = drm_property_create_range(dev, 0, "max bpc", min, max);
2141 if (!prop)
2142 return -ENOMEM;
2143
2144 connector->max_bpc_property = prop;
2145 }
2146
2147 drm_object_attach_property(&connector->base, prop, max);
2148 connector->state->max_requested_bpc = max;
2149 connector->state->max_bpc = max;
2150
2151 return 0;
2152}
2153EXPORT_SYMBOL(drm_connector_attach_max_bpc_property);
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165int drm_connector_attach_hdr_output_metadata_property(struct drm_connector *connector)
2166{
2167 struct drm_device *dev = connector->dev;
2168 struct drm_property *prop = dev->mode_config.hdr_output_metadata_property;
2169
2170 drm_object_attach_property(&connector->base, prop, 0);
2171
2172 return 0;
2173}
2174EXPORT_SYMBOL(drm_connector_attach_hdr_output_metadata_property);
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186int drm_connector_attach_colorspace_property(struct drm_connector *connector)
2187{
2188 struct drm_property *prop = connector->colorspace_property;
2189
2190 drm_object_attach_property(&connector->base, prop, DRM_MODE_COLORIMETRY_DEFAULT);
2191
2192 return 0;
2193}
2194EXPORT_SYMBOL(drm_connector_attach_colorspace_property);
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208bool drm_connector_atomic_hdr_metadata_equal(struct drm_connector_state *old_state,
2209 struct drm_connector_state *new_state)
2210{
2211 struct drm_property_blob *old_blob = old_state->hdr_output_metadata;
2212 struct drm_property_blob *new_blob = new_state->hdr_output_metadata;
2213
2214 if (!old_blob || !new_blob)
2215 return old_blob == new_blob;
2216
2217 if (old_blob->length != new_blob->length)
2218 return false;
2219
2220 return !memcmp(old_blob->data, new_blob->data, old_blob->length);
2221}
2222EXPORT_SYMBOL(drm_connector_atomic_hdr_metadata_equal);
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233void drm_connector_set_vrr_capable_property(
2234 struct drm_connector *connector, bool capable)
2235{
2236 drm_object_property_set_value(&connector->base,
2237 connector->vrr_capable_property,
2238 capable);
2239}
2240EXPORT_SYMBOL(drm_connector_set_vrr_capable_property);
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260int drm_connector_set_panel_orientation(
2261 struct drm_connector *connector,
2262 enum drm_panel_orientation panel_orientation)
2263{
2264 struct drm_device *dev = connector->dev;
2265 struct drm_display_info *info = &connector->display_info;
2266 struct drm_property *prop;
2267
2268
2269 if (info->panel_orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
2270 return 0;
2271
2272
2273 if (panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
2274 return 0;
2275
2276 info->panel_orientation = panel_orientation;
2277
2278 prop = dev->mode_config.panel_orientation_property;
2279 if (!prop) {
2280 prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
2281 "panel orientation",
2282 drm_panel_orientation_enum_list,
2283 ARRAY_SIZE(drm_panel_orientation_enum_list));
2284 if (!prop)
2285 return -ENOMEM;
2286
2287 dev->mode_config.panel_orientation_property = prop;
2288 }
2289
2290 drm_object_attach_property(&connector->base, prop,
2291 info->panel_orientation);
2292 return 0;
2293}
2294EXPORT_SYMBOL(drm_connector_set_panel_orientation);
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310int drm_connector_set_panel_orientation_with_quirk(
2311 struct drm_connector *connector,
2312 enum drm_panel_orientation panel_orientation,
2313 int width, int height)
2314{
2315 int orientation_quirk;
2316
2317 orientation_quirk = drm_get_panel_orientation_quirk(width, height);
2318 if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
2319 panel_orientation = orientation_quirk;
2320
2321 return drm_connector_set_panel_orientation(connector,
2322 panel_orientation);
2323}
2324EXPORT_SYMBOL(drm_connector_set_panel_orientation_with_quirk);
2325
2326int drm_connector_set_obj_prop(struct drm_mode_object *obj,
2327 struct drm_property *property,
2328 uint64_t value)
2329{
2330 int ret = -EINVAL;
2331 struct drm_connector *connector = obj_to_connector(obj);
2332
2333
2334 if (property == connector->dev->mode_config.dpms_property) {
2335 ret = (*connector->funcs->dpms)(connector, (int)value);
2336 } else if (connector->funcs->set_property)
2337 ret = connector->funcs->set_property(connector, property, value);
2338
2339 if (!ret)
2340 drm_object_property_set_value(&connector->base, property, value);
2341 return ret;
2342}
2343
2344int drm_connector_property_set_ioctl(struct drm_device *dev,
2345 void *data, struct drm_file *file_priv)
2346{
2347 struct drm_mode_connector_set_property *conn_set_prop = data;
2348 struct drm_mode_obj_set_property obj_set_prop = {
2349 .value = conn_set_prop->value,
2350 .prop_id = conn_set_prop->prop_id,
2351 .obj_id = conn_set_prop->connector_id,
2352 .obj_type = DRM_MODE_OBJECT_CONNECTOR
2353 };
2354
2355
2356 return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv);
2357}
2358
2359static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector)
2360{
2361
2362
2363
2364 if (connector->state)
2365 return connector->state->best_encoder;
2366 return connector->encoder;
2367}
2368
2369static bool
2370drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
2371 const struct list_head *modes,
2372 const struct drm_file *file_priv)
2373{
2374
2375
2376
2377
2378 if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode))
2379 return false;
2380
2381
2382
2383
2384
2385
2386 if (!file_priv->aspect_ratio_allowed) {
2387 const struct drm_display_mode *mode_itr;
2388
2389 list_for_each_entry(mode_itr, modes, head) {
2390 if (mode_itr->expose_to_userspace &&
2391 drm_mode_match(mode_itr, mode,
2392 DRM_MODE_MATCH_TIMINGS |
2393 DRM_MODE_MATCH_CLOCK |
2394 DRM_MODE_MATCH_FLAGS |
2395 DRM_MODE_MATCH_3D_FLAGS))
2396 return false;
2397 }
2398 }
2399
2400 return true;
2401}
2402
2403int drm_mode_getconnector(struct drm_device *dev, void *data,
2404 struct drm_file *file_priv)
2405{
2406 struct drm_mode_get_connector *out_resp = data;
2407 struct drm_connector *connector;
2408 struct drm_encoder *encoder;
2409 struct drm_display_mode *mode;
2410 int mode_count = 0;
2411 int encoders_count = 0;
2412 int ret = 0;
2413 int copied = 0;
2414 struct drm_mode_modeinfo u_mode;
2415 struct drm_mode_modeinfo __user *mode_ptr;
2416 uint32_t __user *encoder_ptr;
2417
2418 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2419 return -EOPNOTSUPP;
2420
2421 memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
2422
2423 connector = drm_connector_lookup(dev, file_priv, out_resp->connector_id);
2424 if (!connector)
2425 return -ENOENT;
2426
2427 encoders_count = hweight32(connector->possible_encoders);
2428
2429 if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
2430 copied = 0;
2431 encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
2432
2433 drm_connector_for_each_possible_encoder(connector, encoder) {
2434 if (put_user(encoder->base.id, encoder_ptr + copied)) {
2435 ret = -EFAULT;
2436 goto out;
2437 }
2438 copied++;
2439 }
2440 }
2441 out_resp->count_encoders = encoders_count;
2442
2443 out_resp->connector_id = connector->base.id;
2444 out_resp->connector_type = connector->connector_type;
2445 out_resp->connector_type_id = connector->connector_type_id;
2446
2447 mutex_lock(&dev->mode_config.mutex);
2448 if (out_resp->count_modes == 0) {
2449 if (drm_is_current_master(file_priv))
2450 connector->funcs->fill_modes(connector,
2451 dev->mode_config.max_width,
2452 dev->mode_config.max_height);
2453 else
2454 drm_dbg_kms(dev, "User-space requested a forced probe on [CONNECTOR:%d:%s] but is not the DRM master, demoting to read-only probe",
2455 connector->base.id, connector->name);
2456 }
2457
2458 out_resp->mm_width = connector->display_info.width_mm;
2459 out_resp->mm_height = connector->display_info.height_mm;
2460 out_resp->subpixel = connector->display_info.subpixel_order;
2461 out_resp->connection = connector->status;
2462
2463
2464 list_for_each_entry(mode, &connector->modes, head) {
2465 WARN_ON(mode->expose_to_userspace);
2466
2467 if (drm_mode_expose_to_userspace(mode, &connector->modes,
2468 file_priv)) {
2469 mode->expose_to_userspace = true;
2470 mode_count++;
2471 }
2472 }
2473
2474
2475
2476
2477
2478 if ((out_resp->count_modes >= mode_count) && mode_count) {
2479 copied = 0;
2480 mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
2481 list_for_each_entry(mode, &connector->modes, head) {
2482 if (!mode->expose_to_userspace)
2483 continue;
2484
2485
2486 mode->expose_to_userspace = false;
2487
2488 drm_mode_convert_to_umode(&u_mode, mode);
2489
2490
2491
2492
2493 if (!file_priv->aspect_ratio_allowed)
2494 u_mode.flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
2495 if (copy_to_user(mode_ptr + copied,
2496 &u_mode, sizeof(u_mode))) {
2497 ret = -EFAULT;
2498
2499
2500
2501
2502
2503 list_for_each_entry_continue(mode, &connector->modes, head)
2504 mode->expose_to_userspace = false;
2505
2506 mutex_unlock(&dev->mode_config.mutex);
2507
2508 goto out;
2509 }
2510 copied++;
2511 }
2512 } else {
2513
2514 list_for_each_entry(mode, &connector->modes, head)
2515 mode->expose_to_userspace = false;
2516 }
2517
2518 out_resp->count_modes = mode_count;
2519 mutex_unlock(&dev->mode_config.mutex);
2520
2521 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
2522 encoder = drm_connector_get_encoder(connector);
2523 if (encoder)
2524 out_resp->encoder_id = encoder->base.id;
2525 else
2526 out_resp->encoder_id = 0;
2527
2528
2529
2530
2531 ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
2532 (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
2533 (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
2534 &out_resp->count_props);
2535 drm_modeset_unlock(&dev->mode_config.connection_mutex);
2536
2537out:
2538 drm_connector_put(connector);
2539
2540 return ret;
2541}
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556static void drm_tile_group_free(struct kref *kref)
2557{
2558 struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
2559 struct drm_device *dev = tg->dev;
2560
2561 mutex_lock(&dev->mode_config.idr_mutex);
2562 idr_remove(&dev->mode_config.tile_idr, tg->id);
2563 mutex_unlock(&dev->mode_config.idr_mutex);
2564 kfree(tg);
2565}
2566
2567
2568
2569
2570
2571
2572
2573
2574void drm_mode_put_tile_group(struct drm_device *dev,
2575 struct drm_tile_group *tg)
2576{
2577 kref_put(&tg->refcount, drm_tile_group_free);
2578}
2579EXPORT_SYMBOL(drm_mode_put_tile_group);
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
2592 const char topology[8])
2593{
2594 struct drm_tile_group *tg;
2595 int id;
2596
2597 mutex_lock(&dev->mode_config.idr_mutex);
2598 idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
2599 if (!memcmp(tg->group_data, topology, 8)) {
2600 if (!kref_get_unless_zero(&tg->refcount))
2601 tg = NULL;
2602 mutex_unlock(&dev->mode_config.idr_mutex);
2603 return tg;
2604 }
2605 }
2606 mutex_unlock(&dev->mode_config.idr_mutex);
2607 return NULL;
2608}
2609EXPORT_SYMBOL(drm_mode_get_tile_group);
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
2623 const char topology[8])
2624{
2625 struct drm_tile_group *tg;
2626 int ret;
2627
2628 tg = kzalloc(sizeof(*tg), GFP_KERNEL);
2629 if (!tg)
2630 return NULL;
2631
2632 kref_init(&tg->refcount);
2633 memcpy(tg->group_data, topology, 8);
2634 tg->dev = dev;
2635
2636 mutex_lock(&dev->mode_config.idr_mutex);
2637 ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL);
2638 if (ret >= 0) {
2639 tg->id = ret;
2640 } else {
2641 kfree(tg);
2642 tg = NULL;
2643 }
2644
2645 mutex_unlock(&dev->mode_config.idr_mutex);
2646 return tg;
2647}
2648EXPORT_SYMBOL(drm_mode_create_tile_group);
2649