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/drmP.h>
24#include <drm/drm_connector.h>
25#include <drm/drm_edid.h>
26#include <drm/drm_encoder.h>
27
28#include "drm_crtc_internal.h"
29#include "drm_internal.h"
30
31
32
33
34
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
61struct drm_conn_prop_enum_list {
62 int type;
63 const char *name;
64 struct ida ida;
65};
66
67
68
69
70static struct drm_conn_prop_enum_list drm_connector_enum_list[] = {
71 { DRM_MODE_CONNECTOR_Unknown, "Unknown" },
72 { DRM_MODE_CONNECTOR_VGA, "VGA" },
73 { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
74 { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
75 { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
76 { DRM_MODE_CONNECTOR_Composite, "Composite" },
77 { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" },
78 { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
79 { DRM_MODE_CONNECTOR_Component, "Component" },
80 { DRM_MODE_CONNECTOR_9PinDIN, "DIN" },
81 { DRM_MODE_CONNECTOR_DisplayPort, "DP" },
82 { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
83 { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
84 { DRM_MODE_CONNECTOR_TV, "TV" },
85 { DRM_MODE_CONNECTOR_eDP, "eDP" },
86 { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
87 { DRM_MODE_CONNECTOR_DSI, "DSI" },
88 { DRM_MODE_CONNECTOR_DPI, "DPI" },
89};
90
91void drm_connector_ida_init(void)
92{
93 int i;
94
95 for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
96 ida_init(&drm_connector_enum_list[i].ida);
97}
98
99void drm_connector_ida_destroy(void)
100{
101 int i;
102
103 for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
104 ida_destroy(&drm_connector_enum_list[i].ida);
105}
106
107
108
109
110
111
112
113
114
115
116
117static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
118{
119 struct drm_cmdline_mode *mode = &connector->cmdline_mode;
120 char *option = NULL;
121
122 if (fb_get_options(connector->name, &option))
123 return;
124
125 if (!drm_mode_parse_command_line_for_connector(option,
126 connector,
127 mode))
128 return;
129
130 if (mode->force) {
131 DRM_INFO("forcing %s connector %s\n", connector->name,
132 drm_get_connector_force_name(mode->force));
133 connector->force = mode->force;
134 }
135
136 DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
137 connector->name,
138 mode->xres, mode->yres,
139 mode->refresh_specified ? mode->refresh : 60,
140 mode->rb ? " reduced blanking" : "",
141 mode->margins ? " with margins" : "",
142 mode->interlace ? " interlaced" : "");
143}
144
145static void drm_connector_free(struct kref *kref)
146{
147 struct drm_connector *connector =
148 container_of(kref, struct drm_connector, base.refcount);
149 struct drm_device *dev = connector->dev;
150
151 drm_mode_object_unregister(dev, &connector->base);
152 connector->funcs->destroy(connector);
153}
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168int drm_connector_init(struct drm_device *dev,
169 struct drm_connector *connector,
170 const struct drm_connector_funcs *funcs,
171 int connector_type)
172{
173 struct drm_mode_config *config = &dev->mode_config;
174 int ret;
175 struct ida *connector_ida =
176 &drm_connector_enum_list[connector_type].ida;
177
178 ret = __drm_mode_object_add(dev, &connector->base,
179 DRM_MODE_OBJECT_CONNECTOR,
180 false, drm_connector_free);
181 if (ret)
182 return ret;
183
184 connector->base.properties = &connector->properties;
185 connector->dev = dev;
186 connector->funcs = funcs;
187
188 ret = ida_simple_get(&config->connector_ida, 0, 0, GFP_KERNEL);
189 if (ret < 0)
190 goto out_put;
191 connector->index = ret;
192 ret = 0;
193
194 connector->connector_type = connector_type;
195 connector->connector_type_id =
196 ida_simple_get(connector_ida, 1, 0, GFP_KERNEL);
197 if (connector->connector_type_id < 0) {
198 ret = connector->connector_type_id;
199 goto out_put_id;
200 }
201 connector->name =
202 kasprintf(GFP_KERNEL, "%s-%d",
203 drm_connector_enum_list[connector_type].name,
204 connector->connector_type_id);
205 if (!connector->name) {
206 ret = -ENOMEM;
207 goto out_put_type_id;
208 }
209
210 INIT_LIST_HEAD(&connector->probed_modes);
211 INIT_LIST_HEAD(&connector->modes);
212 mutex_init(&connector->mutex);
213 connector->edid_blob_ptr = NULL;
214 connector->status = connector_status_unknown;
215
216 drm_connector_get_cmdline_mode(connector);
217
218
219
220 spin_lock_irq(&config->connector_list_lock);
221 list_add_tail(&connector->head, &config->connector_list);
222 config->num_connector++;
223 spin_unlock_irq(&config->connector_list_lock);
224
225 if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
226 drm_object_attach_property(&connector->base,
227 config->edid_property,
228 0);
229
230 drm_object_attach_property(&connector->base,
231 config->dpms_property, 0);
232
233 drm_object_attach_property(&connector->base,
234 config->link_status_property,
235 0);
236
237 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
238 drm_object_attach_property(&connector->base, config->prop_crtc_id, 0);
239 }
240
241 connector->debugfs_entry = NULL;
242out_put_type_id:
243 if (ret)
244 ida_simple_remove(connector_ida, connector->connector_type_id);
245out_put_id:
246 if (ret)
247 ida_simple_remove(&config->connector_ida, connector->index);
248out_put:
249 if (ret)
250 drm_mode_object_unregister(dev, &connector->base);
251
252 return ret;
253}
254EXPORT_SYMBOL(drm_connector_init);
255
256
257
258
259
260
261
262
263
264
265
266
267
268int drm_mode_connector_attach_encoder(struct drm_connector *connector,
269 struct drm_encoder *encoder)
270{
271 int i;
272
273
274
275
276
277
278
279
280
281
282
283
284 if (WARN_ON(connector->encoder))
285 return -EINVAL;
286
287 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
288 if (connector->encoder_ids[i] == 0) {
289 connector->encoder_ids[i] = encoder->base.id;
290 return 0;
291 }
292 }
293 return -ENOMEM;
294}
295EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
296
297static void drm_mode_remove(struct drm_connector *connector,
298 struct drm_display_mode *mode)
299{
300 list_del(&mode->head);
301 drm_mode_destroy(connector->dev, mode);
302}
303
304
305
306
307
308
309
310void drm_connector_cleanup(struct drm_connector *connector)
311{
312 struct drm_device *dev = connector->dev;
313 struct drm_display_mode *mode, *t;
314
315
316
317
318 if (WARN_ON(connector->registered))
319 drm_connector_unregister(connector);
320
321 if (connector->tile_group) {
322 drm_mode_put_tile_group(dev, connector->tile_group);
323 connector->tile_group = NULL;
324 }
325
326 list_for_each_entry_safe(mode, t, &connector->probed_modes, head)
327 drm_mode_remove(connector, mode);
328
329 list_for_each_entry_safe(mode, t, &connector->modes, head)
330 drm_mode_remove(connector, mode);
331
332 ida_simple_remove(&drm_connector_enum_list[connector->connector_type].ida,
333 connector->connector_type_id);
334
335 ida_simple_remove(&dev->mode_config.connector_ida,
336 connector->index);
337
338 kfree(connector->display_info.bus_formats);
339 drm_mode_object_unregister(dev, &connector->base);
340 kfree(connector->name);
341 connector->name = NULL;
342 spin_lock_irq(&dev->mode_config.connector_list_lock);
343 list_del(&connector->head);
344 dev->mode_config.num_connector--;
345 spin_unlock_irq(&dev->mode_config.connector_list_lock);
346
347 WARN_ON(connector->state && !connector->funcs->atomic_destroy_state);
348 if (connector->state && connector->funcs->atomic_destroy_state)
349 connector->funcs->atomic_destroy_state(connector,
350 connector->state);
351
352 mutex_destroy(&connector->mutex);
353
354 memset(connector, 0, sizeof(*connector));
355}
356EXPORT_SYMBOL(drm_connector_cleanup);
357
358
359
360
361
362
363
364
365
366
367int drm_connector_register(struct drm_connector *connector)
368{
369 int ret = 0;
370
371 if (!connector->dev->registered)
372 return 0;
373
374 mutex_lock(&connector->mutex);
375 if (connector->registered)
376 goto unlock;
377
378 ret = drm_sysfs_connector_add(connector);
379 if (ret)
380 goto unlock;
381
382 ret = drm_debugfs_connector_add(connector);
383 if (ret) {
384 goto err_sysfs;
385 }
386
387 if (connector->funcs->late_register) {
388 ret = connector->funcs->late_register(connector);
389 if (ret)
390 goto err_debugfs;
391 }
392
393 drm_mode_object_register(connector->dev, &connector->base);
394
395 connector->registered = true;
396 goto unlock;
397
398err_debugfs:
399 drm_debugfs_connector_remove(connector);
400err_sysfs:
401 drm_sysfs_connector_remove(connector);
402unlock:
403 mutex_unlock(&connector->mutex);
404 return ret;
405}
406EXPORT_SYMBOL(drm_connector_register);
407
408
409
410
411
412
413
414void drm_connector_unregister(struct drm_connector *connector)
415{
416 mutex_lock(&connector->mutex);
417 if (!connector->registered) {
418 mutex_unlock(&connector->mutex);
419 return;
420 }
421
422 if (connector->funcs->early_unregister)
423 connector->funcs->early_unregister(connector);
424
425 drm_sysfs_connector_remove(connector);
426 drm_debugfs_connector_remove(connector);
427
428 connector->registered = false;
429 mutex_unlock(&connector->mutex);
430}
431EXPORT_SYMBOL(drm_connector_unregister);
432
433void drm_connector_unregister_all(struct drm_device *dev)
434{
435 struct drm_connector *connector;
436 struct drm_connector_list_iter conn_iter;
437
438 drm_connector_list_iter_begin(dev, &conn_iter);
439 drm_for_each_connector_iter(connector, &conn_iter)
440 drm_connector_unregister(connector);
441 drm_connector_list_iter_end(&conn_iter);
442}
443
444int drm_connector_register_all(struct drm_device *dev)
445{
446 struct drm_connector *connector;
447 struct drm_connector_list_iter conn_iter;
448 int ret = 0;
449
450 drm_connector_list_iter_begin(dev, &conn_iter);
451 drm_for_each_connector_iter(connector, &conn_iter) {
452 ret = drm_connector_register(connector);
453 if (ret)
454 break;
455 }
456 drm_connector_list_iter_end(&conn_iter);
457
458 if (ret)
459 drm_connector_unregister_all(dev);
460 return ret;
461}
462
463
464
465
466
467
468
469
470const char *drm_get_connector_status_name(enum drm_connector_status status)
471{
472 if (status == connector_status_connected)
473 return "connected";
474 else if (status == connector_status_disconnected)
475 return "disconnected";
476 else
477 return "unknown";
478}
479EXPORT_SYMBOL(drm_get_connector_status_name);
480
481
482
483
484
485
486
487const char *drm_get_connector_force_name(enum drm_connector_force force)
488{
489 switch (force) {
490 case DRM_FORCE_UNSPECIFIED:
491 return "unspecified";
492 case DRM_FORCE_OFF:
493 return "off";
494 case DRM_FORCE_ON:
495 return "on";
496 case DRM_FORCE_ON_DIGITAL:
497 return "digital";
498 default:
499 return "unknown";
500 }
501}
502
503#ifdef CONFIG_LOCKDEP
504static struct lockdep_map connector_list_iter_dep_map = {
505 .name = "drm_connector_list_iter"
506};
507#endif
508
509
510
511
512
513
514
515
516
517
518
519void drm_connector_list_iter_begin(struct drm_device *dev,
520 struct drm_connector_list_iter *iter)
521{
522 iter->dev = dev;
523 iter->conn = NULL;
524 lock_acquire_shared_recursive(&connector_list_iter_dep_map, 0, 1, NULL, _RET_IP_);
525}
526EXPORT_SYMBOL(drm_connector_list_iter_begin);
527
528
529
530
531
532
533
534
535struct drm_connector *
536drm_connector_list_iter_next(struct drm_connector_list_iter *iter)
537{
538 struct drm_connector *old_conn = iter->conn;
539 struct drm_mode_config *config = &iter->dev->mode_config;
540 struct list_head *lhead;
541 unsigned long flags;
542
543 spin_lock_irqsave(&config->connector_list_lock, flags);
544 lhead = old_conn ? &old_conn->head : &config->connector_list;
545
546 do {
547 if (lhead->next == &config->connector_list) {
548 iter->conn = NULL;
549 break;
550 }
551
552 lhead = lhead->next;
553 iter->conn = list_entry(lhead, struct drm_connector, head);
554
555
556 } while (!kref_get_unless_zero(&iter->conn->base.refcount));
557 spin_unlock_irqrestore(&config->connector_list_lock, flags);
558
559 if (old_conn)
560 drm_connector_put(old_conn);
561
562 return iter->conn;
563}
564EXPORT_SYMBOL(drm_connector_list_iter_next);
565
566
567
568
569
570
571
572
573
574
575void drm_connector_list_iter_end(struct drm_connector_list_iter *iter)
576{
577 iter->dev = NULL;
578 if (iter->conn)
579 drm_connector_put(iter->conn);
580 lock_release(&connector_list_iter_dep_map, 0, _RET_IP_);
581}
582EXPORT_SYMBOL(drm_connector_list_iter_end);
583
584static const struct drm_prop_enum_list drm_subpixel_enum_list[] = {
585 { SubPixelUnknown, "Unknown" },
586 { SubPixelHorizontalRGB, "Horizontal RGB" },
587 { SubPixelHorizontalBGR, "Horizontal BGR" },
588 { SubPixelVerticalRGB, "Vertical RGB" },
589 { SubPixelVerticalBGR, "Vertical BGR" },
590 { SubPixelNone, "None" },
591};
592
593
594
595
596
597
598
599
600const char *drm_get_subpixel_order_name(enum subpixel_order order)
601{
602 return drm_subpixel_enum_list[order].name;
603}
604EXPORT_SYMBOL(drm_get_subpixel_order_name);
605
606static const struct drm_prop_enum_list drm_dpms_enum_list[] = {
607 { DRM_MODE_DPMS_ON, "On" },
608 { DRM_MODE_DPMS_STANDBY, "Standby" },
609 { DRM_MODE_DPMS_SUSPEND, "Suspend" },
610 { DRM_MODE_DPMS_OFF, "Off" }
611};
612DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
613
614static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
615 { DRM_MODE_LINK_STATUS_GOOD, "Good" },
616 { DRM_MODE_LINK_STATUS_BAD, "Bad" },
617};
618DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list)
619
620
621
622
623
624
625
626
627
628
629
630int drm_display_info_set_bus_formats(struct drm_display_info *info,
631 const u32 *formats,
632 unsigned int num_formats)
633{
634 u32 *fmts = NULL;
635
636 if (!formats && num_formats)
637 return -EINVAL;
638
639 if (formats && num_formats) {
640 fmts = kmemdup(formats, sizeof(*formats) * num_formats,
641 GFP_KERNEL);
642 if (!fmts)
643 return -ENOMEM;
644 }
645
646 kfree(info->bus_formats);
647 info->bus_formats = fmts;
648 info->num_bus_formats = num_formats;
649
650 return 0;
651}
652EXPORT_SYMBOL(drm_display_info_set_bus_formats);
653
654
655static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = {
656 { DRM_MODE_SCALE_NONE, "None" },
657 { DRM_MODE_SCALE_FULLSCREEN, "Full" },
658 { DRM_MODE_SCALE_CENTER, "Center" },
659 { DRM_MODE_SCALE_ASPECT, "Full aspect" },
660};
661
662static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = {
663 { DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" },
664 { DRM_MODE_PICTURE_ASPECT_4_3, "4:3" },
665 { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" },
666};
667
668static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = {
669 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" },
670 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" },
671 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" },
672};
673DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list)
674
675static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = {
676 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" },
677 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" },
678 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" },
679};
680DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
681 drm_dvi_i_subconnector_enum_list)
682
683static const struct drm_prop_enum_list drm_tv_select_enum_list[] = {
684 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" },
685 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" },
686 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" },
687 { DRM_MODE_SUBCONNECTOR_Component, "Component" },
688 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" },
689};
690DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
691
692static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = {
693 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" },
694 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" },
695 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" },
696 { DRM_MODE_SUBCONNECTOR_Component, "Component" },
697 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" },
698};
699DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
700 drm_tv_subconnector_enum_list)
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751int drm_connector_create_standard_properties(struct drm_device *dev)
752{
753 struct drm_property *prop;
754
755 prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
756 DRM_MODE_PROP_IMMUTABLE,
757 "EDID", 0);
758 if (!prop)
759 return -ENOMEM;
760 dev->mode_config.edid_property = prop;
761
762 prop = drm_property_create_enum(dev, 0,
763 "DPMS", drm_dpms_enum_list,
764 ARRAY_SIZE(drm_dpms_enum_list));
765 if (!prop)
766 return -ENOMEM;
767 dev->mode_config.dpms_property = prop;
768
769 prop = drm_property_create(dev,
770 DRM_MODE_PROP_BLOB |
771 DRM_MODE_PROP_IMMUTABLE,
772 "PATH", 0);
773 if (!prop)
774 return -ENOMEM;
775 dev->mode_config.path_property = prop;
776
777 prop = drm_property_create(dev,
778 DRM_MODE_PROP_BLOB |
779 DRM_MODE_PROP_IMMUTABLE,
780 "TILE", 0);
781 if (!prop)
782 return -ENOMEM;
783 dev->mode_config.tile_property = prop;
784
785 prop = drm_property_create_enum(dev, 0, "link-status",
786 drm_link_status_enum_list,
787 ARRAY_SIZE(drm_link_status_enum_list));
788 if (!prop)
789 return -ENOMEM;
790 dev->mode_config.link_status_property = prop;
791
792 return 0;
793}
794
795
796
797
798
799
800
801int drm_mode_create_dvi_i_properties(struct drm_device *dev)
802{
803 struct drm_property *dvi_i_selector;
804 struct drm_property *dvi_i_subconnector;
805
806 if (dev->mode_config.dvi_i_select_subconnector_property)
807 return 0;
808
809 dvi_i_selector =
810 drm_property_create_enum(dev, 0,
811 "select subconnector",
812 drm_dvi_i_select_enum_list,
813 ARRAY_SIZE(drm_dvi_i_select_enum_list));
814 dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector;
815
816 dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
817 "subconnector",
818 drm_dvi_i_subconnector_enum_list,
819 ARRAY_SIZE(drm_dvi_i_subconnector_enum_list));
820 dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector;
821
822 return 0;
823}
824EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
825
826
827
828
829
830
831
832
833
834
835
836
837int drm_mode_create_tv_properties(struct drm_device *dev,
838 unsigned int num_modes,
839 const char * const modes[])
840{
841 struct drm_property *tv_selector;
842 struct drm_property *tv_subconnector;
843 unsigned int i;
844
845 if (dev->mode_config.tv_select_subconnector_property)
846 return 0;
847
848
849
850
851 tv_selector = drm_property_create_enum(dev, 0,
852 "select subconnector",
853 drm_tv_select_enum_list,
854 ARRAY_SIZE(drm_tv_select_enum_list));
855 if (!tv_selector)
856 goto nomem;
857
858 dev->mode_config.tv_select_subconnector_property = tv_selector;
859
860 tv_subconnector =
861 drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
862 "subconnector",
863 drm_tv_subconnector_enum_list,
864 ARRAY_SIZE(drm_tv_subconnector_enum_list));
865 if (!tv_subconnector)
866 goto nomem;
867 dev->mode_config.tv_subconnector_property = tv_subconnector;
868
869
870
871
872 dev->mode_config.tv_left_margin_property =
873 drm_property_create_range(dev, 0, "left margin", 0, 100);
874 if (!dev->mode_config.tv_left_margin_property)
875 goto nomem;
876
877 dev->mode_config.tv_right_margin_property =
878 drm_property_create_range(dev, 0, "right margin", 0, 100);
879 if (!dev->mode_config.tv_right_margin_property)
880 goto nomem;
881
882 dev->mode_config.tv_top_margin_property =
883 drm_property_create_range(dev, 0, "top margin", 0, 100);
884 if (!dev->mode_config.tv_top_margin_property)
885 goto nomem;
886
887 dev->mode_config.tv_bottom_margin_property =
888 drm_property_create_range(dev, 0, "bottom margin", 0, 100);
889 if (!dev->mode_config.tv_bottom_margin_property)
890 goto nomem;
891
892 dev->mode_config.tv_mode_property =
893 drm_property_create(dev, DRM_MODE_PROP_ENUM,
894 "mode", num_modes);
895 if (!dev->mode_config.tv_mode_property)
896 goto nomem;
897
898 for (i = 0; i < num_modes; i++)
899 drm_property_add_enum(dev->mode_config.tv_mode_property, i,
900 i, modes[i]);
901
902 dev->mode_config.tv_brightness_property =
903 drm_property_create_range(dev, 0, "brightness", 0, 100);
904 if (!dev->mode_config.tv_brightness_property)
905 goto nomem;
906
907 dev->mode_config.tv_contrast_property =
908 drm_property_create_range(dev, 0, "contrast", 0, 100);
909 if (!dev->mode_config.tv_contrast_property)
910 goto nomem;
911
912 dev->mode_config.tv_flicker_reduction_property =
913 drm_property_create_range(dev, 0, "flicker reduction", 0, 100);
914 if (!dev->mode_config.tv_flicker_reduction_property)
915 goto nomem;
916
917 dev->mode_config.tv_overscan_property =
918 drm_property_create_range(dev, 0, "overscan", 0, 100);
919 if (!dev->mode_config.tv_overscan_property)
920 goto nomem;
921
922 dev->mode_config.tv_saturation_property =
923 drm_property_create_range(dev, 0, "saturation", 0, 100);
924 if (!dev->mode_config.tv_saturation_property)
925 goto nomem;
926
927 dev->mode_config.tv_hue_property =
928 drm_property_create_range(dev, 0, "hue", 0, 100);
929 if (!dev->mode_config.tv_hue_property)
930 goto nomem;
931
932 return 0;
933nomem:
934 return -ENOMEM;
935}
936EXPORT_SYMBOL(drm_mode_create_tv_properties);
937
938
939
940
941
942
943
944
945
946
947
948
949int drm_mode_create_scaling_mode_property(struct drm_device *dev)
950{
951 struct drm_property *scaling_mode;
952
953 if (dev->mode_config.scaling_mode_property)
954 return 0;
955
956 scaling_mode =
957 drm_property_create_enum(dev, 0, "scaling mode",
958 drm_scaling_mode_enum_list,
959 ARRAY_SIZE(drm_scaling_mode_enum_list));
960
961 dev->mode_config.scaling_mode_property = scaling_mode;
962
963 return 0;
964}
965EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
982 u32 scaling_mode_mask)
983{
984 struct drm_device *dev = connector->dev;
985 struct drm_property *scaling_mode_property;
986 int i, j = 0;
987 const unsigned valid_scaling_mode_mask =
988 (1U << ARRAY_SIZE(drm_scaling_mode_enum_list)) - 1;
989
990 if (WARN_ON(hweight32(scaling_mode_mask) < 2 ||
991 scaling_mode_mask & ~valid_scaling_mode_mask))
992 return -EINVAL;
993
994 scaling_mode_property =
995 drm_property_create(dev, DRM_MODE_PROP_ENUM, "scaling mode",
996 hweight32(scaling_mode_mask));
997
998 if (!scaling_mode_property)
999 return -ENOMEM;
1000
1001 for (i = 0; i < ARRAY_SIZE(drm_scaling_mode_enum_list); i++) {
1002 int ret;
1003
1004 if (!(BIT(i) & scaling_mode_mask))
1005 continue;
1006
1007 ret = drm_property_add_enum(scaling_mode_property, j++,
1008 drm_scaling_mode_enum_list[i].type,
1009 drm_scaling_mode_enum_list[i].name);
1010
1011 if (ret) {
1012 drm_property_destroy(dev, scaling_mode_property);
1013
1014 return ret;
1015 }
1016 }
1017
1018 drm_object_attach_property(&connector->base,
1019 scaling_mode_property, 0);
1020
1021 connector->scaling_mode_property = scaling_mode_property;
1022
1023 return 0;
1024}
1025EXPORT_SYMBOL(drm_connector_attach_scaling_mode_property);
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037int drm_mode_create_aspect_ratio_property(struct drm_device *dev)
1038{
1039 if (dev->mode_config.aspect_ratio_property)
1040 return 0;
1041
1042 dev->mode_config.aspect_ratio_property =
1043 drm_property_create_enum(dev, 0, "aspect ratio",
1044 drm_aspect_ratio_enum_list,
1045 ARRAY_SIZE(drm_aspect_ratio_enum_list));
1046
1047 if (dev->mode_config.aspect_ratio_property == NULL)
1048 return -ENOMEM;
1049
1050 return 0;
1051}
1052EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
1053
1054
1055
1056
1057
1058
1059
1060int drm_mode_create_suggested_offset_properties(struct drm_device *dev)
1061{
1062 if (dev->mode_config.suggested_x_property && dev->mode_config.suggested_y_property)
1063 return 0;
1064
1065 dev->mode_config.suggested_x_property =
1066 drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested X", 0, 0xffffffff);
1067
1068 dev->mode_config.suggested_y_property =
1069 drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested Y", 0, 0xffffffff);
1070
1071 if (dev->mode_config.suggested_x_property == NULL ||
1072 dev->mode_config.suggested_y_property == NULL)
1073 return -ENOMEM;
1074 return 0;
1075}
1076EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties);
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091int drm_mode_connector_set_path_property(struct drm_connector *connector,
1092 const char *path)
1093{
1094 struct drm_device *dev = connector->dev;
1095 int ret;
1096
1097 ret = drm_property_replace_global_blob(dev,
1098 &connector->path_blob_ptr,
1099 strlen(path) + 1,
1100 path,
1101 &connector->base,
1102 dev->mode_config.path_property);
1103 return ret;
1104}
1105EXPORT_SYMBOL(drm_mode_connector_set_path_property);
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118int drm_mode_connector_set_tile_property(struct drm_connector *connector)
1119{
1120 struct drm_device *dev = connector->dev;
1121 char tile[256];
1122 int ret;
1123
1124 if (!connector->has_tile) {
1125 ret = drm_property_replace_global_blob(dev,
1126 &connector->tile_blob_ptr,
1127 0,
1128 NULL,
1129 &connector->base,
1130 dev->mode_config.tile_property);
1131 return ret;
1132 }
1133
1134 snprintf(tile, 256, "%d:%d:%d:%d:%d:%d:%d:%d",
1135 connector->tile_group->id, connector->tile_is_single_monitor,
1136 connector->num_h_tile, connector->num_v_tile,
1137 connector->tile_h_loc, connector->tile_v_loc,
1138 connector->tile_h_size, connector->tile_v_size);
1139
1140 ret = drm_property_replace_global_blob(dev,
1141 &connector->tile_blob_ptr,
1142 strlen(tile) + 1,
1143 tile,
1144 &connector->base,
1145 dev->mode_config.tile_property);
1146 return ret;
1147}
1148EXPORT_SYMBOL(drm_mode_connector_set_tile_property);
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161int drm_mode_connector_update_edid_property(struct drm_connector *connector,
1162 const struct edid *edid)
1163{
1164 struct drm_device *dev = connector->dev;
1165 size_t size = 0;
1166 int ret;
1167
1168
1169 if (connector->override_edid)
1170 return 0;
1171
1172 if (edid)
1173 size = EDID_LENGTH * (1 + edid->extensions);
1174
1175 ret = drm_property_replace_global_blob(dev,
1176 &connector->edid_blob_ptr,
1177 size,
1178 edid,
1179 &connector->base,
1180 dev->mode_config.edid_property);
1181 return ret;
1182}
1183EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204void drm_mode_connector_set_link_status_property(struct drm_connector *connector,
1205 uint64_t link_status)
1206{
1207 struct drm_device *dev = connector->dev;
1208
1209 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
1210 connector->state->link_status = link_status;
1211 drm_modeset_unlock(&dev->mode_config.connection_mutex);
1212}
1213EXPORT_SYMBOL(drm_mode_connector_set_link_status_property);
1214
1215int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
1216 struct drm_property *property,
1217 uint64_t value)
1218{
1219 int ret = -EINVAL;
1220 struct drm_connector *connector = obj_to_connector(obj);
1221
1222
1223 if (property == connector->dev->mode_config.dpms_property) {
1224 ret = (*connector->funcs->dpms)(connector, (int)value);
1225 } else if (connector->funcs->set_property)
1226 ret = connector->funcs->set_property(connector, property, value);
1227
1228
1229 if (!ret)
1230 drm_object_property_set_value(&connector->base, property, value);
1231 return ret;
1232}
1233
1234int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
1235 void *data, struct drm_file *file_priv)
1236{
1237 struct drm_mode_connector_set_property *conn_set_prop = data;
1238 struct drm_mode_obj_set_property obj_set_prop = {
1239 .value = conn_set_prop->value,
1240 .prop_id = conn_set_prop->prop_id,
1241 .obj_id = conn_set_prop->connector_id,
1242 .obj_type = DRM_MODE_OBJECT_CONNECTOR
1243 };
1244
1245
1246 return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv);
1247}
1248
1249static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector)
1250{
1251
1252
1253 if (connector->state)
1254 return connector->state->best_encoder;
1255 return connector->encoder;
1256}
1257
1258static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
1259 const struct drm_file *file_priv)
1260{
1261
1262
1263
1264
1265 if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode))
1266 return false;
1267
1268 return true;
1269}
1270
1271int drm_mode_getconnector(struct drm_device *dev, void *data,
1272 struct drm_file *file_priv)
1273{
1274 struct drm_mode_get_connector *out_resp = data;
1275 struct drm_connector *connector;
1276 struct drm_encoder *encoder;
1277 struct drm_display_mode *mode;
1278 int mode_count = 0;
1279 int encoders_count = 0;
1280 int ret = 0;
1281 int copied = 0;
1282 int i;
1283 struct drm_mode_modeinfo u_mode;
1284 struct drm_mode_modeinfo __user *mode_ptr;
1285 uint32_t __user *encoder_ptr;
1286
1287 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1288 return -EINVAL;
1289
1290 memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
1291
1292 connector = drm_connector_lookup(dev, out_resp->connector_id);
1293 if (!connector)
1294 return -ENOENT;
1295
1296 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
1297 if (connector->encoder_ids[i] != 0)
1298 encoders_count++;
1299
1300 if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
1301 copied = 0;
1302 encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
1303 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
1304 if (connector->encoder_ids[i] != 0) {
1305 if (put_user(connector->encoder_ids[i],
1306 encoder_ptr + copied)) {
1307 ret = -EFAULT;
1308 goto out;
1309 }
1310 copied++;
1311 }
1312 }
1313 }
1314 out_resp->count_encoders = encoders_count;
1315
1316 out_resp->connector_id = connector->base.id;
1317 out_resp->connector_type = connector->connector_type;
1318 out_resp->connector_type_id = connector->connector_type_id;
1319
1320 mutex_lock(&dev->mode_config.mutex);
1321 if (out_resp->count_modes == 0) {
1322 connector->funcs->fill_modes(connector,
1323 dev->mode_config.max_width,
1324 dev->mode_config.max_height);
1325 }
1326
1327 out_resp->mm_width = connector->display_info.width_mm;
1328 out_resp->mm_height = connector->display_info.height_mm;
1329 out_resp->subpixel = connector->display_info.subpixel_order;
1330 out_resp->connection = connector->status;
1331
1332
1333 list_for_each_entry(mode, &connector->modes, head)
1334 if (drm_mode_expose_to_userspace(mode, file_priv))
1335 mode_count++;
1336
1337
1338
1339
1340
1341 if ((out_resp->count_modes >= mode_count) && mode_count) {
1342 copied = 0;
1343 mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
1344 list_for_each_entry(mode, &connector->modes, head) {
1345 if (!drm_mode_expose_to_userspace(mode, file_priv))
1346 continue;
1347
1348 drm_mode_convert_to_umode(&u_mode, mode);
1349 if (copy_to_user(mode_ptr + copied,
1350 &u_mode, sizeof(u_mode))) {
1351 ret = -EFAULT;
1352 mutex_unlock(&dev->mode_config.mutex);
1353
1354 goto out;
1355 }
1356 copied++;
1357 }
1358 }
1359 out_resp->count_modes = mode_count;
1360 mutex_unlock(&dev->mode_config.mutex);
1361
1362 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
1363 encoder = drm_connector_get_encoder(connector);
1364 if (encoder)
1365 out_resp->encoder_id = encoder->base.id;
1366 else
1367 out_resp->encoder_id = 0;
1368
1369
1370
1371 ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
1372 (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
1373 (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
1374 &out_resp->count_props);
1375 drm_modeset_unlock(&dev->mode_config.connection_mutex);
1376
1377out:
1378 drm_connector_put(connector);
1379
1380 return ret;
1381}
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396static void drm_tile_group_free(struct kref *kref)
1397{
1398 struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
1399 struct drm_device *dev = tg->dev;
1400 mutex_lock(&dev->mode_config.idr_mutex);
1401 idr_remove(&dev->mode_config.tile_idr, tg->id);
1402 mutex_unlock(&dev->mode_config.idr_mutex);
1403 kfree(tg);
1404}
1405
1406
1407
1408
1409
1410
1411
1412
1413void drm_mode_put_tile_group(struct drm_device *dev,
1414 struct drm_tile_group *tg)
1415{
1416 kref_put(&tg->refcount, drm_tile_group_free);
1417}
1418EXPORT_SYMBOL(drm_mode_put_tile_group);
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
1431 char topology[8])
1432{
1433 struct drm_tile_group *tg;
1434 int id;
1435 mutex_lock(&dev->mode_config.idr_mutex);
1436 idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
1437 if (!memcmp(tg->group_data, topology, 8)) {
1438 if (!kref_get_unless_zero(&tg->refcount))
1439 tg = NULL;
1440 mutex_unlock(&dev->mode_config.idr_mutex);
1441 return tg;
1442 }
1443 }
1444 mutex_unlock(&dev->mode_config.idr_mutex);
1445 return NULL;
1446}
1447EXPORT_SYMBOL(drm_mode_get_tile_group);
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
1461 char topology[8])
1462{
1463 struct drm_tile_group *tg;
1464 int ret;
1465
1466 tg = kzalloc(sizeof(*tg), GFP_KERNEL);
1467 if (!tg)
1468 return ERR_PTR(-ENOMEM);
1469
1470 kref_init(&tg->refcount);
1471 memcpy(tg->group_data, topology, 8);
1472 tg->dev = dev;
1473
1474 mutex_lock(&dev->mode_config.idr_mutex);
1475 ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL);
1476 if (ret >= 0) {
1477 tg->id = ret;
1478 } else {
1479 kfree(tg);
1480 tg = ERR_PTR(ret);
1481 }
1482
1483 mutex_unlock(&dev->mode_config.idr_mutex);
1484 return tg;
1485}
1486EXPORT_SYMBOL(drm_mode_create_tile_group);
1487