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};
96
97void drm_connector_ida_init(void)
98{
99 int i;
100
101 for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
102 ida_init(&drm_connector_enum_list[i].ida);
103}
104
105void drm_connector_ida_destroy(void)
106{
107 int i;
108
109 for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
110 ida_destroy(&drm_connector_enum_list[i].ida);
111}
112
113
114
115
116
117
118
119
120
121
122
123static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
124{
125 struct drm_cmdline_mode *mode = &connector->cmdline_mode;
126 char *option = NULL;
127
128 if (fb_get_options(connector->name, &option))
129 return;
130
131 if (!drm_mode_parse_command_line_for_connector(option,
132 connector,
133 mode))
134 return;
135
136 if (mode->force) {
137 DRM_INFO("forcing %s connector %s\n", connector->name,
138 drm_get_connector_force_name(mode->force));
139 connector->force = mode->force;
140 }
141
142 DRM_DEBUG_KMS("cmdline mode for connector %s %s %dx%d@%dHz%s%s%s\n",
143 connector->name,
144 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
308void drm_connector_attach_edid_property(struct drm_connector *connector)
309{
310 struct drm_mode_config *config = &connector->dev->mode_config;
311
312 drm_object_attach_property(&connector->base,
313 config->edid_property,
314 0);
315}
316EXPORT_SYMBOL(drm_connector_attach_edid_property);
317
318
319
320
321
322
323
324
325
326
327
328
329
330int drm_connector_attach_encoder(struct drm_connector *connector,
331 struct drm_encoder *encoder)
332{
333 int i;
334
335
336
337
338
339
340
341
342
343
344
345
346 if (WARN_ON(connector->encoder))
347 return -EINVAL;
348
349 for (i = 0; i < ARRAY_SIZE(connector->encoder_ids); i++) {
350 if (connector->encoder_ids[i] == 0) {
351 connector->encoder_ids[i] = encoder->base.id;
352 return 0;
353 }
354 }
355 return -ENOMEM;
356}
357EXPORT_SYMBOL(drm_connector_attach_encoder);
358
359
360
361
362
363
364
365
366
367bool drm_connector_has_possible_encoder(struct drm_connector *connector,
368 struct drm_encoder *encoder)
369{
370 struct drm_encoder *enc;
371 int i;
372
373 drm_connector_for_each_possible_encoder(connector, enc, i) {
374 if (enc == encoder)
375 return true;
376 }
377
378 return false;
379}
380EXPORT_SYMBOL(drm_connector_has_possible_encoder);
381
382static void drm_mode_remove(struct drm_connector *connector,
383 struct drm_display_mode *mode)
384{
385 list_del(&mode->head);
386 drm_mode_destroy(connector->dev, mode);
387}
388
389
390
391
392
393
394
395void drm_connector_cleanup(struct drm_connector *connector)
396{
397 struct drm_device *dev = connector->dev;
398 struct drm_display_mode *mode, *t;
399
400
401
402
403 if (WARN_ON(connector->registration_state ==
404 DRM_CONNECTOR_REGISTERED))
405 drm_connector_unregister(connector);
406
407 if (connector->tile_group) {
408 drm_mode_put_tile_group(dev, connector->tile_group);
409 connector->tile_group = NULL;
410 }
411
412 list_for_each_entry_safe(mode, t, &connector->probed_modes, head)
413 drm_mode_remove(connector, mode);
414
415 list_for_each_entry_safe(mode, t, &connector->modes, head)
416 drm_mode_remove(connector, mode);
417
418 ida_simple_remove(&drm_connector_enum_list[connector->connector_type].ida,
419 connector->connector_type_id);
420
421 ida_simple_remove(&dev->mode_config.connector_ida,
422 connector->index);
423
424 kfree(connector->display_info.bus_formats);
425 drm_mode_object_unregister(dev, &connector->base);
426 kfree(connector->name);
427 connector->name = NULL;
428 spin_lock_irq(&dev->mode_config.connector_list_lock);
429 list_del(&connector->head);
430 dev->mode_config.num_connector--;
431 spin_unlock_irq(&dev->mode_config.connector_list_lock);
432
433 WARN_ON(connector->state && !connector->funcs->atomic_destroy_state);
434 if (connector->state && connector->funcs->atomic_destroy_state)
435 connector->funcs->atomic_destroy_state(connector,
436 connector->state);
437
438 mutex_destroy(&connector->mutex);
439
440 memset(connector, 0, sizeof(*connector));
441}
442EXPORT_SYMBOL(drm_connector_cleanup);
443
444
445
446
447
448
449
450
451
452
453int drm_connector_register(struct drm_connector *connector)
454{
455 int ret = 0;
456
457 if (!connector->dev->registered)
458 return 0;
459
460 mutex_lock(&connector->mutex);
461 if (connector->registration_state != DRM_CONNECTOR_INITIALIZING)
462 goto unlock;
463
464 ret = drm_sysfs_connector_add(connector);
465 if (ret)
466 goto unlock;
467
468 drm_debugfs_connector_add(connector);
469
470 if (connector->funcs->late_register) {
471 ret = connector->funcs->late_register(connector);
472 if (ret)
473 goto err_debugfs;
474 }
475
476 drm_mode_object_register(connector->dev, &connector->base);
477
478 connector->registration_state = DRM_CONNECTOR_REGISTERED;
479 goto unlock;
480
481err_debugfs:
482 drm_debugfs_connector_remove(connector);
483 drm_sysfs_connector_remove(connector);
484unlock:
485 mutex_unlock(&connector->mutex);
486 return ret;
487}
488EXPORT_SYMBOL(drm_connector_register);
489
490
491
492
493
494
495
496void drm_connector_unregister(struct drm_connector *connector)
497{
498 mutex_lock(&connector->mutex);
499 if (connector->registration_state != DRM_CONNECTOR_REGISTERED) {
500 mutex_unlock(&connector->mutex);
501 return;
502 }
503
504 if (connector->funcs->early_unregister)
505 connector->funcs->early_unregister(connector);
506
507 drm_sysfs_connector_remove(connector);
508 drm_debugfs_connector_remove(connector);
509
510 connector->registration_state = DRM_CONNECTOR_UNREGISTERED;
511 mutex_unlock(&connector->mutex);
512}
513EXPORT_SYMBOL(drm_connector_unregister);
514
515void drm_connector_unregister_all(struct drm_device *dev)
516{
517 struct drm_connector *connector;
518 struct drm_connector_list_iter conn_iter;
519
520 drm_connector_list_iter_begin(dev, &conn_iter);
521 drm_for_each_connector_iter(connector, &conn_iter)
522 drm_connector_unregister(connector);
523 drm_connector_list_iter_end(&conn_iter);
524}
525
526int drm_connector_register_all(struct drm_device *dev)
527{
528 struct drm_connector *connector;
529 struct drm_connector_list_iter conn_iter;
530 int ret = 0;
531
532 drm_connector_list_iter_begin(dev, &conn_iter);
533 drm_for_each_connector_iter(connector, &conn_iter) {
534 ret = drm_connector_register(connector);
535 if (ret)
536 break;
537 }
538 drm_connector_list_iter_end(&conn_iter);
539
540 if (ret)
541 drm_connector_unregister_all(dev);
542 return ret;
543}
544
545
546
547
548
549
550
551
552const char *drm_get_connector_status_name(enum drm_connector_status status)
553{
554 if (status == connector_status_connected)
555 return "connected";
556 else if (status == connector_status_disconnected)
557 return "disconnected";
558 else
559 return "unknown";
560}
561EXPORT_SYMBOL(drm_get_connector_status_name);
562
563
564
565
566
567
568
569const char *drm_get_connector_force_name(enum drm_connector_force force)
570{
571 switch (force) {
572 case DRM_FORCE_UNSPECIFIED:
573 return "unspecified";
574 case DRM_FORCE_OFF:
575 return "off";
576 case DRM_FORCE_ON:
577 return "on";
578 case DRM_FORCE_ON_DIGITAL:
579 return "digital";
580 default:
581 return "unknown";
582 }
583}
584
585#ifdef CONFIG_LOCKDEP
586static struct lockdep_map connector_list_iter_dep_map = {
587 .name = "drm_connector_list_iter"
588};
589#endif
590
591
592
593
594
595
596
597
598
599
600
601void drm_connector_list_iter_begin(struct drm_device *dev,
602 struct drm_connector_list_iter *iter)
603{
604 iter->dev = dev;
605 iter->conn = NULL;
606 lock_acquire_shared_recursive(&connector_list_iter_dep_map, 0, 1, NULL, _RET_IP_);
607}
608EXPORT_SYMBOL(drm_connector_list_iter_begin);
609
610
611
612
613
614
615static void
616__drm_connector_put_safe(struct drm_connector *conn)
617{
618 struct drm_mode_config *config = &conn->dev->mode_config;
619
620 lockdep_assert_held(&config->connector_list_lock);
621
622 if (!refcount_dec_and_test(&conn->base.refcount.refcount))
623 return;
624
625 llist_add(&conn->free_node, &config->connector_free_list);
626 schedule_work(&config->connector_free_work);
627}
628
629
630
631
632
633
634
635
636struct drm_connector *
637drm_connector_list_iter_next(struct drm_connector_list_iter *iter)
638{
639 struct drm_connector *old_conn = iter->conn;
640 struct drm_mode_config *config = &iter->dev->mode_config;
641 struct list_head *lhead;
642 unsigned long flags;
643
644 spin_lock_irqsave(&config->connector_list_lock, flags);
645 lhead = old_conn ? &old_conn->head : &config->connector_list;
646
647 do {
648 if (lhead->next == &config->connector_list) {
649 iter->conn = NULL;
650 break;
651 }
652
653 lhead = lhead->next;
654 iter->conn = list_entry(lhead, struct drm_connector, head);
655
656
657 } while (!kref_get_unless_zero(&iter->conn->base.refcount));
658
659 if (old_conn)
660 __drm_connector_put_safe(old_conn);
661 spin_unlock_irqrestore(&config->connector_list_lock, flags);
662
663 return iter->conn;
664}
665EXPORT_SYMBOL(drm_connector_list_iter_next);
666
667
668
669
670
671
672
673
674
675
676void drm_connector_list_iter_end(struct drm_connector_list_iter *iter)
677{
678 struct drm_mode_config *config = &iter->dev->mode_config;
679 unsigned long flags;
680
681 iter->dev = NULL;
682 if (iter->conn) {
683 spin_lock_irqsave(&config->connector_list_lock, flags);
684 __drm_connector_put_safe(iter->conn);
685 spin_unlock_irqrestore(&config->connector_list_lock, flags);
686 }
687 lock_release(&connector_list_iter_dep_map, 0, _RET_IP_);
688}
689EXPORT_SYMBOL(drm_connector_list_iter_end);
690
691static const struct drm_prop_enum_list drm_subpixel_enum_list[] = {
692 { SubPixelUnknown, "Unknown" },
693 { SubPixelHorizontalRGB, "Horizontal RGB" },
694 { SubPixelHorizontalBGR, "Horizontal BGR" },
695 { SubPixelVerticalRGB, "Vertical RGB" },
696 { SubPixelVerticalBGR, "Vertical BGR" },
697 { SubPixelNone, "None" },
698};
699
700
701
702
703
704
705
706
707const char *drm_get_subpixel_order_name(enum subpixel_order order)
708{
709 return drm_subpixel_enum_list[order].name;
710}
711EXPORT_SYMBOL(drm_get_subpixel_order_name);
712
713static const struct drm_prop_enum_list drm_dpms_enum_list[] = {
714 { DRM_MODE_DPMS_ON, "On" },
715 { DRM_MODE_DPMS_STANDBY, "Standby" },
716 { DRM_MODE_DPMS_SUSPEND, "Suspend" },
717 { DRM_MODE_DPMS_OFF, "Off" }
718};
719DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
720
721static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
722 { DRM_MODE_LINK_STATUS_GOOD, "Good" },
723 { DRM_MODE_LINK_STATUS_BAD, "Bad" },
724};
725
726
727
728
729
730
731
732
733
734
735
736int drm_display_info_set_bus_formats(struct drm_display_info *info,
737 const u32 *formats,
738 unsigned int num_formats)
739{
740 u32 *fmts = NULL;
741
742 if (!formats && num_formats)
743 return -EINVAL;
744
745 if (formats && num_formats) {
746 fmts = kmemdup(formats, sizeof(*formats) * num_formats,
747 GFP_KERNEL);
748 if (!fmts)
749 return -ENOMEM;
750 }
751
752 kfree(info->bus_formats);
753 info->bus_formats = fmts;
754 info->num_bus_formats = num_formats;
755
756 return 0;
757}
758EXPORT_SYMBOL(drm_display_info_set_bus_formats);
759
760
761static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = {
762 { DRM_MODE_SCALE_NONE, "None" },
763 { DRM_MODE_SCALE_FULLSCREEN, "Full" },
764 { DRM_MODE_SCALE_CENTER, "Center" },
765 { DRM_MODE_SCALE_ASPECT, "Full aspect" },
766};
767
768static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = {
769 { DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" },
770 { DRM_MODE_PICTURE_ASPECT_4_3, "4:3" },
771 { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" },
772};
773
774static const struct drm_prop_enum_list drm_content_type_enum_list[] = {
775 { DRM_MODE_CONTENT_TYPE_NO_DATA, "No Data" },
776 { DRM_MODE_CONTENT_TYPE_GRAPHICS, "Graphics" },
777 { DRM_MODE_CONTENT_TYPE_PHOTO, "Photo" },
778 { DRM_MODE_CONTENT_TYPE_CINEMA, "Cinema" },
779 { DRM_MODE_CONTENT_TYPE_GAME, "Game" },
780};
781
782static const struct drm_prop_enum_list drm_panel_orientation_enum_list[] = {
783 { DRM_MODE_PANEL_ORIENTATION_NORMAL, "Normal" },
784 { DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP, "Upside Down" },
785 { DRM_MODE_PANEL_ORIENTATION_LEFT_UP, "Left Side Up" },
786 { DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, "Right Side Up" },
787};
788
789static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = {
790 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" },
791 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" },
792 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" },
793};
794DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list)
795
796static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = {
797 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" },
798 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" },
799 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" },
800};
801DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
802 drm_dvi_i_subconnector_enum_list)
803
804static const struct drm_prop_enum_list drm_tv_select_enum_list[] = {
805 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" },
806 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" },
807 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" },
808 { DRM_MODE_SUBCONNECTOR_Component, "Component" },
809 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" },
810};
811DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
812
813static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = {
814 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" },
815 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" },
816 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" },
817 { DRM_MODE_SUBCONNECTOR_Component, "Component" },
818 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" },
819};
820DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
821 drm_tv_subconnector_enum_list)
822
823static const struct drm_prop_enum_list hdmi_colorspaces[] = {
824
825 { DRM_MODE_COLORIMETRY_DEFAULT, "Default" },
826
827 { DRM_MODE_COLORIMETRY_SMPTE_170M_YCC, "SMPTE_170M_YCC" },
828 { DRM_MODE_COLORIMETRY_BT709_YCC, "BT709_YCC" },
829
830 { DRM_MODE_COLORIMETRY_XVYCC_601, "XVYCC_601" },
831
832 { DRM_MODE_COLORIMETRY_XVYCC_709, "XVYCC_709" },
833
834 { DRM_MODE_COLORIMETRY_SYCC_601, "SYCC_601" },
835
836 { DRM_MODE_COLORIMETRY_OPYCC_601, "opYCC_601" },
837
838 { DRM_MODE_COLORIMETRY_OPRGB, "opRGB" },
839
840 { DRM_MODE_COLORIMETRY_BT2020_CYCC, "BT2020_CYCC" },
841
842 { DRM_MODE_COLORIMETRY_BT2020_RGB, "BT2020_RGB" },
843
844 { DRM_MODE_COLORIMETRY_BT2020_YCC, "BT2020_YCC" },
845
846 { DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65, "DCI-P3_RGB_D65" },
847 { DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER, "DCI-P3_RGB_Theater" },
848};
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
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
1046int drm_connector_create_standard_properties(struct drm_device *dev)
1047{
1048 struct drm_property *prop;
1049
1050 prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
1051 DRM_MODE_PROP_IMMUTABLE,
1052 "EDID", 0);
1053 if (!prop)
1054 return -ENOMEM;
1055 dev->mode_config.edid_property = prop;
1056
1057 prop = drm_property_create_enum(dev, 0,
1058 "DPMS", drm_dpms_enum_list,
1059 ARRAY_SIZE(drm_dpms_enum_list));
1060 if (!prop)
1061 return -ENOMEM;
1062 dev->mode_config.dpms_property = prop;
1063
1064 prop = drm_property_create(dev,
1065 DRM_MODE_PROP_BLOB |
1066 DRM_MODE_PROP_IMMUTABLE,
1067 "PATH", 0);
1068 if (!prop)
1069 return -ENOMEM;
1070 dev->mode_config.path_property = prop;
1071
1072 prop = drm_property_create(dev,
1073 DRM_MODE_PROP_BLOB |
1074 DRM_MODE_PROP_IMMUTABLE,
1075 "TILE", 0);
1076 if (!prop)
1077 return -ENOMEM;
1078 dev->mode_config.tile_property = prop;
1079
1080 prop = drm_property_create_enum(dev, 0, "link-status",
1081 drm_link_status_enum_list,
1082 ARRAY_SIZE(drm_link_status_enum_list));
1083 if (!prop)
1084 return -ENOMEM;
1085 dev->mode_config.link_status_property = prop;
1086
1087 prop = drm_property_create_bool(dev, DRM_MODE_PROP_IMMUTABLE, "non-desktop");
1088 if (!prop)
1089 return -ENOMEM;
1090 dev->mode_config.non_desktop_property = prop;
1091
1092 prop = drm_property_create(dev, DRM_MODE_PROP_BLOB,
1093 "HDR_OUTPUT_METADATA", 0);
1094 if (!prop)
1095 return -ENOMEM;
1096 dev->mode_config.hdr_output_metadata_property = prop;
1097
1098 return 0;
1099}
1100
1101
1102
1103
1104
1105
1106
1107int drm_mode_create_dvi_i_properties(struct drm_device *dev)
1108{
1109 struct drm_property *dvi_i_selector;
1110 struct drm_property *dvi_i_subconnector;
1111
1112 if (dev->mode_config.dvi_i_select_subconnector_property)
1113 return 0;
1114
1115 dvi_i_selector =
1116 drm_property_create_enum(dev, 0,
1117 "select subconnector",
1118 drm_dvi_i_select_enum_list,
1119 ARRAY_SIZE(drm_dvi_i_select_enum_list));
1120 dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector;
1121
1122 dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1123 "subconnector",
1124 drm_dvi_i_subconnector_enum_list,
1125 ARRAY_SIZE(drm_dvi_i_subconnector_enum_list));
1126 dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector;
1127
1128 return 0;
1129}
1130EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
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
1164int drm_connector_attach_content_type_property(struct drm_connector *connector)
1165{
1166 if (!drm_mode_create_content_type_property(connector->dev))
1167 drm_object_attach_property(&connector->base,
1168 connector->dev->mode_config.content_type_property,
1169 DRM_MODE_CONTENT_TYPE_NO_DATA);
1170 return 0;
1171}
1172EXPORT_SYMBOL(drm_connector_attach_content_type_property);
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame,
1184 const struct drm_connector_state *conn_state)
1185{
1186 switch (conn_state->content_type) {
1187 case DRM_MODE_CONTENT_TYPE_GRAPHICS:
1188 frame->content_type = HDMI_CONTENT_TYPE_GRAPHICS;
1189 break;
1190 case DRM_MODE_CONTENT_TYPE_CINEMA:
1191 frame->content_type = HDMI_CONTENT_TYPE_CINEMA;
1192 break;
1193 case DRM_MODE_CONTENT_TYPE_GAME:
1194 frame->content_type = HDMI_CONTENT_TYPE_GAME;
1195 break;
1196 case DRM_MODE_CONTENT_TYPE_PHOTO:
1197 frame->content_type = HDMI_CONTENT_TYPE_PHOTO;
1198 break;
1199 default:
1200
1201 frame->content_type = HDMI_CONTENT_TYPE_GRAPHICS;
1202 }
1203
1204 frame->itc = conn_state->content_type != DRM_MODE_CONTENT_TYPE_NO_DATA;
1205}
1206EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
1207
1208
1209
1210
1211
1212
1213
1214
1215void drm_connector_attach_tv_margin_properties(struct drm_connector *connector)
1216{
1217 struct drm_device *dev = connector->dev;
1218
1219 drm_object_attach_property(&connector->base,
1220 dev->mode_config.tv_left_margin_property,
1221 0);
1222 drm_object_attach_property(&connector->base,
1223 dev->mode_config.tv_right_margin_property,
1224 0);
1225 drm_object_attach_property(&connector->base,
1226 dev->mode_config.tv_top_margin_property,
1227 0);
1228 drm_object_attach_property(&connector->base,
1229 dev->mode_config.tv_bottom_margin_property,
1230 0);
1231}
1232EXPORT_SYMBOL(drm_connector_attach_tv_margin_properties);
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243int drm_mode_create_tv_margin_properties(struct drm_device *dev)
1244{
1245 if (dev->mode_config.tv_left_margin_property)
1246 return 0;
1247
1248 dev->mode_config.tv_left_margin_property =
1249 drm_property_create_range(dev, 0, "left margin", 0, 100);
1250 if (!dev->mode_config.tv_left_margin_property)
1251 return -ENOMEM;
1252
1253 dev->mode_config.tv_right_margin_property =
1254 drm_property_create_range(dev, 0, "right margin", 0, 100);
1255 if (!dev->mode_config.tv_right_margin_property)
1256 return -ENOMEM;
1257
1258 dev->mode_config.tv_top_margin_property =
1259 drm_property_create_range(dev, 0, "top margin", 0, 100);
1260 if (!dev->mode_config.tv_top_margin_property)
1261 return -ENOMEM;
1262
1263 dev->mode_config.tv_bottom_margin_property =
1264 drm_property_create_range(dev, 0, "bottom margin", 0, 100);
1265 if (!dev->mode_config.tv_bottom_margin_property)
1266 return -ENOMEM;
1267
1268 return 0;
1269}
1270EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283int drm_mode_create_tv_properties(struct drm_device *dev,
1284 unsigned int num_modes,
1285 const char * const modes[])
1286{
1287 struct drm_property *tv_selector;
1288 struct drm_property *tv_subconnector;
1289 unsigned int i;
1290
1291 if (dev->mode_config.tv_select_subconnector_property)
1292 return 0;
1293
1294
1295
1296
1297 tv_selector = drm_property_create_enum(dev, 0,
1298 "select subconnector",
1299 drm_tv_select_enum_list,
1300 ARRAY_SIZE(drm_tv_select_enum_list));
1301 if (!tv_selector)
1302 goto nomem;
1303
1304 dev->mode_config.tv_select_subconnector_property = tv_selector;
1305
1306 tv_subconnector =
1307 drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1308 "subconnector",
1309 drm_tv_subconnector_enum_list,
1310 ARRAY_SIZE(drm_tv_subconnector_enum_list));
1311 if (!tv_subconnector)
1312 goto nomem;
1313 dev->mode_config.tv_subconnector_property = tv_subconnector;
1314
1315
1316
1317
1318 if (drm_mode_create_tv_margin_properties(dev))
1319 goto nomem;
1320
1321 dev->mode_config.tv_mode_property =
1322 drm_property_create(dev, DRM_MODE_PROP_ENUM,
1323 "mode", num_modes);
1324 if (!dev->mode_config.tv_mode_property)
1325 goto nomem;
1326
1327 for (i = 0; i < num_modes; i++)
1328 drm_property_add_enum(dev->mode_config.tv_mode_property,
1329 i, modes[i]);
1330
1331 dev->mode_config.tv_brightness_property =
1332 drm_property_create_range(dev, 0, "brightness", 0, 100);
1333 if (!dev->mode_config.tv_brightness_property)
1334 goto nomem;
1335
1336 dev->mode_config.tv_contrast_property =
1337 drm_property_create_range(dev, 0, "contrast", 0, 100);
1338 if (!dev->mode_config.tv_contrast_property)
1339 goto nomem;
1340
1341 dev->mode_config.tv_flicker_reduction_property =
1342 drm_property_create_range(dev, 0, "flicker reduction", 0, 100);
1343 if (!dev->mode_config.tv_flicker_reduction_property)
1344 goto nomem;
1345
1346 dev->mode_config.tv_overscan_property =
1347 drm_property_create_range(dev, 0, "overscan", 0, 100);
1348 if (!dev->mode_config.tv_overscan_property)
1349 goto nomem;
1350
1351 dev->mode_config.tv_saturation_property =
1352 drm_property_create_range(dev, 0, "saturation", 0, 100);
1353 if (!dev->mode_config.tv_saturation_property)
1354 goto nomem;
1355
1356 dev->mode_config.tv_hue_property =
1357 drm_property_create_range(dev, 0, "hue", 0, 100);
1358 if (!dev->mode_config.tv_hue_property)
1359 goto nomem;
1360
1361 return 0;
1362nomem:
1363 return -ENOMEM;
1364}
1365EXPORT_SYMBOL(drm_mode_create_tv_properties);
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378int drm_mode_create_scaling_mode_property(struct drm_device *dev)
1379{
1380 struct drm_property *scaling_mode;
1381
1382 if (dev->mode_config.scaling_mode_property)
1383 return 0;
1384
1385 scaling_mode =
1386 drm_property_create_enum(dev, 0, "scaling mode",
1387 drm_scaling_mode_enum_list,
1388 ARRAY_SIZE(drm_scaling_mode_enum_list));
1389
1390 dev->mode_config.scaling_mode_property = scaling_mode;
1391
1392 return 0;
1393}
1394EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469int drm_connector_attach_vrr_capable_property(
1470 struct drm_connector *connector)
1471{
1472 struct drm_device *dev = connector->dev;
1473 struct drm_property *prop;
1474
1475 if (!connector->vrr_capable_property) {
1476 prop = drm_property_create_bool(dev, DRM_MODE_PROP_IMMUTABLE,
1477 "vrr_capable");
1478 if (!prop)
1479 return -ENOMEM;
1480
1481 connector->vrr_capable_property = prop;
1482 drm_object_attach_property(&connector->base, prop, 0);
1483 }
1484
1485 return 0;
1486}
1487EXPORT_SYMBOL(drm_connector_attach_vrr_capable_property);
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
1504 u32 scaling_mode_mask)
1505{
1506 struct drm_device *dev = connector->dev;
1507 struct drm_property *scaling_mode_property;
1508 int i;
1509 const unsigned valid_scaling_mode_mask =
1510 (1U << ARRAY_SIZE(drm_scaling_mode_enum_list)) - 1;
1511
1512 if (WARN_ON(hweight32(scaling_mode_mask) < 2 ||
1513 scaling_mode_mask & ~valid_scaling_mode_mask))
1514 return -EINVAL;
1515
1516 scaling_mode_property =
1517 drm_property_create(dev, DRM_MODE_PROP_ENUM, "scaling mode",
1518 hweight32(scaling_mode_mask));
1519
1520 if (!scaling_mode_property)
1521 return -ENOMEM;
1522
1523 for (i = 0; i < ARRAY_SIZE(drm_scaling_mode_enum_list); i++) {
1524 int ret;
1525
1526 if (!(BIT(i) & scaling_mode_mask))
1527 continue;
1528
1529 ret = drm_property_add_enum(scaling_mode_property,
1530 drm_scaling_mode_enum_list[i].type,
1531 drm_scaling_mode_enum_list[i].name);
1532
1533 if (ret) {
1534 drm_property_destroy(dev, scaling_mode_property);
1535
1536 return ret;
1537 }
1538 }
1539
1540 drm_object_attach_property(&connector->base,
1541 scaling_mode_property, 0);
1542
1543 connector->scaling_mode_property = scaling_mode_property;
1544
1545 return 0;
1546}
1547EXPORT_SYMBOL(drm_connector_attach_scaling_mode_property);
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559int drm_mode_create_aspect_ratio_property(struct drm_device *dev)
1560{
1561 if (dev->mode_config.aspect_ratio_property)
1562 return 0;
1563
1564 dev->mode_config.aspect_ratio_property =
1565 drm_property_create_enum(dev, 0, "aspect ratio",
1566 drm_aspect_ratio_enum_list,
1567 ARRAY_SIZE(drm_aspect_ratio_enum_list));
1568
1569 if (dev->mode_config.aspect_ratio_property == NULL)
1570 return -ENOMEM;
1571
1572 return 0;
1573}
1574EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603int drm_mode_create_colorspace_property(struct drm_connector *connector)
1604{
1605 struct drm_device *dev = connector->dev;
1606 struct drm_property *prop;
1607
1608 if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
1609 connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) {
1610 prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
1611 "Colorspace",
1612 hdmi_colorspaces,
1613 ARRAY_SIZE(hdmi_colorspaces));
1614 if (!prop)
1615 return -ENOMEM;
1616 } else {
1617 DRM_DEBUG_KMS("Colorspace property not supported\n");
1618 return 0;
1619 }
1620
1621 connector->colorspace_property = prop;
1622
1623 return 0;
1624}
1625EXPORT_SYMBOL(drm_mode_create_colorspace_property);
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637int drm_mode_create_content_type_property(struct drm_device *dev)
1638{
1639 if (dev->mode_config.content_type_property)
1640 return 0;
1641
1642 dev->mode_config.content_type_property =
1643 drm_property_create_enum(dev, 0, "content type",
1644 drm_content_type_enum_list,
1645 ARRAY_SIZE(drm_content_type_enum_list));
1646
1647 if (dev->mode_config.content_type_property == NULL)
1648 return -ENOMEM;
1649
1650 return 0;
1651}
1652EXPORT_SYMBOL(drm_mode_create_content_type_property);
1653
1654
1655
1656
1657
1658
1659
1660int drm_mode_create_suggested_offset_properties(struct drm_device *dev)
1661{
1662 if (dev->mode_config.suggested_x_property && dev->mode_config.suggested_y_property)
1663 return 0;
1664
1665 dev->mode_config.suggested_x_property =
1666 drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested X", 0, 0xffffffff);
1667
1668 dev->mode_config.suggested_y_property =
1669 drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested Y", 0, 0xffffffff);
1670
1671 if (dev->mode_config.suggested_x_property == NULL ||
1672 dev->mode_config.suggested_y_property == NULL)
1673 return -ENOMEM;
1674 return 0;
1675}
1676EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties);
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691int drm_connector_set_path_property(struct drm_connector *connector,
1692 const char *path)
1693{
1694 struct drm_device *dev = connector->dev;
1695 int ret;
1696
1697 ret = drm_property_replace_global_blob(dev,
1698 &connector->path_blob_ptr,
1699 strlen(path) + 1,
1700 path,
1701 &connector->base,
1702 dev->mode_config.path_property);
1703 return ret;
1704}
1705EXPORT_SYMBOL(drm_connector_set_path_property);
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720int drm_connector_set_tile_property(struct drm_connector *connector)
1721{
1722 struct drm_device *dev = connector->dev;
1723 char tile[256];
1724 int ret;
1725
1726 if (!connector->has_tile) {
1727 ret = drm_property_replace_global_blob(dev,
1728 &connector->tile_blob_ptr,
1729 0,
1730 NULL,
1731 &connector->base,
1732 dev->mode_config.tile_property);
1733 return ret;
1734 }
1735
1736 snprintf(tile, 256, "%d:%d:%d:%d:%d:%d:%d:%d",
1737 connector->tile_group->id, connector->tile_is_single_monitor,
1738 connector->num_h_tile, connector->num_v_tile,
1739 connector->tile_h_loc, connector->tile_v_loc,
1740 connector->tile_h_size, connector->tile_v_size);
1741
1742 ret = drm_property_replace_global_blob(dev,
1743 &connector->tile_blob_ptr,
1744 strlen(tile) + 1,
1745 tile,
1746 &connector->base,
1747 dev->mode_config.tile_property);
1748 return ret;
1749}
1750EXPORT_SYMBOL(drm_connector_set_tile_property);
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766int drm_connector_update_edid_property(struct drm_connector *connector,
1767 const struct edid *edid)
1768{
1769 struct drm_device *dev = connector->dev;
1770 size_t size = 0;
1771 int ret;
1772
1773
1774 if (connector->override_edid)
1775 return 0;
1776
1777 if (edid)
1778 size = EDID_LENGTH * (1 + edid->extensions);
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788 if (edid)
1789 drm_add_display_info(connector, edid);
1790 else
1791 drm_reset_display_info(connector);
1792
1793 drm_object_property_set_value(&connector->base,
1794 dev->mode_config.non_desktop_property,
1795 connector->display_info.non_desktop);
1796
1797 ret = drm_property_replace_global_blob(dev,
1798 &connector->edid_blob_ptr,
1799 size,
1800 edid,
1801 &connector->base,
1802 dev->mode_config.edid_property);
1803 if (ret)
1804 return ret;
1805 return drm_connector_set_tile_property(connector);
1806}
1807EXPORT_SYMBOL(drm_connector_update_edid_property);
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828void drm_connector_set_link_status_property(struct drm_connector *connector,
1829 uint64_t link_status)
1830{
1831 struct drm_device *dev = connector->dev;
1832
1833 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
1834 connector->state->link_status = link_status;
1835 drm_modeset_unlock(&dev->mode_config.connection_mutex);
1836}
1837EXPORT_SYMBOL(drm_connector_set_link_status_property);
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850int drm_connector_attach_max_bpc_property(struct drm_connector *connector,
1851 int min, int max)
1852{
1853 struct drm_device *dev = connector->dev;
1854 struct drm_property *prop;
1855
1856 prop = connector->max_bpc_property;
1857 if (!prop) {
1858 prop = drm_property_create_range(dev, 0, "max bpc", min, max);
1859 if (!prop)
1860 return -ENOMEM;
1861
1862 connector->max_bpc_property = prop;
1863 }
1864
1865 drm_object_attach_property(&connector->base, prop, max);
1866 connector->state->max_requested_bpc = max;
1867 connector->state->max_bpc = max;
1868
1869 return 0;
1870}
1871EXPORT_SYMBOL(drm_connector_attach_max_bpc_property);
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882void drm_connector_set_vrr_capable_property(
1883 struct drm_connector *connector, bool capable)
1884{
1885 drm_object_property_set_value(&connector->base,
1886 connector->vrr_capable_property,
1887 capable);
1888}
1889EXPORT_SYMBOL(drm_connector_set_vrr_capable_property);
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909int drm_connector_init_panel_orientation_property(
1910 struct drm_connector *connector, int width, int height)
1911{
1912 struct drm_device *dev = connector->dev;
1913 struct drm_display_info *info = &connector->display_info;
1914 struct drm_property *prop;
1915 int orientation_quirk;
1916
1917 orientation_quirk = drm_get_panel_orientation_quirk(width, height);
1918 if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
1919 info->panel_orientation = orientation_quirk;
1920
1921 if (info->panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
1922 return 0;
1923
1924 prop = dev->mode_config.panel_orientation_property;
1925 if (!prop) {
1926 prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1927 "panel orientation",
1928 drm_panel_orientation_enum_list,
1929 ARRAY_SIZE(drm_panel_orientation_enum_list));
1930 if (!prop)
1931 return -ENOMEM;
1932
1933 dev->mode_config.panel_orientation_property = prop;
1934 }
1935
1936 drm_object_attach_property(&connector->base, prop,
1937 info->panel_orientation);
1938 return 0;
1939}
1940EXPORT_SYMBOL(drm_connector_init_panel_orientation_property);
1941
1942int drm_connector_set_obj_prop(struct drm_mode_object *obj,
1943 struct drm_property *property,
1944 uint64_t value)
1945{
1946 int ret = -EINVAL;
1947 struct drm_connector *connector = obj_to_connector(obj);
1948
1949
1950 if (property == connector->dev->mode_config.dpms_property) {
1951 ret = (*connector->funcs->dpms)(connector, (int)value);
1952 } else if (connector->funcs->set_property)
1953 ret = connector->funcs->set_property(connector, property, value);
1954
1955 if (!ret)
1956 drm_object_property_set_value(&connector->base, property, value);
1957 return ret;
1958}
1959
1960int drm_connector_property_set_ioctl(struct drm_device *dev,
1961 void *data, struct drm_file *file_priv)
1962{
1963 struct drm_mode_connector_set_property *conn_set_prop = data;
1964 struct drm_mode_obj_set_property obj_set_prop = {
1965 .value = conn_set_prop->value,
1966 .prop_id = conn_set_prop->prop_id,
1967 .obj_id = conn_set_prop->connector_id,
1968 .obj_type = DRM_MODE_OBJECT_CONNECTOR
1969 };
1970
1971
1972 return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv);
1973}
1974
1975static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector)
1976{
1977
1978
1979 if (connector->state)
1980 return connector->state->best_encoder;
1981 return connector->encoder;
1982}
1983
1984static bool
1985drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
1986 const struct list_head *export_list,
1987 const struct drm_file *file_priv)
1988{
1989
1990
1991
1992
1993 if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode))
1994 return false;
1995
1996
1997
1998
1999
2000
2001 if (!file_priv->aspect_ratio_allowed) {
2002 struct drm_display_mode *mode_itr;
2003
2004 list_for_each_entry(mode_itr, export_list, export_head)
2005 if (drm_mode_match(mode_itr, mode,
2006 DRM_MODE_MATCH_TIMINGS |
2007 DRM_MODE_MATCH_CLOCK |
2008 DRM_MODE_MATCH_FLAGS |
2009 DRM_MODE_MATCH_3D_FLAGS))
2010 return false;
2011 }
2012
2013 return true;
2014}
2015
2016int drm_mode_getconnector(struct drm_device *dev, void *data,
2017 struct drm_file *file_priv)
2018{
2019 struct drm_mode_get_connector *out_resp = data;
2020 struct drm_connector *connector;
2021 struct drm_encoder *encoder;
2022 struct drm_display_mode *mode;
2023 int mode_count = 0;
2024 int encoders_count = 0;
2025 int ret = 0;
2026 int copied = 0;
2027 int i;
2028 struct drm_mode_modeinfo u_mode;
2029 struct drm_mode_modeinfo __user *mode_ptr;
2030 uint32_t __user *encoder_ptr;
2031 LIST_HEAD(export_list);
2032
2033 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2034 return -EOPNOTSUPP;
2035
2036 memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
2037
2038 connector = drm_connector_lookup(dev, file_priv, out_resp->connector_id);
2039 if (!connector)
2040 return -ENOENT;
2041
2042 drm_connector_for_each_possible_encoder(connector, encoder, i)
2043 encoders_count++;
2044
2045 if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
2046 copied = 0;
2047 encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
2048
2049 drm_connector_for_each_possible_encoder(connector, encoder, i) {
2050 if (put_user(encoder->base.id, encoder_ptr + copied)) {
2051 ret = -EFAULT;
2052 goto out;
2053 }
2054 copied++;
2055 }
2056 }
2057 out_resp->count_encoders = encoders_count;
2058
2059 out_resp->connector_id = connector->base.id;
2060 out_resp->connector_type = connector->connector_type;
2061 out_resp->connector_type_id = connector->connector_type_id;
2062
2063 mutex_lock(&dev->mode_config.mutex);
2064 if (out_resp->count_modes == 0) {
2065 connector->funcs->fill_modes(connector,
2066 dev->mode_config.max_width,
2067 dev->mode_config.max_height);
2068 }
2069
2070 out_resp->mm_width = connector->display_info.width_mm;
2071 out_resp->mm_height = connector->display_info.height_mm;
2072 out_resp->subpixel = connector->display_info.subpixel_order;
2073 out_resp->connection = connector->status;
2074
2075
2076 list_for_each_entry(mode, &connector->modes, head)
2077 if (drm_mode_expose_to_userspace(mode, &export_list,
2078 file_priv)) {
2079 list_add_tail(&mode->export_head, &export_list);
2080 mode_count++;
2081 }
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091 if ((out_resp->count_modes >= mode_count) && mode_count) {
2092 copied = 0;
2093 mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
2094 list_for_each_entry(mode, &export_list, export_head) {
2095 drm_mode_convert_to_umode(&u_mode, mode);
2096
2097
2098
2099
2100 if (!file_priv->aspect_ratio_allowed)
2101 u_mode.flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
2102 if (copy_to_user(mode_ptr + copied,
2103 &u_mode, sizeof(u_mode))) {
2104 ret = -EFAULT;
2105 mutex_unlock(&dev->mode_config.mutex);
2106
2107 goto out;
2108 }
2109 copied++;
2110 }
2111 }
2112 out_resp->count_modes = mode_count;
2113 mutex_unlock(&dev->mode_config.mutex);
2114
2115 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
2116 encoder = drm_connector_get_encoder(connector);
2117 if (encoder)
2118 out_resp->encoder_id = encoder->base.id;
2119 else
2120 out_resp->encoder_id = 0;
2121
2122
2123
2124 ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
2125 (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
2126 (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
2127 &out_resp->count_props);
2128 drm_modeset_unlock(&dev->mode_config.connection_mutex);
2129
2130out:
2131 drm_connector_put(connector);
2132
2133 return ret;
2134}
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149static void drm_tile_group_free(struct kref *kref)
2150{
2151 struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
2152 struct drm_device *dev = tg->dev;
2153 mutex_lock(&dev->mode_config.idr_mutex);
2154 idr_remove(&dev->mode_config.tile_idr, tg->id);
2155 mutex_unlock(&dev->mode_config.idr_mutex);
2156 kfree(tg);
2157}
2158
2159
2160
2161
2162
2163
2164
2165
2166void drm_mode_put_tile_group(struct drm_device *dev,
2167 struct drm_tile_group *tg)
2168{
2169 kref_put(&tg->refcount, drm_tile_group_free);
2170}
2171EXPORT_SYMBOL(drm_mode_put_tile_group);
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
2184 char topology[8])
2185{
2186 struct drm_tile_group *tg;
2187 int id;
2188 mutex_lock(&dev->mode_config.idr_mutex);
2189 idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
2190 if (!memcmp(tg->group_data, topology, 8)) {
2191 if (!kref_get_unless_zero(&tg->refcount))
2192 tg = NULL;
2193 mutex_unlock(&dev->mode_config.idr_mutex);
2194 return tg;
2195 }
2196 }
2197 mutex_unlock(&dev->mode_config.idr_mutex);
2198 return NULL;
2199}
2200EXPORT_SYMBOL(drm_mode_get_tile_group);
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
2214 char topology[8])
2215{
2216 struct drm_tile_group *tg;
2217 int ret;
2218
2219 tg = kzalloc(sizeof(*tg), GFP_KERNEL);
2220 if (!tg)
2221 return NULL;
2222
2223 kref_init(&tg->refcount);
2224 memcpy(tg->group_data, topology, 8);
2225 tg->dev = dev;
2226
2227 mutex_lock(&dev->mode_config.idr_mutex);
2228 ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL);
2229 if (ret >= 0) {
2230 tg->id = ret;
2231 } else {
2232 kfree(tg);
2233 tg = NULL;
2234 }
2235
2236 mutex_unlock(&dev->mode_config.idr_mutex);
2237 return tg;
2238}
2239EXPORT_SYMBOL(drm_mode_create_tile_group);
2240