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#include <drm/drmP.h>
29#include <drm/drm_atomic.h>
30#include <drm/drm_plane_helper.h>
31#include <drm/drm_crtc_helper.h>
32#include <drm/drm_atomic_helper.h>
33#include <linux/fence.h>
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56static void
57drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
58 struct drm_plane_state *plane_state,
59 struct drm_plane *plane)
60{
61 struct drm_crtc_state *crtc_state;
62
63 if (plane->state->crtc) {
64 crtc_state = state->crtc_states[drm_crtc_index(plane->state->crtc)];
65
66 if (WARN_ON(!crtc_state))
67 return;
68
69 crtc_state->planes_changed = true;
70 }
71
72 if (plane_state->crtc) {
73 crtc_state =
74 state->crtc_states[drm_crtc_index(plane_state->crtc)];
75
76 if (WARN_ON(!crtc_state))
77 return;
78
79 crtc_state->planes_changed = true;
80 }
81}
82
83static struct drm_crtc *
84get_current_crtc_for_encoder(struct drm_device *dev,
85 struct drm_encoder *encoder)
86{
87 struct drm_mode_config *config = &dev->mode_config;
88 struct drm_connector *connector;
89
90 WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
91
92 list_for_each_entry(connector, &config->connector_list, head) {
93 if (connector->state->best_encoder != encoder)
94 continue;
95
96 return connector->state->crtc;
97 }
98
99 return NULL;
100}
101
102static int
103steal_encoder(struct drm_atomic_state *state,
104 struct drm_encoder *encoder,
105 struct drm_crtc *encoder_crtc)
106{
107 struct drm_mode_config *config = &state->dev->mode_config;
108 struct drm_crtc_state *crtc_state;
109 struct drm_connector *connector;
110 struct drm_connector_state *connector_state;
111 int ret;
112
113
114
115
116
117 WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
118
119 DRM_DEBUG_KMS("[ENCODER:%d:%s] in use on [CRTC:%d], stealing it\n",
120 encoder->base.id, encoder->name,
121 encoder_crtc->base.id);
122
123 crtc_state = drm_atomic_get_crtc_state(state, encoder_crtc);
124 if (IS_ERR(crtc_state))
125 return PTR_ERR(crtc_state);
126
127 crtc_state->mode_changed = true;
128
129 list_for_each_entry(connector, &config->connector_list, head) {
130 if (connector->state->best_encoder != encoder)
131 continue;
132
133 DRM_DEBUG_KMS("Stealing encoder from [CONNECTOR:%d:%s]\n",
134 connector->base.id,
135 connector->name);
136
137 connector_state = drm_atomic_get_connector_state(state,
138 connector);
139 if (IS_ERR(connector_state))
140 return PTR_ERR(connector_state);
141
142 ret = drm_atomic_set_crtc_for_connector(connector_state, NULL);
143 if (ret)
144 return ret;
145 connector_state->best_encoder = NULL;
146 }
147
148 return 0;
149}
150
151static int
152update_connector_routing(struct drm_atomic_state *state, int conn_idx)
153{
154 struct drm_connector_helper_funcs *funcs;
155 struct drm_encoder *new_encoder;
156 struct drm_crtc *encoder_crtc;
157 struct drm_connector *connector;
158 struct drm_connector_state *connector_state;
159 struct drm_crtc_state *crtc_state;
160 int idx, ret;
161
162 connector = state->connectors[conn_idx];
163 connector_state = state->connector_states[conn_idx];
164
165 if (!connector)
166 return 0;
167
168 DRM_DEBUG_KMS("Updating routing for [CONNECTOR:%d:%s]\n",
169 connector->base.id,
170 connector->name);
171
172 if (connector->state->crtc != connector_state->crtc) {
173 if (connector->state->crtc) {
174 idx = drm_crtc_index(connector->state->crtc);
175
176 crtc_state = state->crtc_states[idx];
177 crtc_state->mode_changed = true;
178 }
179
180 if (connector_state->crtc) {
181 idx = drm_crtc_index(connector_state->crtc);
182
183 crtc_state = state->crtc_states[idx];
184 crtc_state->mode_changed = true;
185 }
186 }
187
188 if (!connector_state->crtc) {
189 DRM_DEBUG_KMS("Disabling [CONNECTOR:%d:%s]\n",
190 connector->base.id,
191 connector->name);
192
193 connector_state->best_encoder = NULL;
194
195 return 0;
196 }
197
198 funcs = connector->helper_private;
199 new_encoder = funcs->best_encoder(connector);
200
201 if (!new_encoder) {
202 DRM_DEBUG_KMS("No suitable encoder found for [CONNECTOR:%d:%s]\n",
203 connector->base.id,
204 connector->name);
205 return -EINVAL;
206 }
207
208 if (new_encoder == connector_state->best_encoder) {
209 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d]\n",
210 connector->base.id,
211 connector->name,
212 new_encoder->base.id,
213 new_encoder->name,
214 connector_state->crtc->base.id);
215
216 return 0;
217 }
218
219 encoder_crtc = get_current_crtc_for_encoder(state->dev,
220 new_encoder);
221
222 if (encoder_crtc) {
223 ret = steal_encoder(state, new_encoder, encoder_crtc);
224 if (ret) {
225 DRM_DEBUG_KMS("Encoder stealing failed for [CONNECTOR:%d:%s]\n",
226 connector->base.id,
227 connector->name);
228 return ret;
229 }
230 }
231
232 connector_state->best_encoder = new_encoder;
233 idx = drm_crtc_index(connector_state->crtc);
234
235 crtc_state = state->crtc_states[idx];
236 crtc_state->mode_changed = true;
237
238 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d]\n",
239 connector->base.id,
240 connector->name,
241 new_encoder->base.id,
242 new_encoder->name,
243 connector_state->crtc->base.id);
244
245 return 0;
246}
247
248static int
249mode_fixup(struct drm_atomic_state *state)
250{
251 int ncrtcs = state->dev->mode_config.num_crtc;
252 struct drm_crtc_state *crtc_state;
253 struct drm_connector_state *conn_state;
254 int i;
255 bool ret;
256
257 for (i = 0; i < ncrtcs; i++) {
258 crtc_state = state->crtc_states[i];
259
260 if (!crtc_state || !crtc_state->mode_changed)
261 continue;
262
263 drm_mode_copy(&crtc_state->adjusted_mode, &crtc_state->mode);
264 }
265
266 for (i = 0; i < state->num_connector; i++) {
267 struct drm_encoder_helper_funcs *funcs;
268 struct drm_encoder *encoder;
269
270 conn_state = state->connector_states[i];
271
272 if (!conn_state)
273 continue;
274
275 WARN_ON(!!conn_state->best_encoder != !!conn_state->crtc);
276
277 if (!conn_state->crtc || !conn_state->best_encoder)
278 continue;
279
280 crtc_state =
281 state->crtc_states[drm_crtc_index(conn_state->crtc)];
282
283
284
285
286
287 encoder = conn_state->best_encoder;
288 funcs = encoder->helper_private;
289
290 if (encoder->bridge && encoder->bridge->funcs->mode_fixup) {
291 ret = encoder->bridge->funcs->mode_fixup(
292 encoder->bridge, &crtc_state->mode,
293 &crtc_state->adjusted_mode);
294 if (!ret) {
295 DRM_DEBUG_KMS("Bridge fixup failed\n");
296 return -EINVAL;
297 }
298 }
299
300
301 ret = funcs->mode_fixup(encoder, &crtc_state->mode,
302 &crtc_state->adjusted_mode);
303 if (!ret) {
304 DRM_DEBUG_KMS("[ENCODER:%d:%s] fixup failed\n",
305 encoder->base.id, encoder->name);
306 return -EINVAL;
307 }
308 }
309
310 for (i = 0; i < ncrtcs; i++) {
311 struct drm_crtc_helper_funcs *funcs;
312 struct drm_crtc *crtc;
313
314 crtc_state = state->crtc_states[i];
315 crtc = state->crtcs[i];
316
317 if (!crtc_state || !crtc_state->mode_changed)
318 continue;
319
320 funcs = crtc->helper_private;
321 ret = funcs->mode_fixup(crtc, &crtc_state->mode,
322 &crtc_state->adjusted_mode);
323 if (!ret) {
324 DRM_DEBUG_KMS("[CRTC:%d] fixup failed\n",
325 crtc->base.id);
326 return -EINVAL;
327 }
328 }
329
330 return 0;
331}
332
333static int
334drm_atomic_helper_check_modeset(struct drm_device *dev,
335 struct drm_atomic_state *state)
336{
337 int ncrtcs = dev->mode_config.num_crtc;
338 struct drm_crtc *crtc;
339 struct drm_crtc_state *crtc_state;
340 int i, ret;
341
342 for (i = 0; i < ncrtcs; i++) {
343 crtc = state->crtcs[i];
344 crtc_state = state->crtc_states[i];
345
346 if (!crtc)
347 continue;
348
349 if (!drm_mode_equal(&crtc->state->mode, &crtc_state->mode)) {
350 DRM_DEBUG_KMS("[CRTC:%d] mode changed\n",
351 crtc->base.id);
352 crtc_state->mode_changed = true;
353 }
354
355 if (crtc->state->enable != crtc_state->enable) {
356 DRM_DEBUG_KMS("[CRTC:%d] enable changed\n",
357 crtc->base.id);
358 crtc_state->mode_changed = true;
359 }
360 }
361
362 for (i = 0; i < state->num_connector; i++) {
363
364
365
366
367
368 ret = update_connector_routing(state, i);
369 if (ret)
370 return ret;
371 }
372
373
374
375
376
377
378
379 for (i = 0; i < ncrtcs; i++) {
380 int num_connectors;
381
382 crtc = state->crtcs[i];
383 crtc_state = state->crtc_states[i];
384
385 if (!crtc || !crtc_state->mode_changed)
386 continue;
387
388 DRM_DEBUG_KMS("[CRTC:%d] needs full modeset, enable: %c\n",
389 crtc->base.id,
390 crtc_state->enable ? 'y' : 'n');
391
392 ret = drm_atomic_add_affected_connectors(state, crtc);
393 if (ret != 0)
394 return ret;
395
396 num_connectors = drm_atomic_connectors_for_crtc(state,
397 crtc);
398
399 if (crtc_state->enable != !!num_connectors) {
400 DRM_DEBUG_KMS("[CRTC:%d] enabled/connectors mismatch\n",
401 crtc->base.id);
402
403 return -EINVAL;
404 }
405 }
406
407 return mode_fixup(state);
408}
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424int drm_atomic_helper_check(struct drm_device *dev,
425 struct drm_atomic_state *state)
426{
427 int nplanes = dev->mode_config.num_total_plane;
428 int ncrtcs = dev->mode_config.num_crtc;
429 int i, ret = 0;
430
431 for (i = 0; i < nplanes; i++) {
432 struct drm_plane_helper_funcs *funcs;
433 struct drm_plane *plane = state->planes[i];
434 struct drm_plane_state *plane_state = state->plane_states[i];
435
436 if (!plane)
437 continue;
438
439 funcs = plane->helper_private;
440
441 drm_atomic_helper_plane_changed(state, plane_state, plane);
442
443 if (!funcs || !funcs->atomic_check)
444 continue;
445
446 ret = funcs->atomic_check(plane, plane_state);
447 if (ret) {
448 DRM_DEBUG_KMS("[PLANE:%d] atomic check failed\n",
449 plane->base.id);
450 return ret;
451 }
452 }
453
454 for (i = 0; i < ncrtcs; i++) {
455 struct drm_crtc_helper_funcs *funcs;
456 struct drm_crtc *crtc = state->crtcs[i];
457
458 if (!crtc)
459 continue;
460
461 funcs = crtc->helper_private;
462
463 if (!funcs || !funcs->atomic_check)
464 continue;
465
466 ret = funcs->atomic_check(crtc, state->crtc_states[i]);
467 if (ret) {
468 DRM_DEBUG_KMS("[CRTC:%d] atomic check failed\n",
469 crtc->base.id);
470 return ret;
471 }
472 }
473
474 ret = drm_atomic_helper_check_modeset(dev, state);
475 if (ret)
476 return ret;
477
478 return ret;
479}
480EXPORT_SYMBOL(drm_atomic_helper_check);
481
482static void
483disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
484{
485 int ncrtcs = old_state->dev->mode_config.num_crtc;
486 int i;
487
488 for (i = 0; i < old_state->num_connector; i++) {
489 struct drm_connector_state *old_conn_state;
490 struct drm_connector *connector;
491 struct drm_encoder_helper_funcs *funcs;
492 struct drm_encoder *encoder;
493
494 old_conn_state = old_state->connector_states[i];
495 connector = old_state->connectors[i];
496
497
498
499 if (!old_conn_state || !old_conn_state->crtc)
500 continue;
501
502 encoder = old_conn_state->best_encoder;
503
504
505
506
507 if (WARN_ON(!encoder))
508 continue;
509
510 funcs = encoder->helper_private;
511
512
513
514
515
516 if (encoder->bridge)
517 encoder->bridge->funcs->disable(encoder->bridge);
518
519
520 if (connector->state->crtc)
521 funcs->prepare(encoder);
522 else if (funcs->disable)
523 funcs->disable(encoder);
524 else
525 funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
526
527 if (encoder->bridge)
528 encoder->bridge->funcs->post_disable(encoder->bridge);
529 }
530
531 for (i = 0; i < ncrtcs; i++) {
532 struct drm_crtc_helper_funcs *funcs;
533 struct drm_crtc *crtc;
534
535 crtc = old_state->crtcs[i];
536
537
538 if (!crtc || !crtc->state->mode_changed)
539 continue;
540
541 funcs = crtc->helper_private;
542
543
544 if (crtc->state->enable)
545 funcs->prepare(crtc);
546 else if (funcs->disable)
547 funcs->disable(crtc);
548 else
549 funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
550 }
551}
552
553static void
554set_routing_links(struct drm_device *dev, struct drm_atomic_state *old_state)
555{
556 int ncrtcs = old_state->dev->mode_config.num_crtc;
557 int i;
558
559
560 for (i = 0; i < old_state->num_connector; i++) {
561 struct drm_connector *connector;
562
563 connector = old_state->connectors[i];
564
565 if (!connector || !connector->encoder)
566 continue;
567
568 WARN_ON(!connector->encoder->crtc);
569
570 connector->encoder->crtc = NULL;
571 connector->encoder = NULL;
572 }
573
574
575 for (i = 0; i < old_state->num_connector; i++) {
576 struct drm_connector *connector;
577
578 connector = old_state->connectors[i];
579
580 if (!connector || !connector->state->crtc)
581 continue;
582
583 if (WARN_ON(!connector->state->best_encoder))
584 continue;
585
586 connector->encoder = connector->state->best_encoder;
587 connector->encoder->crtc = connector->state->crtc;
588 }
589
590
591 for (i = 0; i < ncrtcs; i++) {
592 struct drm_crtc *crtc;
593
594 crtc = old_state->crtcs[i];
595
596 if (!crtc)
597 continue;
598
599 crtc->mode = crtc->state->mode;
600 crtc->enabled = crtc->state->enable;
601 crtc->x = crtc->primary->state->src_x >> 16;
602 crtc->y = crtc->primary->state->src_y >> 16;
603 }
604}
605
606static void
607crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
608{
609 int ncrtcs = old_state->dev->mode_config.num_crtc;
610 int i;
611
612 for (i = 0; i < ncrtcs; i++) {
613 struct drm_crtc_helper_funcs *funcs;
614 struct drm_crtc *crtc;
615
616 crtc = old_state->crtcs[i];
617
618 if (!crtc || !crtc->state->mode_changed)
619 continue;
620
621 funcs = crtc->helper_private;
622
623 if (crtc->state->enable)
624 funcs->mode_set_nofb(crtc);
625 }
626
627 for (i = 0; i < old_state->num_connector; i++) {
628 struct drm_connector *connector;
629 struct drm_crtc_state *new_crtc_state;
630 struct drm_encoder_helper_funcs *funcs;
631 struct drm_encoder *encoder;
632 struct drm_display_mode *mode, *adjusted_mode;
633
634 connector = old_state->connectors[i];
635
636 if (!connector || !connector->state->best_encoder)
637 continue;
638
639 encoder = connector->state->best_encoder;
640 funcs = encoder->helper_private;
641 new_crtc_state = connector->state->crtc->state;
642 mode = &new_crtc_state->mode;
643 adjusted_mode = &new_crtc_state->adjusted_mode;
644
645
646
647
648
649 funcs->mode_set(encoder, mode, adjusted_mode);
650
651 if (encoder->bridge && encoder->bridge->funcs->mode_set)
652 encoder->bridge->funcs->mode_set(encoder->bridge,
653 mode, adjusted_mode);
654 }
655}
656
657
658
659
660
661
662
663
664
665
666void drm_atomic_helper_commit_pre_planes(struct drm_device *dev,
667 struct drm_atomic_state *state)
668{
669 disable_outputs(dev, state);
670 set_routing_links(dev, state);
671 crtc_set_mode(dev, state);
672}
673EXPORT_SYMBOL(drm_atomic_helper_commit_pre_planes);
674
675
676
677
678
679
680
681
682
683
684void drm_atomic_helper_commit_post_planes(struct drm_device *dev,
685 struct drm_atomic_state *old_state)
686{
687 int ncrtcs = old_state->dev->mode_config.num_crtc;
688 int i;
689
690 for (i = 0; i < ncrtcs; i++) {
691 struct drm_crtc_helper_funcs *funcs;
692 struct drm_crtc *crtc;
693
694 crtc = old_state->crtcs[i];
695
696
697 if (!crtc || !crtc->state->mode_changed)
698 continue;
699
700 funcs = crtc->helper_private;
701
702 if (crtc->state->enable)
703 funcs->commit(crtc);
704 }
705
706 for (i = 0; i < old_state->num_connector; i++) {
707 struct drm_connector *connector;
708 struct drm_encoder_helper_funcs *funcs;
709 struct drm_encoder *encoder;
710
711 connector = old_state->connectors[i];
712
713 if (!connector || !connector->state->best_encoder)
714 continue;
715
716 encoder = connector->state->best_encoder;
717 funcs = encoder->helper_private;
718
719
720
721
722
723 if (encoder->bridge)
724 encoder->bridge->funcs->pre_enable(encoder->bridge);
725
726 funcs->commit(encoder);
727
728 if (encoder->bridge)
729 encoder->bridge->funcs->enable(encoder->bridge);
730 }
731}
732EXPORT_SYMBOL(drm_atomic_helper_commit_post_planes);
733
734static void wait_for_fences(struct drm_device *dev,
735 struct drm_atomic_state *state)
736{
737 int nplanes = dev->mode_config.num_total_plane;
738 int i;
739
740 for (i = 0; i < nplanes; i++) {
741 struct drm_plane *plane = state->planes[i];
742
743 if (!plane || !plane->state->fence)
744 continue;
745
746 WARN_ON(!plane->state->fb);
747
748 fence_wait(plane->state->fence, false);
749 fence_put(plane->state->fence);
750 plane->state->fence = NULL;
751 }
752}
753
754static bool framebuffer_changed(struct drm_device *dev,
755 struct drm_atomic_state *old_state,
756 struct drm_crtc *crtc)
757{
758 struct drm_plane *plane;
759 struct drm_plane_state *old_plane_state;
760 int nplanes = old_state->dev->mode_config.num_total_plane;
761 int i;
762
763 for (i = 0; i < nplanes; i++) {
764 plane = old_state->planes[i];
765 old_plane_state = old_state->plane_states[i];
766
767 if (!plane)
768 continue;
769
770 if (plane->state->crtc != crtc &&
771 old_plane_state->crtc != crtc)
772 continue;
773
774 if (plane->state->fb != old_plane_state->fb)
775 return true;
776 }
777
778 return false;
779}
780
781
782
783
784
785
786
787
788
789
790
791
792void
793drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
794 struct drm_atomic_state *old_state)
795{
796 struct drm_crtc *crtc;
797 struct drm_crtc_state *old_crtc_state;
798 int ncrtcs = old_state->dev->mode_config.num_crtc;
799 int i, ret;
800
801 for (i = 0; i < ncrtcs; i++) {
802 crtc = old_state->crtcs[i];
803 old_crtc_state = old_state->crtc_states[i];
804
805 if (!crtc)
806 continue;
807
808
809
810
811 old_crtc_state->enable = false;
812
813 if (!crtc->state->enable)
814 continue;
815
816 if (!framebuffer_changed(dev, old_state, crtc))
817 continue;
818
819 ret = drm_crtc_vblank_get(crtc);
820 if (ret != 0)
821 continue;
822
823 old_crtc_state->enable = true;
824 old_crtc_state->last_vblank_count = drm_vblank_count(dev, i);
825 }
826
827 for (i = 0; i < ncrtcs; i++) {
828 crtc = old_state->crtcs[i];
829 old_crtc_state = old_state->crtc_states[i];
830
831 if (!crtc || !old_crtc_state->enable)
832 continue;
833
834 ret = wait_event_timeout(dev->vblank[i].queue,
835 old_crtc_state->last_vblank_count !=
836 drm_vblank_count(dev, i),
837 msecs_to_jiffies(50));
838
839 drm_crtc_vblank_put(crtc);
840 }
841}
842EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857int drm_atomic_helper_commit(struct drm_device *dev,
858 struct drm_atomic_state *state,
859 bool async)
860{
861 int ret;
862
863 if (async)
864 return -EBUSY;
865
866 ret = drm_atomic_helper_prepare_planes(dev, state);
867 if (ret)
868 return ret;
869
870
871
872
873
874
875
876 drm_atomic_helper_swap_state(dev, state);
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894 wait_for_fences(dev, state);
895
896 drm_atomic_helper_commit_pre_planes(dev, state);
897
898 drm_atomic_helper_commit_planes(dev, state);
899
900 drm_atomic_helper_commit_post_planes(dev, state);
901
902 drm_atomic_helper_wait_for_vblanks(dev, state);
903
904 drm_atomic_helper_cleanup_planes(dev, state);
905
906 drm_atomic_state_free(state);
907
908 return 0;
909}
910EXPORT_SYMBOL(drm_atomic_helper_commit);
911
912
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
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962int drm_atomic_helper_prepare_planes(struct drm_device *dev,
963 struct drm_atomic_state *state)
964{
965 int nplanes = dev->mode_config.num_total_plane;
966 int ret, i;
967
968 for (i = 0; i < nplanes; i++) {
969 struct drm_plane_helper_funcs *funcs;
970 struct drm_plane *plane = state->planes[i];
971 struct drm_framebuffer *fb;
972
973 if (!plane)
974 continue;
975
976 funcs = plane->helper_private;
977
978 fb = state->plane_states[i]->fb;
979
980 if (fb && funcs->prepare_fb) {
981 ret = funcs->prepare_fb(plane, fb);
982 if (ret)
983 goto fail;
984 }
985 }
986
987 return 0;
988
989fail:
990 for (i--; i >= 0; i--) {
991 struct drm_plane_helper_funcs *funcs;
992 struct drm_plane *plane = state->planes[i];
993 struct drm_framebuffer *fb;
994
995 if (!plane)
996 continue;
997
998 funcs = plane->helper_private;
999
1000 fb = state->plane_states[i]->fb;
1001
1002 if (fb && funcs->cleanup_fb)
1003 funcs->cleanup_fb(plane, fb);
1004
1005 }
1006
1007 return ret;
1008}
1009EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024void drm_atomic_helper_commit_planes(struct drm_device *dev,
1025 struct drm_atomic_state *old_state)
1026{
1027 int nplanes = dev->mode_config.num_total_plane;
1028 int ncrtcs = dev->mode_config.num_crtc;
1029 int i;
1030
1031 for (i = 0; i < ncrtcs; i++) {
1032 struct drm_crtc_helper_funcs *funcs;
1033 struct drm_crtc *crtc = old_state->crtcs[i];
1034
1035 if (!crtc)
1036 continue;
1037
1038 funcs = crtc->helper_private;
1039
1040 if (!funcs || !funcs->atomic_begin)
1041 continue;
1042
1043 funcs->atomic_begin(crtc);
1044 }
1045
1046 for (i = 0; i < nplanes; i++) {
1047 struct drm_plane_helper_funcs *funcs;
1048 struct drm_plane *plane = old_state->planes[i];
1049 struct drm_plane_state *old_plane_state;
1050
1051 if (!plane)
1052 continue;
1053
1054 funcs = plane->helper_private;
1055
1056 if (!funcs || !funcs->atomic_update)
1057 continue;
1058
1059 old_plane_state = old_state->plane_states[i];
1060
1061 funcs->atomic_update(plane, old_plane_state);
1062 }
1063
1064 for (i = 0; i < ncrtcs; i++) {
1065 struct drm_crtc_helper_funcs *funcs;
1066 struct drm_crtc *crtc = old_state->crtcs[i];
1067
1068 if (!crtc)
1069 continue;
1070
1071 funcs = crtc->helper_private;
1072
1073 if (!funcs || !funcs->atomic_flush)
1074 continue;
1075
1076 funcs->atomic_flush(crtc);
1077 }
1078}
1079EXPORT_SYMBOL(drm_atomic_helper_commit_planes);
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
1094 struct drm_atomic_state *old_state)
1095{
1096 int nplanes = dev->mode_config.num_total_plane;
1097 int i;
1098
1099 for (i = 0; i < nplanes; i++) {
1100 struct drm_plane_helper_funcs *funcs;
1101 struct drm_plane *plane = old_state->planes[i];
1102 struct drm_framebuffer *old_fb;
1103
1104 if (!plane)
1105 continue;
1106
1107 funcs = plane->helper_private;
1108
1109 old_fb = old_state->plane_states[i]->fb;
1110
1111 if (old_fb && funcs->cleanup_fb)
1112 funcs->cleanup_fb(plane, old_fb);
1113 }
1114}
1115EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142void drm_atomic_helper_swap_state(struct drm_device *dev,
1143 struct drm_atomic_state *state)
1144{
1145 int i;
1146
1147 for (i = 0; i < dev->mode_config.num_connector; i++) {
1148 struct drm_connector *connector = state->connectors[i];
1149
1150 if (!connector)
1151 continue;
1152
1153 connector->state->state = state;
1154 swap(state->connector_states[i], connector->state);
1155 connector->state->state = NULL;
1156 }
1157
1158 for (i = 0; i < dev->mode_config.num_crtc; i++) {
1159 struct drm_crtc *crtc = state->crtcs[i];
1160
1161 if (!crtc)
1162 continue;
1163
1164 crtc->state->state = state;
1165 swap(state->crtc_states[i], crtc->state);
1166 crtc->state->state = NULL;
1167 }
1168
1169 for (i = 0; i < dev->mode_config.num_total_plane; i++) {
1170 struct drm_plane *plane = state->planes[i];
1171
1172 if (!plane)
1173 continue;
1174
1175 plane->state->state = state;
1176 swap(state->plane_states[i], plane->state);
1177 plane->state->state = NULL;
1178 }
1179}
1180EXPORT_SYMBOL(drm_atomic_helper_swap_state);
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201int drm_atomic_helper_update_plane(struct drm_plane *plane,
1202 struct drm_crtc *crtc,
1203 struct drm_framebuffer *fb,
1204 int crtc_x, int crtc_y,
1205 unsigned int crtc_w, unsigned int crtc_h,
1206 uint32_t src_x, uint32_t src_y,
1207 uint32_t src_w, uint32_t src_h)
1208{
1209 struct drm_atomic_state *state;
1210 struct drm_plane_state *plane_state;
1211 int ret = 0;
1212
1213 state = drm_atomic_state_alloc(plane->dev);
1214 if (!state)
1215 return -ENOMEM;
1216
1217 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
1218retry:
1219 plane_state = drm_atomic_get_plane_state(state, plane);
1220 if (IS_ERR(plane_state)) {
1221 ret = PTR_ERR(plane_state);
1222 goto fail;
1223 }
1224
1225 ret = drm_atomic_set_crtc_for_plane(state, plane, crtc);
1226 if (ret != 0)
1227 goto fail;
1228 drm_atomic_set_fb_for_plane(plane_state, fb);
1229 plane_state->crtc_x = crtc_x;
1230 plane_state->crtc_y = crtc_y;
1231 plane_state->crtc_h = crtc_h;
1232 plane_state->crtc_w = crtc_w;
1233 plane_state->src_x = src_x;
1234 plane_state->src_y = src_y;
1235 plane_state->src_h = src_h;
1236 plane_state->src_w = src_w;
1237
1238 ret = drm_atomic_commit(state);
1239 if (ret != 0)
1240 goto fail;
1241
1242
1243 return 0;
1244fail:
1245 if (ret == -EDEADLK)
1246 goto backoff;
1247
1248 drm_atomic_state_free(state);
1249
1250 return ret;
1251backoff:
1252 drm_atomic_state_clear(state);
1253 drm_atomic_legacy_backoff(state);
1254
1255
1256
1257
1258
1259
1260 plane->old_fb = plane->fb;
1261
1262 goto retry;
1263}
1264EXPORT_SYMBOL(drm_atomic_helper_update_plane);
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275int drm_atomic_helper_disable_plane(struct drm_plane *plane)
1276{
1277 struct drm_atomic_state *state;
1278 struct drm_plane_state *plane_state;
1279 int ret = 0;
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289 if (!plane->crtc)
1290 return 0;
1291
1292 state = drm_atomic_state_alloc(plane->dev);
1293 if (!state)
1294 return -ENOMEM;
1295
1296 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(plane->crtc);
1297retry:
1298 plane_state = drm_atomic_get_plane_state(state, plane);
1299 if (IS_ERR(plane_state)) {
1300 ret = PTR_ERR(plane_state);
1301 goto fail;
1302 }
1303
1304 ret = drm_atomic_set_crtc_for_plane(state, plane, NULL);
1305 if (ret != 0)
1306 goto fail;
1307 drm_atomic_set_fb_for_plane(plane_state, NULL);
1308 plane_state->crtc_x = 0;
1309 plane_state->crtc_y = 0;
1310 plane_state->crtc_h = 0;
1311 plane_state->crtc_w = 0;
1312 plane_state->src_x = 0;
1313 plane_state->src_y = 0;
1314 plane_state->src_h = 0;
1315 plane_state->src_w = 0;
1316
1317 ret = drm_atomic_commit(state);
1318 if (ret != 0)
1319 goto fail;
1320
1321
1322 return 0;
1323fail:
1324 if (ret == -EDEADLK)
1325 goto backoff;
1326
1327 drm_atomic_state_free(state);
1328
1329 return ret;
1330backoff:
1331 drm_atomic_state_clear(state);
1332 drm_atomic_legacy_backoff(state);
1333
1334
1335
1336
1337
1338
1339 plane->old_fb = plane->fb;
1340
1341 goto retry;
1342}
1343EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
1344
1345static int update_output_state(struct drm_atomic_state *state,
1346 struct drm_mode_set *set)
1347{
1348 struct drm_device *dev = set->crtc->dev;
1349 struct drm_connector_state *conn_state;
1350 int ncrtcs = state->dev->mode_config.num_crtc;
1351 int ret, i, j;
1352
1353 ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
1354 state->acquire_ctx);
1355 if (ret)
1356 return ret;
1357
1358
1359 for (i = 0; i < set->num_connectors; i++) {
1360 conn_state = drm_atomic_get_connector_state(state,
1361 set->connectors[i]);
1362 if (IS_ERR(conn_state))
1363 return PTR_ERR(conn_state);
1364 }
1365
1366 for (i = 0; i < ncrtcs; i++) {
1367 struct drm_crtc *crtc = state->crtcs[i];
1368
1369 if (!crtc)
1370 continue;
1371
1372 ret = drm_atomic_add_affected_connectors(state, crtc);
1373 if (ret)
1374 return ret;
1375 }
1376
1377
1378 for (i = 0; i < state->num_connector; i++) {
1379 struct drm_connector *connector;
1380
1381 connector = state->connectors[i];
1382 conn_state = state->connector_states[i];
1383
1384 if (!connector)
1385 continue;
1386
1387 if (conn_state->crtc == set->crtc) {
1388 ret = drm_atomic_set_crtc_for_connector(conn_state,
1389 NULL);
1390 if (ret)
1391 return ret;
1392 }
1393
1394 for (j = 0; j < set->num_connectors; j++) {
1395 if (set->connectors[j] == connector) {
1396 ret = drm_atomic_set_crtc_for_connector(conn_state,
1397 set->crtc);
1398 if (ret)
1399 return ret;
1400 break;
1401 }
1402 }
1403 }
1404
1405 for (i = 0; i < ncrtcs; i++) {
1406 struct drm_crtc *crtc = state->crtcs[i];
1407 struct drm_crtc_state *crtc_state = state->crtc_states[i];
1408
1409 if (!crtc)
1410 continue;
1411
1412
1413
1414
1415
1416 if (crtc == set->crtc)
1417 continue;
1418
1419 crtc_state->enable =
1420 drm_atomic_connectors_for_crtc(state, crtc);
1421 }
1422
1423 return 0;
1424}
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435int drm_atomic_helper_set_config(struct drm_mode_set *set)
1436{
1437 struct drm_atomic_state *state;
1438 struct drm_crtc *crtc = set->crtc;
1439 struct drm_crtc_state *crtc_state;
1440 struct drm_plane_state *primary_state;
1441 int ret = 0;
1442
1443 state = drm_atomic_state_alloc(crtc->dev);
1444 if (!state)
1445 return -ENOMEM;
1446
1447 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
1448retry:
1449 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1450 if (IS_ERR(crtc_state)) {
1451 ret = PTR_ERR(crtc_state);
1452 goto fail;
1453 }
1454
1455 primary_state = drm_atomic_get_plane_state(state, crtc->primary);
1456 if (IS_ERR(primary_state)) {
1457 ret = PTR_ERR(primary_state);
1458 goto fail;
1459 }
1460
1461 if (!set->mode) {
1462 WARN_ON(set->fb);
1463 WARN_ON(set->num_connectors);
1464
1465 crtc_state->enable = false;
1466
1467 ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, NULL);
1468 if (ret != 0)
1469 goto fail;
1470
1471 drm_atomic_set_fb_for_plane(primary_state, NULL);
1472
1473 goto commit;
1474 }
1475
1476 WARN_ON(!set->fb);
1477 WARN_ON(!set->num_connectors);
1478
1479 crtc_state->enable = true;
1480 drm_mode_copy(&crtc_state->mode, set->mode);
1481
1482 ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, crtc);
1483 if (ret != 0)
1484 goto fail;
1485 drm_atomic_set_fb_for_plane(primary_state, set->fb);
1486 primary_state->crtc_x = 0;
1487 primary_state->crtc_y = 0;
1488 primary_state->crtc_h = set->mode->vdisplay;
1489 primary_state->crtc_w = set->mode->hdisplay;
1490 primary_state->src_x = set->x << 16;
1491 primary_state->src_y = set->y << 16;
1492 primary_state->src_h = set->mode->vdisplay << 16;
1493 primary_state->src_w = set->mode->hdisplay << 16;
1494
1495commit:
1496 ret = update_output_state(state, set);
1497 if (ret)
1498 goto fail;
1499
1500 ret = drm_atomic_commit(state);
1501 if (ret != 0)
1502 goto fail;
1503
1504
1505 return 0;
1506fail:
1507 if (ret == -EDEADLK)
1508 goto backoff;
1509
1510 drm_atomic_state_free(state);
1511
1512 return ret;
1513backoff:
1514 drm_atomic_state_clear(state);
1515 drm_atomic_legacy_backoff(state);
1516
1517
1518
1519
1520
1521
1522 crtc->primary->old_fb = crtc->primary->fb;
1523
1524 goto retry;
1525}
1526EXPORT_SYMBOL(drm_atomic_helper_set_config);
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539int
1540drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc,
1541 struct drm_property *property,
1542 uint64_t val)
1543{
1544 struct drm_atomic_state *state;
1545 struct drm_crtc_state *crtc_state;
1546 int ret = 0;
1547
1548 state = drm_atomic_state_alloc(crtc->dev);
1549 if (!state)
1550 return -ENOMEM;
1551
1552
1553 state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
1554retry:
1555 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1556 if (IS_ERR(crtc_state)) {
1557 ret = PTR_ERR(crtc_state);
1558 goto fail;
1559 }
1560
1561 ret = crtc->funcs->atomic_set_property(crtc, crtc_state,
1562 property, val);
1563 if (ret)
1564 goto fail;
1565
1566 ret = drm_atomic_commit(state);
1567 if (ret != 0)
1568 goto fail;
1569
1570
1571 return 0;
1572fail:
1573 if (ret == -EDEADLK)
1574 goto backoff;
1575
1576 drm_atomic_state_free(state);
1577
1578 return ret;
1579backoff:
1580 drm_atomic_state_clear(state);
1581 drm_atomic_legacy_backoff(state);
1582
1583 goto retry;
1584}
1585EXPORT_SYMBOL(drm_atomic_helper_crtc_set_property);
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598int
1599drm_atomic_helper_plane_set_property(struct drm_plane *plane,
1600 struct drm_property *property,
1601 uint64_t val)
1602{
1603 struct drm_atomic_state *state;
1604 struct drm_plane_state *plane_state;
1605 int ret = 0;
1606
1607 state = drm_atomic_state_alloc(plane->dev);
1608 if (!state)
1609 return -ENOMEM;
1610
1611
1612 state->acquire_ctx = plane->dev->mode_config.acquire_ctx;
1613retry:
1614 plane_state = drm_atomic_get_plane_state(state, plane);
1615 if (IS_ERR(plane_state)) {
1616 ret = PTR_ERR(plane_state);
1617 goto fail;
1618 }
1619
1620 ret = plane->funcs->atomic_set_property(plane, plane_state,
1621 property, val);
1622 if (ret)
1623 goto fail;
1624
1625 ret = drm_atomic_commit(state);
1626 if (ret != 0)
1627 goto fail;
1628
1629
1630 return 0;
1631fail:
1632 if (ret == -EDEADLK)
1633 goto backoff;
1634
1635 drm_atomic_state_free(state);
1636
1637 return ret;
1638backoff:
1639 drm_atomic_state_clear(state);
1640 drm_atomic_legacy_backoff(state);
1641
1642 goto retry;
1643}
1644EXPORT_SYMBOL(drm_atomic_helper_plane_set_property);
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657int
1658drm_atomic_helper_connector_set_property(struct drm_connector *connector,
1659 struct drm_property *property,
1660 uint64_t val)
1661{
1662 struct drm_atomic_state *state;
1663 struct drm_connector_state *connector_state;
1664 int ret = 0;
1665
1666 state = drm_atomic_state_alloc(connector->dev);
1667 if (!state)
1668 return -ENOMEM;
1669
1670
1671 state->acquire_ctx = connector->dev->mode_config.acquire_ctx;
1672retry:
1673 connector_state = drm_atomic_get_connector_state(state, connector);
1674 if (IS_ERR(connector_state)) {
1675 ret = PTR_ERR(connector_state);
1676 goto fail;
1677 }
1678
1679 ret = connector->funcs->atomic_set_property(connector, connector_state,
1680 property, val);
1681 if (ret)
1682 goto fail;
1683
1684 ret = drm_atomic_commit(state);
1685 if (ret != 0)
1686 goto fail;
1687
1688
1689 return 0;
1690fail:
1691 if (ret == -EDEADLK)
1692 goto backoff;
1693
1694 drm_atomic_state_free(state);
1695
1696 return ret;
1697backoff:
1698 drm_atomic_state_clear(state);
1699 drm_atomic_legacy_backoff(state);
1700
1701 goto retry;
1702}
1703EXPORT_SYMBOL(drm_atomic_helper_connector_set_property);
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
1722 struct drm_framebuffer *fb,
1723 struct drm_pending_vblank_event *event,
1724 uint32_t flags)
1725{
1726 struct drm_plane *plane = crtc->primary;
1727 struct drm_atomic_state *state;
1728 struct drm_plane_state *plane_state;
1729 struct drm_crtc_state *crtc_state;
1730 int ret = 0;
1731
1732 if (flags & DRM_MODE_PAGE_FLIP_ASYNC)
1733 return -EINVAL;
1734
1735 state = drm_atomic_state_alloc(plane->dev);
1736 if (!state)
1737 return -ENOMEM;
1738
1739 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
1740retry:
1741 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1742 if (IS_ERR(crtc_state)) {
1743 ret = PTR_ERR(crtc_state);
1744 goto fail;
1745 }
1746 crtc_state->event = event;
1747
1748 plane_state = drm_atomic_get_plane_state(state, plane);
1749 if (IS_ERR(plane_state)) {
1750 ret = PTR_ERR(plane_state);
1751 goto fail;
1752 }
1753
1754 ret = drm_atomic_set_crtc_for_plane(state, plane, crtc);
1755 if (ret != 0)
1756 goto fail;
1757 drm_atomic_set_fb_for_plane(plane_state, fb);
1758
1759 ret = drm_atomic_async_commit(state);
1760 if (ret != 0)
1761 goto fail;
1762
1763
1764
1765 plane->fb = plane->state->fb;
1766
1767
1768 return 0;
1769fail:
1770 if (ret == -EDEADLK)
1771 goto backoff;
1772
1773 drm_atomic_state_free(state);
1774
1775 return ret;
1776backoff:
1777 drm_atomic_state_clear(state);
1778 drm_atomic_legacy_backoff(state);
1779
1780
1781
1782
1783
1784
1785 plane->old_fb = plane->fb;
1786
1787 goto retry;
1788}
1789EXPORT_SYMBOL(drm_atomic_helper_page_flip);
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
1814{
1815 kfree(crtc->state);
1816 crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
1817}
1818EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
1819
1820
1821
1822
1823
1824
1825
1826
1827struct drm_crtc_state *
1828drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc)
1829{
1830 struct drm_crtc_state *state;
1831
1832 if (WARN_ON(!crtc->state))
1833 return NULL;
1834
1835 state = kmemdup(crtc->state, sizeof(*crtc->state), GFP_KERNEL);
1836
1837 if (state) {
1838 state->mode_changed = false;
1839 state->planes_changed = false;
1840 state->event = NULL;
1841 }
1842
1843 return state;
1844}
1845EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
1856 struct drm_crtc_state *state)
1857{
1858 kfree(state);
1859}
1860EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
1861
1862
1863
1864
1865
1866
1867
1868
1869void drm_atomic_helper_plane_reset(struct drm_plane *plane)
1870{
1871 if (plane->state && plane->state->fb)
1872 drm_framebuffer_unreference(plane->state->fb);
1873
1874 kfree(plane->state);
1875 plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
1876}
1877EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
1878
1879
1880
1881
1882
1883
1884
1885
1886struct drm_plane_state *
1887drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane)
1888{
1889 struct drm_plane_state *state;
1890
1891 if (WARN_ON(!plane->state))
1892 return NULL;
1893
1894 state = kmemdup(plane->state, sizeof(*plane->state), GFP_KERNEL);
1895
1896 if (state && state->fb)
1897 drm_framebuffer_reference(state->fb);
1898
1899 return state;
1900}
1901EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
1912 struct drm_plane_state *state)
1913{
1914 if (state->fb)
1915 drm_framebuffer_unreference(state->fb);
1916
1917 kfree(state);
1918}
1919EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929void drm_atomic_helper_connector_reset(struct drm_connector *connector)
1930{
1931 kfree(connector->state);
1932 connector->state = kzalloc(sizeof(*connector->state), GFP_KERNEL);
1933}
1934EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
1935
1936
1937
1938
1939
1940
1941
1942
1943struct drm_connector_state *
1944drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
1945{
1946 if (WARN_ON(!connector->state))
1947 return NULL;
1948
1949 return kmemdup(connector->state, sizeof(*connector->state), GFP_KERNEL);
1950}
1951EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
1962 struct drm_connector_state *state)
1963{
1964 kfree(state);
1965}
1966EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
1967