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/kernel.h>
34#include <linux/moduleparam.h>
35
36#include <drm/drm_atomic.h>
37#include <drm/drm_atomic_helper.h>
38#include <drm/drm_atomic_uapi.h>
39#include <drm/drm_bridge.h>
40#include <drm/drm_crtc.h>
41#include <drm/drm_crtc_helper.h>
42#include <drm/drm_drv.h>
43#include <drm/drm_edid.h>
44#include <drm/drm_encoder.h>
45#include <drm/drm_fb_helper.h>
46#include <drm/drm_fourcc.h>
47#include <drm/drm_plane_helper.h>
48#include <drm/drm_print.h>
49#include <drm/drm_vblank.h>
50
51#include "drm_crtc_helper_internal.h"
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
96{
97 struct drm_connector *connector;
98 struct drm_connector_list_iter conn_iter;
99 struct drm_device *dev = encoder->dev;
100
101 WARN_ON(drm_drv_uses_atomic_modeset(dev));
102
103
104
105
106
107 if (!oops_in_progress) {
108 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
109 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
110 }
111
112
113 drm_connector_list_iter_begin(dev, &conn_iter);
114 drm_for_each_connector_iter(connector, &conn_iter) {
115 if (connector->encoder == encoder) {
116 drm_connector_list_iter_end(&conn_iter);
117 return true;
118 }
119 }
120 drm_connector_list_iter_end(&conn_iter);
121 return false;
122}
123EXPORT_SYMBOL(drm_helper_encoder_in_use);
124
125
126
127
128
129
130
131
132
133
134
135
136bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
137{
138 struct drm_encoder *encoder;
139 struct drm_device *dev = crtc->dev;
140
141 WARN_ON(drm_drv_uses_atomic_modeset(dev));
142
143
144
145
146
147 if (!oops_in_progress)
148 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
149
150 drm_for_each_encoder(encoder, dev)
151 if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))
152 return true;
153 return false;
154}
155EXPORT_SYMBOL(drm_helper_crtc_in_use);
156
157static void
158drm_encoder_disable(struct drm_encoder *encoder)
159{
160 const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
161
162 if (!encoder_funcs)
163 return;
164
165 if (encoder_funcs->disable)
166 (*encoder_funcs->disable)(encoder);
167 else if (encoder_funcs->dpms)
168 (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
169}
170
171static void __drm_helper_disable_unused_functions(struct drm_device *dev)
172{
173 struct drm_encoder *encoder;
174 struct drm_crtc *crtc;
175
176 drm_warn_on_modeset_not_all_locked(dev);
177
178 drm_for_each_encoder(encoder, dev) {
179 if (!drm_helper_encoder_in_use(encoder)) {
180 drm_encoder_disable(encoder);
181
182 encoder->crtc = NULL;
183 }
184 }
185
186 drm_for_each_crtc(crtc, dev) {
187 const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
188
189 crtc->enabled = drm_helper_crtc_in_use(crtc);
190 if (!crtc->enabled) {
191 if (crtc_funcs->disable)
192 (*crtc_funcs->disable)(crtc);
193 else
194 (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
195 crtc->primary->fb = NULL;
196 }
197 }
198}
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219void drm_helper_disable_unused_functions(struct drm_device *dev)
220{
221 WARN_ON(drm_drv_uses_atomic_modeset(dev));
222
223 drm_modeset_lock_all(dev);
224 __drm_helper_disable_unused_functions(dev);
225 drm_modeset_unlock_all(dev);
226}
227EXPORT_SYMBOL(drm_helper_disable_unused_functions);
228
229
230
231
232
233
234static void
235drm_crtc_prepare_encoders(struct drm_device *dev)
236{
237 const struct drm_encoder_helper_funcs *encoder_funcs;
238 struct drm_encoder *encoder;
239
240 drm_for_each_encoder(encoder, dev) {
241 encoder_funcs = encoder->helper_private;
242 if (!encoder_funcs)
243 continue;
244
245
246 if (encoder->crtc == NULL)
247 drm_encoder_disable(encoder);
248 }
249}
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
272 struct drm_display_mode *mode,
273 int x, int y,
274 struct drm_framebuffer *old_fb)
275{
276 struct drm_device *dev = crtc->dev;
277 struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
278 const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
279 const struct drm_encoder_helper_funcs *encoder_funcs;
280 int saved_x, saved_y;
281 bool saved_enabled;
282 struct drm_encoder *encoder;
283 bool ret = true;
284
285 WARN_ON(drm_drv_uses_atomic_modeset(dev));
286
287 drm_warn_on_modeset_not_all_locked(dev);
288
289 saved_enabled = crtc->enabled;
290 crtc->enabled = drm_helper_crtc_in_use(crtc);
291 if (!crtc->enabled)
292 return true;
293
294 adjusted_mode = drm_mode_duplicate(dev, mode);
295 if (!adjusted_mode) {
296 crtc->enabled = saved_enabled;
297 return false;
298 }
299
300 saved_mode = crtc->mode;
301 saved_hwmode = crtc->hwmode;
302 saved_x = crtc->x;
303 saved_y = crtc->y;
304
305
306
307
308 crtc->mode = *mode;
309 crtc->x = x;
310 crtc->y = y;
311
312
313
314
315
316 drm_for_each_encoder(encoder, dev) {
317
318 if (encoder->crtc != crtc)
319 continue;
320
321 encoder_funcs = encoder->helper_private;
322 if (!encoder_funcs)
323 continue;
324
325 encoder_funcs = encoder->helper_private;
326 if (encoder_funcs->mode_fixup) {
327 if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
328 adjusted_mode))) {
329 DRM_DEBUG_KMS("Encoder fixup failed\n");
330 goto done;
331 }
332 }
333 }
334
335 if (crtc_funcs->mode_fixup) {
336 if (!(ret = crtc_funcs->mode_fixup(crtc, mode,
337 adjusted_mode))) {
338 DRM_DEBUG_KMS("CRTC fixup failed\n");
339 goto done;
340 }
341 }
342 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
343
344 crtc->hwmode = *adjusted_mode;
345
346
347 drm_for_each_encoder(encoder, dev) {
348
349 if (encoder->crtc != crtc)
350 continue;
351
352 encoder_funcs = encoder->helper_private;
353 if (!encoder_funcs)
354 continue;
355
356
357 if (encoder_funcs->prepare)
358 encoder_funcs->prepare(encoder);
359 }
360
361 drm_crtc_prepare_encoders(dev);
362
363 crtc_funcs->prepare(crtc);
364
365
366
367
368 ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
369 if (!ret)
370 goto done;
371
372 drm_for_each_encoder(encoder, dev) {
373
374 if (encoder->crtc != crtc)
375 continue;
376
377 encoder_funcs = encoder->helper_private;
378 if (!encoder_funcs)
379 continue;
380
381 DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%s]\n",
382 encoder->base.id, encoder->name, mode->name);
383 if (encoder_funcs->mode_set)
384 encoder_funcs->mode_set(encoder, mode, adjusted_mode);
385 }
386
387
388 crtc_funcs->commit(crtc);
389
390 drm_for_each_encoder(encoder, dev) {
391
392 if (encoder->crtc != crtc)
393 continue;
394
395 encoder_funcs = encoder->helper_private;
396 if (!encoder_funcs)
397 continue;
398
399 if (encoder_funcs->commit)
400 encoder_funcs->commit(encoder);
401 }
402
403
404
405
406
407 drm_calc_timestamping_constants(crtc, &crtc->hwmode);
408
409
410done:
411 drm_mode_destroy(dev, adjusted_mode);
412 if (!ret) {
413 crtc->enabled = saved_enabled;
414 crtc->mode = saved_mode;
415 crtc->hwmode = saved_hwmode;
416 crtc->x = saved_x;
417 crtc->y = saved_y;
418 }
419
420 return ret;
421}
422EXPORT_SYMBOL(drm_crtc_helper_set_mode);
423
424static void
425drm_crtc_helper_disable(struct drm_crtc *crtc)
426{
427 struct drm_device *dev = crtc->dev;
428 struct drm_connector *connector;
429 struct drm_encoder *encoder;
430
431
432 drm_for_each_encoder(encoder, dev) {
433 struct drm_connector_list_iter conn_iter;
434
435 if (encoder->crtc != crtc)
436 continue;
437
438 drm_connector_list_iter_begin(dev, &conn_iter);
439 drm_for_each_connector_iter(connector, &conn_iter) {
440 if (connector->encoder != encoder)
441 continue;
442
443 connector->encoder = NULL;
444
445
446
447
448
449
450
451 connector->dpms = DRM_MODE_DPMS_OFF;
452
453
454 drm_connector_put(connector);
455 }
456 drm_connector_list_iter_end(&conn_iter);
457 }
458
459 __drm_helper_disable_unused_functions(dev);
460}
461
462
463
464
465
466struct drm_encoder *
467drm_connector_get_single_encoder(struct drm_connector *connector)
468{
469 struct drm_encoder *encoder;
470
471 WARN_ON(hweight32(connector->possible_encoders) > 1);
472 drm_connector_for_each_possible_encoder(connector, encoder)
473 return encoder;
474
475 return NULL;
476}
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516int drm_crtc_helper_set_config(struct drm_mode_set *set,
517 struct drm_modeset_acquire_ctx *ctx)
518{
519 struct drm_device *dev;
520 struct drm_crtc **save_encoder_crtcs, *new_crtc;
521 struct drm_encoder **save_connector_encoders, *new_encoder, *encoder;
522 bool mode_changed = false;
523 bool fb_changed = false;
524 struct drm_connector *connector;
525 struct drm_connector_list_iter conn_iter;
526 int count = 0, ro, fail = 0;
527 const struct drm_crtc_helper_funcs *crtc_funcs;
528 struct drm_mode_set save_set;
529 int ret;
530 int i;
531
532 DRM_DEBUG_KMS("\n");
533
534 BUG_ON(!set);
535 BUG_ON(!set->crtc);
536 BUG_ON(!set->crtc->helper_private);
537
538
539 BUG_ON(!set->mode && set->fb);
540 BUG_ON(set->fb && set->num_connectors == 0);
541
542 crtc_funcs = set->crtc->helper_private;
543
544 dev = set->crtc->dev;
545 WARN_ON(drm_drv_uses_atomic_modeset(dev));
546
547 if (!set->mode)
548 set->fb = NULL;
549
550 if (set->fb) {
551 DRM_DEBUG_KMS("[CRTC:%d:%s] [FB:%d] #connectors=%d (x y) (%i %i)\n",
552 set->crtc->base.id, set->crtc->name,
553 set->fb->base.id,
554 (int)set->num_connectors, set->x, set->y);
555 } else {
556 DRM_DEBUG_KMS("[CRTC:%d:%s] [NOFB]\n",
557 set->crtc->base.id, set->crtc->name);
558 drm_crtc_helper_disable(set->crtc);
559 return 0;
560 }
561
562 drm_warn_on_modeset_not_all_locked(dev);
563
564
565
566
567
568 save_encoder_crtcs = kcalloc(dev->mode_config.num_encoder,
569 sizeof(struct drm_crtc *), GFP_KERNEL);
570 if (!save_encoder_crtcs)
571 return -ENOMEM;
572
573 save_connector_encoders = kcalloc(dev->mode_config.num_connector,
574 sizeof(struct drm_encoder *), GFP_KERNEL);
575 if (!save_connector_encoders) {
576 kfree(save_encoder_crtcs);
577 return -ENOMEM;
578 }
579
580
581
582
583
584
585 count = 0;
586 drm_for_each_encoder(encoder, dev) {
587 save_encoder_crtcs[count++] = encoder->crtc;
588 }
589
590 count = 0;
591 drm_connector_list_iter_begin(dev, &conn_iter);
592 drm_for_each_connector_iter(connector, &conn_iter)
593 save_connector_encoders[count++] = connector->encoder;
594 drm_connector_list_iter_end(&conn_iter);
595
596 save_set.crtc = set->crtc;
597 save_set.mode = &set->crtc->mode;
598 save_set.x = set->crtc->x;
599 save_set.y = set->crtc->y;
600 save_set.fb = set->crtc->primary->fb;
601
602
603
604 if (set->crtc->primary->fb != set->fb) {
605
606 if (set->crtc->primary->fb == NULL) {
607 DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
608 mode_changed = true;
609 } else if (set->fb->format != set->crtc->primary->fb->format) {
610 mode_changed = true;
611 } else
612 fb_changed = true;
613 }
614
615 if (set->x != set->crtc->x || set->y != set->crtc->y)
616 fb_changed = true;
617
618 if (!drm_mode_equal(set->mode, &set->crtc->mode)) {
619 DRM_DEBUG_KMS("modes are different, full mode set\n");
620 drm_mode_debug_printmodeline(&set->crtc->mode);
621 drm_mode_debug_printmodeline(set->mode);
622 mode_changed = true;
623 }
624
625
626
627
628 for (ro = 0; ro < set->num_connectors; ro++) {
629 if (set->connectors[ro]->encoder)
630 continue;
631 drm_connector_get(set->connectors[ro]);
632 }
633
634
635 count = 0;
636 drm_connector_list_iter_begin(dev, &conn_iter);
637 drm_for_each_connector_iter(connector, &conn_iter) {
638 const struct drm_connector_helper_funcs *connector_funcs =
639 connector->helper_private;
640 new_encoder = connector->encoder;
641 for (ro = 0; ro < set->num_connectors; ro++) {
642 if (set->connectors[ro] == connector) {
643 if (connector_funcs->best_encoder)
644 new_encoder = connector_funcs->best_encoder(connector);
645 else
646 new_encoder = drm_connector_get_single_encoder(connector);
647
648
649
650 if (new_encoder == NULL)
651
652 fail = 1;
653
654 if (connector->dpms != DRM_MODE_DPMS_ON) {
655 DRM_DEBUG_KMS("connector dpms not on, full mode switch\n");
656 mode_changed = true;
657 }
658
659 break;
660 }
661 }
662
663 if (new_encoder != connector->encoder) {
664 DRM_DEBUG_KMS("encoder changed, full mode switch\n");
665 mode_changed = true;
666
667
668
669 if (connector->encoder)
670 connector->encoder->crtc = NULL;
671 connector->encoder = new_encoder;
672 }
673 }
674 drm_connector_list_iter_end(&conn_iter);
675
676 if (fail) {
677 ret = -EINVAL;
678 goto fail;
679 }
680
681 count = 0;
682 drm_connector_list_iter_begin(dev, &conn_iter);
683 drm_for_each_connector_iter(connector, &conn_iter) {
684 if (!connector->encoder)
685 continue;
686
687 if (connector->encoder->crtc == set->crtc)
688 new_crtc = NULL;
689 else
690 new_crtc = connector->encoder->crtc;
691
692 for (ro = 0; ro < set->num_connectors; ro++) {
693 if (set->connectors[ro] == connector)
694 new_crtc = set->crtc;
695 }
696
697
698 if (new_crtc &&
699 !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
700 ret = -EINVAL;
701 drm_connector_list_iter_end(&conn_iter);
702 goto fail;
703 }
704 if (new_crtc != connector->encoder->crtc) {
705 DRM_DEBUG_KMS("crtc changed, full mode switch\n");
706 mode_changed = true;
707 connector->encoder->crtc = new_crtc;
708 }
709 if (new_crtc) {
710 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d:%s]\n",
711 connector->base.id, connector->name,
712 new_crtc->base.id, new_crtc->name);
713 } else {
714 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
715 connector->base.id, connector->name);
716 }
717 }
718 drm_connector_list_iter_end(&conn_iter);
719
720
721 if (fb_changed && !crtc_funcs->mode_set_base)
722 mode_changed = true;
723
724 if (mode_changed) {
725 if (drm_helper_crtc_in_use(set->crtc)) {
726 DRM_DEBUG_KMS("attempting to set mode from"
727 " userspace\n");
728 drm_mode_debug_printmodeline(set->mode);
729 set->crtc->primary->fb = set->fb;
730 if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
731 set->x, set->y,
732 save_set.fb)) {
733 DRM_ERROR("failed to set mode on [CRTC:%d:%s]\n",
734 set->crtc->base.id, set->crtc->name);
735 set->crtc->primary->fb = save_set.fb;
736 ret = -EINVAL;
737 goto fail;
738 }
739 DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
740 for (i = 0; i < set->num_connectors; i++) {
741 DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
742 set->connectors[i]->name);
743 set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
744 }
745 }
746 __drm_helper_disable_unused_functions(dev);
747 } else if (fb_changed) {
748 set->crtc->x = set->x;
749 set->crtc->y = set->y;
750 set->crtc->primary->fb = set->fb;
751 ret = crtc_funcs->mode_set_base(set->crtc,
752 set->x, set->y, save_set.fb);
753 if (ret != 0) {
754 set->crtc->x = save_set.x;
755 set->crtc->y = save_set.y;
756 set->crtc->primary->fb = save_set.fb;
757 goto fail;
758 }
759 }
760
761 kfree(save_connector_encoders);
762 kfree(save_encoder_crtcs);
763 return 0;
764
765fail:
766
767 count = 0;
768 drm_for_each_encoder(encoder, dev) {
769 encoder->crtc = save_encoder_crtcs[count++];
770 }
771
772 count = 0;
773 drm_connector_list_iter_begin(dev, &conn_iter);
774 drm_for_each_connector_iter(connector, &conn_iter)
775 connector->encoder = save_connector_encoders[count++];
776 drm_connector_list_iter_end(&conn_iter);
777
778
779
780
781 for (ro = 0; ro < set->num_connectors; ro++) {
782 if (set->connectors[ro]->encoder)
783 continue;
784 drm_connector_put(set->connectors[ro]);
785 }
786
787
788 if (mode_changed &&
789 !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
790 save_set.y, save_set.fb))
791 DRM_ERROR("failed to restore config after modeset failure\n");
792
793 kfree(save_connector_encoders);
794 kfree(save_encoder_crtcs);
795 return ret;
796}
797EXPORT_SYMBOL(drm_crtc_helper_set_config);
798
799static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
800{
801 int dpms = DRM_MODE_DPMS_OFF;
802 struct drm_connector *connector;
803 struct drm_connector_list_iter conn_iter;
804 struct drm_device *dev = encoder->dev;
805
806 drm_connector_list_iter_begin(dev, &conn_iter);
807 drm_for_each_connector_iter(connector, &conn_iter)
808 if (connector->encoder == encoder)
809 if (connector->dpms < dpms)
810 dpms = connector->dpms;
811 drm_connector_list_iter_end(&conn_iter);
812
813 return dpms;
814}
815
816
817static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode)
818{
819 const struct drm_encoder_helper_funcs *encoder_funcs;
820
821 encoder_funcs = encoder->helper_private;
822 if (!encoder_funcs)
823 return;
824
825 if (encoder_funcs->dpms)
826 encoder_funcs->dpms(encoder, mode);
827}
828
829static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
830{
831 int dpms = DRM_MODE_DPMS_OFF;
832 struct drm_connector *connector;
833 struct drm_connector_list_iter conn_iter;
834 struct drm_device *dev = crtc->dev;
835
836 drm_connector_list_iter_begin(dev, &conn_iter);
837 drm_for_each_connector_iter(connector, &conn_iter)
838 if (connector->encoder && connector->encoder->crtc == crtc)
839 if (connector->dpms < dpms)
840 dpms = connector->dpms;
841 drm_connector_list_iter_end(&conn_iter);
842
843 return dpms;
844}
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867int drm_helper_connector_dpms(struct drm_connector *connector, int mode)
868{
869 struct drm_encoder *encoder = connector->encoder;
870 struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
871 int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF;
872
873 WARN_ON(drm_drv_uses_atomic_modeset(connector->dev));
874
875 if (mode == connector->dpms)
876 return 0;
877
878 old_dpms = connector->dpms;
879 connector->dpms = mode;
880
881 if (encoder)
882 encoder_dpms = drm_helper_choose_encoder_dpms(encoder);
883
884
885 if (mode < old_dpms) {
886 if (crtc) {
887 const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
888
889 if (crtc_funcs->dpms)
890 (*crtc_funcs->dpms) (crtc,
891 drm_helper_choose_crtc_dpms(crtc));
892 }
893 if (encoder)
894 drm_helper_encoder_dpms(encoder, encoder_dpms);
895 }
896
897
898 if (mode > old_dpms) {
899 if (encoder)
900 drm_helper_encoder_dpms(encoder, encoder_dpms);
901 if (crtc) {
902 const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
903
904 if (crtc_funcs->dpms)
905 (*crtc_funcs->dpms) (crtc,
906 drm_helper_choose_crtc_dpms(crtc));
907 }
908 }
909
910 return 0;
911}
912EXPORT_SYMBOL(drm_helper_connector_dpms);
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
940void drm_helper_resume_force_mode(struct drm_device *dev)
941{
942 struct drm_crtc *crtc;
943 struct drm_encoder *encoder;
944 const struct drm_crtc_helper_funcs *crtc_funcs;
945 int encoder_dpms;
946 bool ret;
947
948 WARN_ON(drm_drv_uses_atomic_modeset(dev));
949
950 drm_modeset_lock_all(dev);
951 drm_for_each_crtc(crtc, dev) {
952
953 if (!crtc->enabled)
954 continue;
955
956 ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
957 crtc->x, crtc->y, crtc->primary->fb);
958
959
960 if (ret == false)
961 DRM_ERROR("failed to set mode on crtc %p\n", crtc);
962
963
964 if (drm_helper_choose_crtc_dpms(crtc)) {
965 drm_for_each_encoder(encoder, dev) {
966
967 if(encoder->crtc != crtc)
968 continue;
969
970 encoder_dpms = drm_helper_choose_encoder_dpms(
971 encoder);
972
973 drm_helper_encoder_dpms(encoder, encoder_dpms);
974 }
975
976 crtc_funcs = crtc->helper_private;
977 if (crtc_funcs->dpms)
978 (*crtc_funcs->dpms) (crtc,
979 drm_helper_choose_crtc_dpms(crtc));
980 }
981 }
982
983
984 __drm_helper_disable_unused_functions(dev);
985 drm_modeset_unlock_all(dev);
986}
987EXPORT_SYMBOL(drm_helper_resume_force_mode);
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002int drm_helper_force_disable_all(struct drm_device *dev)
1003{
1004 struct drm_crtc *crtc;
1005 int ret = 0;
1006
1007 drm_modeset_lock_all(dev);
1008 drm_for_each_crtc(crtc, dev)
1009 if (crtc->enabled) {
1010 struct drm_mode_set set = {
1011 .crtc = crtc,
1012 };
1013
1014 ret = drm_mode_set_config_internal(&set);
1015 if (ret)
1016 goto out;
1017 }
1018out:
1019 drm_modeset_unlock_all(dev);
1020 return ret;
1021}
1022EXPORT_SYMBOL(drm_helper_force_disable_all);
1023