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