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_display_mode *mode;
86
87 if (!connector->cmdline_mode.specified)
88 return 0;
89
90 mode = drm_mode_create_from_cmdline_mode(connector->dev,
91 &connector->cmdline_mode);
92 if (mode == NULL)
93 return 0;
94
95 drm_mode_probed_add(connector, mode);
96 return 1;
97}
98
99#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
100
101
102
103
104
105
106
107
108
109
110
111void drm_kms_helper_poll_enable_locked(struct drm_device *dev)
112{
113 bool poll = false;
114 struct drm_connector *connector;
115
116 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
117
118 if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
119 return;
120
121 drm_for_each_connector(connector, dev) {
122 if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
123 DRM_CONNECTOR_POLL_DISCONNECT))
124 poll = true;
125 }
126
127 if (poll)
128 schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
129}
130EXPORT_SYMBOL(drm_kms_helper_poll_enable_locked);
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
189 uint32_t maxX, uint32_t maxY)
190{
191 struct drm_device *dev = connector->dev;
192 struct drm_display_mode *mode;
193 const struct drm_connector_helper_funcs *connector_funcs =
194 connector->helper_private;
195 int count = 0;
196 int mode_flags = 0;
197 bool verbose_prune = true;
198 enum drm_connector_status old_status;
199
200 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
201
202 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
203 connector->name);
204
205 list_for_each_entry(mode, &connector->modes, head)
206 mode->status = MODE_STALE;
207
208 old_status = connector->status;
209
210 if (connector->force) {
211 if (connector->force == DRM_FORCE_ON ||
212 connector->force == DRM_FORCE_ON_DIGITAL)
213 connector->status = connector_status_connected;
214 else
215 connector->status = connector_status_disconnected;
216 if (connector->funcs->force)
217 connector->funcs->force(connector);
218 } else {
219 connector->status = connector->funcs->detect(connector, true);
220 }
221
222
223
224
225
226
227
228 if (old_status != connector->status) {
229 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
230 connector->base.id,
231 connector->name,
232 drm_get_connector_status_name(old_status),
233 drm_get_connector_status_name(connector->status));
234
235
236
237
238
239
240
241 dev->mode_config.delayed_event = true;
242 if (dev->mode_config.poll_enabled)
243 schedule_delayed_work(&dev->mode_config.output_poll_work,
244 0);
245 }
246
247
248 if (drm_kms_helper_poll != dev->mode_config.poll_running)
249 drm_kms_helper_poll_enable_locked(dev);
250
251 dev->mode_config.poll_running = drm_kms_helper_poll;
252
253 if (connector->status == connector_status_disconnected) {
254 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
255 connector->base.id, connector->name);
256 drm_mode_connector_update_edid_property(connector, NULL);
257 verbose_prune = false;
258 goto prune;
259 }
260
261 if (connector->override_edid) {
262 struct edid *edid = (struct edid *) connector->edid_blob_ptr->data;
263
264 count = drm_add_edid_modes(connector, edid);
265 drm_edid_to_eld(connector, edid);
266 } else {
267#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
268 count = drm_load_edid_firmware(connector);
269 if (count == 0)
270#endif
271 count = (*connector_funcs->get_modes)(connector);
272 }
273
274 if (count == 0 && connector->status == connector_status_connected)
275 count = drm_add_modes_noedid(connector, 1024, 768);
276 count += drm_helper_probe_add_cmdline_mode(connector);
277 if (count == 0)
278 goto prune;
279
280 drm_mode_connector_list_update(connector);
281
282 if (connector->interlace_allowed)
283 mode_flags |= DRM_MODE_FLAG_INTERLACE;
284 if (connector->doublescan_allowed)
285 mode_flags |= DRM_MODE_FLAG_DBLSCAN;
286 if (connector->stereo_allowed)
287 mode_flags |= DRM_MODE_FLAG_3D_MASK;
288
289 list_for_each_entry(mode, &connector->modes, head) {
290 if (mode->status == MODE_OK)
291 mode->status = drm_mode_validate_basic(mode);
292
293 if (mode->status == MODE_OK)
294 mode->status = drm_mode_validate_size(mode, maxX, maxY);
295
296 if (mode->status == MODE_OK)
297 mode->status = drm_mode_validate_flag(mode, mode_flags);
298
299 if (mode->status == MODE_OK && connector_funcs->mode_valid)
300 mode->status = connector_funcs->mode_valid(connector,
301 mode);
302 }
303
304prune:
305 drm_mode_prune_invalid(dev, &connector->modes, verbose_prune);
306
307 if (list_empty(&connector->modes))
308 return 0;
309
310 list_for_each_entry(mode, &connector->modes, head)
311 mode->vrefresh = drm_mode_vrefresh(mode);
312
313 drm_mode_sort(&connector->modes);
314
315 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
316 connector->name);
317 list_for_each_entry(mode, &connector->modes, head) {
318 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
319 drm_mode_debug_printmodeline(mode);
320 }
321
322 return count;
323}
324EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342void drm_kms_helper_hotplug_event(struct drm_device *dev)
343{
344
345 drm_sysfs_hotplug_event(dev);
346 if (dev->mode_config.funcs->output_poll_changed)
347 dev->mode_config.funcs->output_poll_changed(dev);
348}
349EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
350
351static void output_poll_execute(struct work_struct *work)
352{
353 struct delayed_work *delayed_work = to_delayed_work(work);
354 struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work);
355 struct drm_connector *connector;
356 enum drm_connector_status old_status;
357 bool repoll = false, changed;
358
359
360 changed = dev->mode_config.delayed_event;
361 dev->mode_config.delayed_event = false;
362
363 if (!drm_kms_helper_poll)
364 goto out;
365
366 mutex_lock(&dev->mode_config.mutex);
367 drm_for_each_connector(connector, dev) {
368
369
370 if (connector->force)
371 continue;
372
373
374
375 if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD)
376 continue;
377
378 old_status = connector->status;
379
380
381 if (old_status == connector_status_connected &&
382 !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT))
383 continue;
384
385 repoll = true;
386
387 connector->status = connector->funcs->detect(connector, false);
388 if (old_status != connector->status) {
389 const char *old, *new;
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404 if (connector->status == connector_status_unknown) {
405 connector->status = old_status;
406 continue;
407 }
408
409 old = drm_get_connector_status_name(old_status);
410 new = drm_get_connector_status_name(connector->status);
411
412 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] "
413 "status updated from %s to %s\n",
414 connector->base.id,
415 connector->name,
416 old, new);
417
418 changed = true;
419 }
420 }
421
422 mutex_unlock(&dev->mode_config.mutex);
423
424out:
425 if (changed)
426 drm_kms_helper_hotplug_event(dev);
427
428 if (repoll)
429 schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD);
430}
431
432
433
434
435
436
437
438
439
440
441
442void drm_kms_helper_poll_disable(struct drm_device *dev)
443{
444 if (!dev->mode_config.poll_enabled)
445 return;
446 cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
447}
448EXPORT_SYMBOL(drm_kms_helper_poll_disable);
449
450
451
452
453
454
455
456
457
458
459
460void drm_kms_helper_poll_enable(struct drm_device *dev)
461{
462 mutex_lock(&dev->mode_config.mutex);
463 drm_kms_helper_poll_enable_locked(dev);
464 mutex_unlock(&dev->mode_config.mutex);
465}
466EXPORT_SYMBOL(drm_kms_helper_poll_enable);
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487void drm_kms_helper_poll_init(struct drm_device *dev)
488{
489 INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute);
490 dev->mode_config.poll_enabled = true;
491
492 drm_kms_helper_poll_enable(dev);
493}
494EXPORT_SYMBOL(drm_kms_helper_poll_init);
495
496
497
498
499
500void drm_kms_helper_poll_fini(struct drm_device *dev)
501{
502 drm_kms_helper_poll_disable(dev);
503}
504EXPORT_SYMBOL(drm_kms_helper_poll_fini);
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529bool drm_helper_hpd_irq_event(struct drm_device *dev)
530{
531 struct drm_connector *connector;
532 enum drm_connector_status old_status;
533 bool changed = false;
534
535 if (!dev->mode_config.poll_enabled)
536 return false;
537
538 mutex_lock(&dev->mode_config.mutex);
539 drm_for_each_connector(connector, dev) {
540
541
542 if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
543 continue;
544
545 old_status = connector->status;
546
547 connector->status = connector->funcs->detect(connector, false);
548 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
549 connector->base.id,
550 connector->name,
551 drm_get_connector_status_name(old_status),
552 drm_get_connector_status_name(connector->status));
553 if (old_status != connector->status)
554 changed = true;
555 }
556
557 mutex_unlock(&dev->mode_config.mutex);
558
559 if (changed)
560 drm_kms_helper_hotplug_event(dev);
561
562 return changed;
563}
564EXPORT_SYMBOL(drm_helper_hpd_irq_event);
565