1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <linux/export.h>
33#include <linux/moduleparam.h>
34
35#include <drm/drmP.h>
36#include <drm/drm_client.h>
37#include <drm/drm_crtc.h>
38#include <drm/drm_fourcc.h>
39#include <drm/drm_crtc_helper.h>
40#include <drm/drm_fb_helper.h>
41#include <drm/drm_edid.h>
42#include <drm/drm_modeset_helper_vtables.h>
43
44#include "drm_crtc_helper_internal.h"
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65static bool drm_kms_helper_poll = true;
66module_param_named(poll, drm_kms_helper_poll, bool, 0600);
67
68static enum drm_mode_status
69drm_mode_validate_flag(const struct drm_display_mode *mode,
70 int flags)
71{
72 if ((mode->flags & DRM_MODE_FLAG_INTERLACE) &&
73 !(flags & DRM_MODE_FLAG_INTERLACE))
74 return MODE_NO_INTERLACE;
75
76 if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) &&
77 !(flags & DRM_MODE_FLAG_DBLSCAN))
78 return MODE_NO_DBLESCAN;
79
80 if ((mode->flags & DRM_MODE_FLAG_3D_MASK) &&
81 !(flags & DRM_MODE_FLAG_3D_MASK))
82 return MODE_NO_STEREO;
83
84 return MODE_OK;
85}
86
87static enum drm_mode_status
88drm_mode_validate_pipeline(struct drm_display_mode *mode,
89 struct drm_connector *connector)
90{
91 struct drm_device *dev = connector->dev;
92 enum drm_mode_status ret = MODE_OK;
93 struct drm_encoder *encoder;
94 int i;
95
96
97 ret = drm_connector_mode_valid(connector, mode);
98 if (ret != MODE_OK)
99 return ret;
100
101
102 drm_connector_for_each_possible_encoder(connector, encoder, i) {
103 struct drm_crtc *crtc;
104
105 ret = drm_encoder_mode_valid(encoder, mode);
106 if (ret != MODE_OK) {
107
108
109
110
111 continue;
112 }
113
114 ret = drm_bridge_mode_valid(encoder->bridge, mode);
115 if (ret != MODE_OK) {
116
117
118 continue;
119 }
120
121 drm_for_each_crtc(crtc, dev) {
122 if (!drm_encoder_crtc_ok(encoder, crtc))
123 continue;
124
125 ret = drm_crtc_mode_valid(crtc, mode);
126 if (ret == MODE_OK) {
127
128
129
130 return ret;
131 }
132 }
133 }
134
135 return ret;
136}
137
138static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
139{
140 struct drm_cmdline_mode *cmdline_mode;
141 struct drm_display_mode *mode;
142
143 cmdline_mode = &connector->cmdline_mode;
144 if (!cmdline_mode->specified)
145 return 0;
146
147
148 list_for_each_entry(mode, &connector->probed_modes, head) {
149 if (mode->hdisplay != cmdline_mode->xres ||
150 mode->vdisplay != cmdline_mode->yres)
151 continue;
152
153 if (cmdline_mode->refresh_specified) {
154
155 if (drm_mode_vrefresh(mode) != cmdline_mode->refresh)
156 continue;
157 }
158
159 return 0;
160 }
161
162 mode = drm_mode_create_from_cmdline_mode(connector->dev,
163 cmdline_mode);
164 if (mode == NULL)
165 return 0;
166
167 drm_mode_probed_add(connector, mode);
168 return 1;
169}
170
171enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
172 const struct drm_display_mode *mode)
173{
174 const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
175
176 if (!crtc_funcs || !crtc_funcs->mode_valid)
177 return MODE_OK;
178
179 return crtc_funcs->mode_valid(crtc, mode);
180}
181
182enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder,
183 const struct drm_display_mode *mode)
184{
185 const struct drm_encoder_helper_funcs *encoder_funcs =
186 encoder->helper_private;
187
188 if (!encoder_funcs || !encoder_funcs->mode_valid)
189 return MODE_OK;
190
191 return encoder_funcs->mode_valid(encoder, mode);
192}
193
194enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector,
195 struct drm_display_mode *mode)
196{
197 const struct drm_connector_helper_funcs *connector_funcs =
198 connector->helper_private;
199
200 if (!connector_funcs || !connector_funcs->mode_valid)
201 return MODE_OK;
202
203 return connector_funcs->mode_valid(connector, mode);
204}
205
206#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222void drm_kms_helper_poll_enable(struct drm_device *dev)
223{
224 bool poll = false;
225 struct drm_connector *connector;
226 struct drm_connector_list_iter conn_iter;
227 unsigned long delay = DRM_OUTPUT_POLL_PERIOD;
228
229 if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
230 return;
231
232 drm_connector_list_iter_begin(dev, &conn_iter);
233 drm_for_each_connector_iter(connector, &conn_iter) {
234 if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
235 DRM_CONNECTOR_POLL_DISCONNECT))
236 poll = true;
237 }
238 drm_connector_list_iter_end(&conn_iter);
239
240 if (dev->mode_config.delayed_event) {
241
242
243
244
245
246
247
248
249
250
251 poll = true;
252 delay = HZ;
253 }
254
255 if (poll)
256 schedule_delayed_work(&dev->mode_config.output_poll_work, delay);
257}
258EXPORT_SYMBOL(drm_kms_helper_poll_enable);
259
260static enum drm_connector_status
261drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force)
262{
263 const struct drm_connector_helper_funcs *funcs = connector->helper_private;
264 struct drm_modeset_acquire_ctx ctx;
265 int ret;
266
267 drm_modeset_acquire_init(&ctx, 0);
268
269retry:
270 ret = drm_modeset_lock(&connector->dev->mode_config.connection_mutex, &ctx);
271 if (!ret) {
272 if (funcs->detect_ctx)
273 ret = funcs->detect_ctx(connector, &ctx, force);
274 else if (connector->funcs->detect)
275 ret = connector->funcs->detect(connector, force);
276 else
277 ret = connector_status_connected;
278 }
279
280 if (ret == -EDEADLK) {
281 drm_modeset_backoff(&ctx);
282 goto retry;
283 }
284
285 if (WARN_ON(ret < 0))
286 ret = connector_status_unknown;
287
288 drm_modeset_drop_locks(&ctx);
289 drm_modeset_acquire_fini(&ctx);
290
291 return ret;
292}
293
294
295
296
297
298
299
300
301
302
303
304int
305drm_helper_probe_detect(struct drm_connector *connector,
306 struct drm_modeset_acquire_ctx *ctx,
307 bool force)
308{
309 const struct drm_connector_helper_funcs *funcs = connector->helper_private;
310 struct drm_device *dev = connector->dev;
311 int ret;
312
313 if (!ctx)
314 return drm_helper_probe_detect_ctx(connector, force);
315
316 ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
317 if (ret)
318 return ret;
319
320 if (funcs->detect_ctx)
321 return funcs->detect_ctx(connector, ctx, force);
322 else if (connector->funcs->detect)
323 return connector->funcs->detect(connector, force);
324 else
325 return connector_status_connected;
326}
327EXPORT_SYMBOL(drm_helper_probe_detect);
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
388 uint32_t maxX, uint32_t maxY)
389{
390 struct drm_device *dev = connector->dev;
391 struct drm_display_mode *mode;
392 const struct drm_connector_helper_funcs *connector_funcs =
393 connector->helper_private;
394 int count = 0, ret;
395 int mode_flags = 0;
396 bool verbose_prune = true;
397 enum drm_connector_status old_status;
398 struct drm_modeset_acquire_ctx ctx;
399
400 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
401
402 drm_modeset_acquire_init(&ctx, 0);
403
404 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
405 connector->name);
406
407retry:
408 ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
409 if (ret == -EDEADLK) {
410 drm_modeset_backoff(&ctx);
411 goto retry;
412 } else
413 WARN_ON(ret < 0);
414
415
416 list_for_each_entry(mode, &connector->modes, head)
417 mode->status = MODE_STALE;
418
419 old_status = connector->status;
420
421 if (connector->force) {
422 if (connector->force == DRM_FORCE_ON ||
423 connector->force == DRM_FORCE_ON_DIGITAL)
424 connector->status = connector_status_connected;
425 else
426 connector->status = connector_status_disconnected;
427 if (connector->funcs->force)
428 connector->funcs->force(connector);
429 } else {
430 ret = drm_helper_probe_detect(connector, &ctx, true);
431
432 if (ret == -EDEADLK) {
433 drm_modeset_backoff(&ctx);
434 goto retry;
435 } else if (WARN(ret < 0, "Invalid return value %i for connector detection\n", ret))
436 ret = connector_status_unknown;
437
438 connector->status = ret;
439 }
440
441
442
443
444
445
446
447 if (old_status != connector->status) {
448 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
449 connector->base.id,
450 connector->name,
451 drm_get_connector_status_name(old_status),
452 drm_get_connector_status_name(connector->status));
453
454
455
456
457
458
459
460 dev->mode_config.delayed_event = true;
461 if (dev->mode_config.poll_enabled)
462 schedule_delayed_work(&dev->mode_config.output_poll_work,
463 0);
464 }
465
466
467 if (drm_kms_helper_poll != dev->mode_config.poll_running)
468 drm_kms_helper_poll_enable(dev);
469
470 dev->mode_config.poll_running = drm_kms_helper_poll;
471
472 if (connector->status == connector_status_disconnected) {
473 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
474 connector->base.id, connector->name);
475 drm_connector_update_edid_property(connector, NULL);
476 verbose_prune = false;
477 goto prune;
478 }
479
480 count = (*connector_funcs->get_modes)(connector);
481
482 if (count == 0 && connector->status == connector_status_connected)
483 count = drm_add_modes_noedid(connector, 1024, 768);
484 count += drm_helper_probe_add_cmdline_mode(connector);
485 if (count == 0)
486 goto prune;
487
488 drm_connector_list_update(connector);
489
490 if (connector->interlace_allowed)
491 mode_flags |= DRM_MODE_FLAG_INTERLACE;
492 if (connector->doublescan_allowed)
493 mode_flags |= DRM_MODE_FLAG_DBLSCAN;
494 if (connector->stereo_allowed)
495 mode_flags |= DRM_MODE_FLAG_3D_MASK;
496
497 list_for_each_entry(mode, &connector->modes, head) {
498 if (mode->status == MODE_OK)
499 mode->status = drm_mode_validate_driver(dev, mode);
500
501 if (mode->status == MODE_OK)
502 mode->status = drm_mode_validate_size(mode, maxX, maxY);
503
504 if (mode->status == MODE_OK)
505 mode->status = drm_mode_validate_flag(mode, mode_flags);
506
507 if (mode->status == MODE_OK)
508 mode->status = drm_mode_validate_pipeline(mode,
509 connector);
510
511 if (mode->status == MODE_OK)
512 mode->status = drm_mode_validate_ycbcr420(mode,
513 connector);
514 }
515
516prune:
517 drm_mode_prune_invalid(dev, &connector->modes, verbose_prune);
518
519 drm_modeset_drop_locks(&ctx);
520 drm_modeset_acquire_fini(&ctx);
521
522 if (list_empty(&connector->modes))
523 return 0;
524
525 list_for_each_entry(mode, &connector->modes, head)
526 mode->vrefresh = drm_mode_vrefresh(mode);
527
528 drm_mode_sort(&connector->modes);
529
530 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
531 connector->name);
532 list_for_each_entry(mode, &connector->modes, head) {
533 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
534 drm_mode_debug_printmodeline(mode);
535 }
536
537 return count;
538}
539EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557void drm_kms_helper_hotplug_event(struct drm_device *dev)
558{
559
560 drm_sysfs_hotplug_event(dev);
561 if (dev->mode_config.funcs->output_poll_changed)
562 dev->mode_config.funcs->output_poll_changed(dev);
563
564 drm_client_dev_hotplug(dev);
565}
566EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
567
568static void output_poll_execute(struct work_struct *work)
569{
570 struct delayed_work *delayed_work = to_delayed_work(work);
571 struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work);
572 struct drm_connector *connector;
573 struct drm_connector_list_iter conn_iter;
574 enum drm_connector_status old_status;
575 bool repoll = false, changed;
576
577
578 changed = dev->mode_config.delayed_event;
579 dev->mode_config.delayed_event = false;
580
581 if (!drm_kms_helper_poll)
582 goto out;
583
584 if (!mutex_trylock(&dev->mode_config.mutex)) {
585 repoll = true;
586 goto out;
587 }
588
589 drm_connector_list_iter_begin(dev, &conn_iter);
590 drm_for_each_connector_iter(connector, &conn_iter) {
591
592 if (connector->force)
593 continue;
594
595
596
597 if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD)
598 continue;
599
600 old_status = connector->status;
601
602
603 if (old_status == connector_status_connected &&
604 !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT))
605 continue;
606
607 repoll = true;
608
609 connector->status = drm_helper_probe_detect(connector, NULL, false);
610 if (old_status != connector->status) {
611 const char *old, *new;
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626 if (connector->status == connector_status_unknown) {
627 connector->status = old_status;
628 continue;
629 }
630
631 old = drm_get_connector_status_name(old_status);
632 new = drm_get_connector_status_name(connector->status);
633
634 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] "
635 "status updated from %s to %s\n",
636 connector->base.id,
637 connector->name,
638 old, new);
639
640 changed = true;
641 }
642 }
643 drm_connector_list_iter_end(&conn_iter);
644
645 mutex_unlock(&dev->mode_config.mutex);
646
647out:
648 if (changed)
649 drm_kms_helper_hotplug_event(dev);
650
651 if (repoll)
652 schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD);
653}
654
655
656
657
658
659
660
661
662
663
664
665
666
667bool drm_kms_helper_is_poll_worker(void)
668{
669 struct work_struct *work = current_work();
670
671 return work && work->func == output_poll_execute;
672}
673EXPORT_SYMBOL(drm_kms_helper_is_poll_worker);
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689void drm_kms_helper_poll_disable(struct drm_device *dev)
690{
691 if (!dev->mode_config.poll_enabled)
692 return;
693 cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
694}
695EXPORT_SYMBOL(drm_kms_helper_poll_disable);
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716void drm_kms_helper_poll_init(struct drm_device *dev)
717{
718 INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute);
719 dev->mode_config.poll_enabled = true;
720
721 drm_kms_helper_poll_enable(dev);
722}
723EXPORT_SYMBOL(drm_kms_helper_poll_init);
724
725
726
727
728
729void drm_kms_helper_poll_fini(struct drm_device *dev)
730{
731 drm_kms_helper_poll_disable(dev);
732}
733EXPORT_SYMBOL(drm_kms_helper_poll_fini);
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758bool drm_helper_hpd_irq_event(struct drm_device *dev)
759{
760 struct drm_connector *connector;
761 struct drm_connector_list_iter conn_iter;
762 enum drm_connector_status old_status;
763 bool changed = false;
764
765 if (!dev->mode_config.poll_enabled)
766 return false;
767
768 mutex_lock(&dev->mode_config.mutex);
769 drm_connector_list_iter_begin(dev, &conn_iter);
770 drm_for_each_connector_iter(connector, &conn_iter) {
771
772 if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
773 continue;
774
775 old_status = connector->status;
776
777 connector->status = drm_helper_probe_detect(connector, NULL, false);
778 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
779 connector->base.id,
780 connector->name,
781 drm_get_connector_status_name(old_status),
782 drm_get_connector_status_name(connector->status));
783 if (old_status != connector->status)
784 changed = true;
785 }
786 drm_connector_list_iter_end(&conn_iter);
787 mutex_unlock(&dev->mode_config.mutex);
788
789 if (changed)
790 drm_kms_helper_hotplug_event(dev);
791
792 return changed;
793}
794EXPORT_SYMBOL(drm_helper_hpd_irq_event);
795