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