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_ATOMIC("[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_ATOMIC("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 const 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_ATOMIC("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_ATOMIC("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_ATOMIC("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_ATOMIC("[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_ATOMIC("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_ATOMIC("[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 struct drm_crtc *crtc;
252 struct drm_crtc_state *crtc_state;
253 struct drm_connector *connector;
254 struct drm_connector_state *conn_state;
255 int i;
256 bool ret;
257
258 for_each_crtc_in_state(state, crtc, crtc_state, i) {
259 if (!crtc_state->mode_changed)
260 continue;
261
262 drm_mode_copy(&crtc_state->adjusted_mode, &crtc_state->mode);
263 }
264
265 for_each_connector_in_state(state, connector, conn_state, i) {
266 const struct drm_encoder_helper_funcs *funcs;
267 struct drm_encoder *encoder;
268
269 WARN_ON(!!conn_state->best_encoder != !!conn_state->crtc);
270
271 if (!conn_state->crtc || !conn_state->best_encoder)
272 continue;
273
274 crtc_state =
275 state->crtc_states[drm_crtc_index(conn_state->crtc)];
276
277
278
279
280
281 encoder = conn_state->best_encoder;
282 funcs = encoder->helper_private;
283
284 if (encoder->bridge && encoder->bridge->funcs->mode_fixup) {
285 ret = encoder->bridge->funcs->mode_fixup(
286 encoder->bridge, &crtc_state->mode,
287 &crtc_state->adjusted_mode);
288 if (!ret) {
289 DRM_DEBUG_ATOMIC("Bridge fixup failed\n");
290 return -EINVAL;
291 }
292 }
293
294 if (funcs->atomic_check) {
295 ret = funcs->atomic_check(encoder, crtc_state,
296 conn_state);
297 if (ret) {
298 DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] check failed\n",
299 encoder->base.id, encoder->name);
300 return ret;
301 }
302 } else {
303 ret = funcs->mode_fixup(encoder, &crtc_state->mode,
304 &crtc_state->adjusted_mode);
305 if (!ret) {
306 DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] fixup failed\n",
307 encoder->base.id, encoder->name);
308 return -EINVAL;
309 }
310 }
311 }
312
313 for_each_crtc_in_state(state, crtc, crtc_state, i) {
314 const struct drm_crtc_helper_funcs *funcs;
315
316 if (!crtc_state->mode_changed)
317 continue;
318
319 funcs = crtc->helper_private;
320 ret = funcs->mode_fixup(crtc, &crtc_state->mode,
321 &crtc_state->adjusted_mode);
322 if (!ret) {
323 DRM_DEBUG_ATOMIC("[CRTC:%d] fixup failed\n",
324 crtc->base.id);
325 return -EINVAL;
326 }
327 }
328
329 return 0;
330}
331
332static bool
333needs_modeset(struct drm_crtc_state *state)
334{
335 return state->mode_changed || state->active_changed;
336}
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360int
361drm_atomic_helper_check_modeset(struct drm_device *dev,
362 struct drm_atomic_state *state)
363{
364 struct drm_crtc *crtc;
365 struct drm_crtc_state *crtc_state;
366 struct drm_connector *connector;
367 struct drm_connector_state *connector_state;
368 int i, ret;
369
370 for_each_crtc_in_state(state, crtc, crtc_state, i) {
371 if (!drm_mode_equal(&crtc->state->mode, &crtc_state->mode)) {
372 DRM_DEBUG_ATOMIC("[CRTC:%d] mode changed\n",
373 crtc->base.id);
374 crtc_state->mode_changed = true;
375 }
376
377 if (crtc->state->enable != crtc_state->enable) {
378 DRM_DEBUG_ATOMIC("[CRTC:%d] enable changed\n",
379 crtc->base.id);
380 crtc_state->mode_changed = true;
381 }
382 }
383
384 for_each_connector_in_state(state, connector, connector_state, i) {
385
386
387
388
389
390 ret = update_connector_routing(state, i);
391 if (ret)
392 return ret;
393 }
394
395
396
397
398
399
400
401 for_each_crtc_in_state(state, crtc, crtc_state, i) {
402 int num_connectors;
403
404
405
406
407
408
409 if (crtc->state->active != crtc_state->active) {
410 DRM_DEBUG_ATOMIC("[CRTC:%d] active changed\n",
411 crtc->base.id);
412 crtc_state->active_changed = true;
413 }
414
415 if (!needs_modeset(crtc_state))
416 continue;
417
418 DRM_DEBUG_ATOMIC("[CRTC:%d] needs all connectors, enable: %c, active: %c\n",
419 crtc->base.id,
420 crtc_state->enable ? 'y' : 'n',
421 crtc_state->active ? 'y' : 'n');
422
423 ret = drm_atomic_add_affected_connectors(state, crtc);
424 if (ret != 0)
425 return ret;
426
427 num_connectors = drm_atomic_connectors_for_crtc(state,
428 crtc);
429
430 if (crtc_state->enable != !!num_connectors) {
431 DRM_DEBUG_ATOMIC("[CRTC:%d] enabled/connectors mismatch\n",
432 crtc->base.id);
433
434 return -EINVAL;
435 }
436 }
437
438 return mode_fixup(state);
439}
440EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
441
442
443
444
445
446
447
448
449
450
451
452
453
454int
455drm_atomic_helper_check_planes(struct drm_device *dev,
456 struct drm_atomic_state *state)
457{
458 struct drm_crtc *crtc;
459 struct drm_crtc_state *crtc_state;
460 struct drm_plane *plane;
461 struct drm_plane_state *plane_state;
462 int i, ret = 0;
463
464 for_each_plane_in_state(state, plane, plane_state, i) {
465 const struct drm_plane_helper_funcs *funcs;
466
467 funcs = plane->helper_private;
468
469 drm_atomic_helper_plane_changed(state, plane_state, plane);
470
471 if (!funcs || !funcs->atomic_check)
472 continue;
473
474 ret = funcs->atomic_check(plane, plane_state);
475 if (ret) {
476 DRM_DEBUG_ATOMIC("[PLANE:%d] atomic driver check failed\n",
477 plane->base.id);
478 return ret;
479 }
480 }
481
482 for_each_crtc_in_state(state, crtc, crtc_state, i) {
483 const struct drm_crtc_helper_funcs *funcs;
484
485 funcs = crtc->helper_private;
486
487 if (!funcs || !funcs->atomic_check)
488 continue;
489
490 ret = funcs->atomic_check(crtc, state->crtc_states[i]);
491 if (ret) {
492 DRM_DEBUG_ATOMIC("[CRTC:%d] atomic driver check failed\n",
493 crtc->base.id);
494 return ret;
495 }
496 }
497
498 return ret;
499}
500EXPORT_SYMBOL(drm_atomic_helper_check_planes);
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522int drm_atomic_helper_check(struct drm_device *dev,
523 struct drm_atomic_state *state)
524{
525 int ret;
526
527 ret = drm_atomic_helper_check_modeset(dev, state);
528 if (ret)
529 return ret;
530
531 ret = drm_atomic_helper_check_planes(dev, state);
532 if (ret)
533 return ret;
534
535 return ret;
536}
537EXPORT_SYMBOL(drm_atomic_helper_check);
538
539static void
540disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
541{
542 struct drm_connector *connector;
543 struct drm_connector_state *old_conn_state;
544 struct drm_crtc *crtc;
545 struct drm_crtc_state *old_crtc_state;
546 int i;
547
548 for_each_connector_in_state(old_state, connector, old_conn_state, i) {
549 const struct drm_encoder_helper_funcs *funcs;
550 struct drm_encoder *encoder;
551 struct drm_crtc_state *old_crtc_state;
552
553
554
555 if (!old_conn_state->crtc)
556 continue;
557
558 old_crtc_state = old_state->crtc_states[drm_crtc_index(old_conn_state->crtc)];
559
560 if (!old_crtc_state->active ||
561 !needs_modeset(old_conn_state->crtc->state))
562 continue;
563
564 encoder = old_conn_state->best_encoder;
565
566
567
568
569 if (WARN_ON(!encoder))
570 continue;
571
572 funcs = encoder->helper_private;
573
574 DRM_DEBUG_ATOMIC("disabling [ENCODER:%d:%s]\n",
575 encoder->base.id, encoder->name);
576
577
578
579
580
581 if (encoder->bridge)
582 encoder->bridge->funcs->disable(encoder->bridge);
583
584
585 if (connector->state->crtc && funcs->prepare)
586 funcs->prepare(encoder);
587 else if (funcs->disable)
588 funcs->disable(encoder);
589 else
590 funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
591
592 if (encoder->bridge)
593 encoder->bridge->funcs->post_disable(encoder->bridge);
594 }
595
596 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
597 const struct drm_crtc_helper_funcs *funcs;
598
599
600 if (!needs_modeset(crtc->state))
601 continue;
602
603 if (!old_crtc_state->active)
604 continue;
605
606 funcs = crtc->helper_private;
607
608 DRM_DEBUG_ATOMIC("disabling [CRTC:%d]\n",
609 crtc->base.id);
610
611
612
613 if (crtc->state->enable && funcs->prepare)
614 funcs->prepare(crtc);
615 else if (funcs->disable)
616 funcs->disable(crtc);
617 else
618 funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
619 }
620}
621
622static void
623set_routing_links(struct drm_device *dev, struct drm_atomic_state *old_state)
624{
625 struct drm_connector *connector;
626 struct drm_connector_state *old_conn_state;
627 struct drm_crtc *crtc;
628 struct drm_crtc_state *old_crtc_state;
629 int i;
630
631
632 for_each_connector_in_state(old_state, connector, old_conn_state, i) {
633 if (!connector->encoder)
634 continue;
635
636 WARN_ON(!connector->encoder->crtc);
637
638 connector->encoder->crtc = NULL;
639 connector->encoder = NULL;
640 }
641
642
643 for_each_connector_in_state(old_state, connector, old_conn_state, i) {
644 if (!connector->state->crtc)
645 continue;
646
647 if (WARN_ON(!connector->state->best_encoder))
648 continue;
649
650 connector->encoder = connector->state->best_encoder;
651 connector->encoder->crtc = connector->state->crtc;
652 }
653
654
655 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
656 crtc->mode = crtc->state->mode;
657 crtc->enabled = crtc->state->enable;
658 crtc->x = crtc->primary->state->src_x >> 16;
659 crtc->y = crtc->primary->state->src_y >> 16;
660 }
661}
662
663static void
664crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
665{
666 struct drm_crtc *crtc;
667 struct drm_crtc_state *old_crtc_state;
668 struct drm_connector *connector;
669 struct drm_connector_state *old_conn_state;
670 int i;
671
672 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
673 const struct drm_crtc_helper_funcs *funcs;
674
675 if (!crtc->state->mode_changed)
676 continue;
677
678 funcs = crtc->helper_private;
679
680 if (crtc->state->enable && funcs->mode_set_nofb) {
681 DRM_DEBUG_ATOMIC("modeset on [CRTC:%d]\n",
682 crtc->base.id);
683
684 funcs->mode_set_nofb(crtc);
685 }
686 }
687
688 for_each_connector_in_state(old_state, connector, old_conn_state, i) {
689 const struct drm_encoder_helper_funcs *funcs;
690 struct drm_crtc_state *new_crtc_state;
691 struct drm_encoder *encoder;
692 struct drm_display_mode *mode, *adjusted_mode;
693
694 if (!connector->state->best_encoder)
695 continue;
696
697 encoder = connector->state->best_encoder;
698 funcs = encoder->helper_private;
699 new_crtc_state = connector->state->crtc->state;
700 mode = &new_crtc_state->mode;
701 adjusted_mode = &new_crtc_state->adjusted_mode;
702
703 if (!new_crtc_state->mode_changed)
704 continue;
705
706 DRM_DEBUG_ATOMIC("modeset on [ENCODER:%d:%s]\n",
707 encoder->base.id, encoder->name);
708
709
710
711
712
713 if (funcs->mode_set)
714 funcs->mode_set(encoder, mode, adjusted_mode);
715
716 if (encoder->bridge && encoder->bridge->funcs->mode_set)
717 encoder->bridge->funcs->mode_set(encoder->bridge,
718 mode, adjusted_mode);
719 }
720}
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev,
737 struct drm_atomic_state *old_state)
738{
739 disable_outputs(dev, old_state);
740 set_routing_links(dev, old_state);
741 crtc_set_mode(dev, old_state);
742}
743EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_disables);
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
760 struct drm_atomic_state *old_state)
761{
762 struct drm_crtc *crtc;
763 struct drm_crtc_state *old_crtc_state;
764 struct drm_connector *connector;
765 struct drm_connector_state *old_conn_state;
766 int i;
767
768 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
769 const struct drm_crtc_helper_funcs *funcs;
770
771
772 if (!needs_modeset(crtc->state))
773 continue;
774
775 if (!crtc->state->active)
776 continue;
777
778 funcs = crtc->helper_private;
779
780 if (crtc->state->enable) {
781 DRM_DEBUG_ATOMIC("enabling [CRTC:%d]\n",
782 crtc->base.id);
783
784 if (funcs->enable)
785 funcs->enable(crtc);
786 else
787 funcs->commit(crtc);
788 }
789 }
790
791 for_each_connector_in_state(old_state, connector, old_conn_state, i) {
792 const struct drm_encoder_helper_funcs *funcs;
793 struct drm_encoder *encoder;
794
795 if (!connector->state->best_encoder)
796 continue;
797
798 if (!connector->state->crtc->state->active ||
799 !needs_modeset(connector->state->crtc->state))
800 continue;
801
802 encoder = connector->state->best_encoder;
803 funcs = encoder->helper_private;
804
805 DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n",
806 encoder->base.id, encoder->name);
807
808
809
810
811
812 if (encoder->bridge)
813 encoder->bridge->funcs->pre_enable(encoder->bridge);
814
815 if (funcs->enable)
816 funcs->enable(encoder);
817 else
818 funcs->commit(encoder);
819
820 if (encoder->bridge)
821 encoder->bridge->funcs->enable(encoder->bridge);
822 }
823}
824EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables);
825
826static void wait_for_fences(struct drm_device *dev,
827 struct drm_atomic_state *state)
828{
829 struct drm_plane *plane;
830 struct drm_plane_state *plane_state;
831 int i;
832
833 for_each_plane_in_state(state, plane, plane_state, i) {
834 if (!plane->state->fence)
835 continue;
836
837 WARN_ON(!plane->state->fb);
838
839 fence_wait(plane->state->fence, false);
840 fence_put(plane->state->fence);
841 plane->state->fence = NULL;
842 }
843}
844
845static bool framebuffer_changed(struct drm_device *dev,
846 struct drm_atomic_state *old_state,
847 struct drm_crtc *crtc)
848{
849 struct drm_plane *plane;
850 struct drm_plane_state *old_plane_state;
851 int i;
852
853 for_each_plane_in_state(old_state, plane, old_plane_state, i) {
854 if (plane->state->crtc != crtc &&
855 old_plane_state->crtc != crtc)
856 continue;
857
858 if (plane->state->fb != old_plane_state->fb)
859 return true;
860 }
861
862 return false;
863}
864
865
866
867
868
869
870
871
872
873
874
875
876void
877drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
878 struct drm_atomic_state *old_state)
879{
880 struct drm_crtc *crtc;
881 struct drm_crtc_state *old_crtc_state;
882 int i, ret;
883
884 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
885
886
887
888 old_crtc_state->enable = false;
889
890 if (!crtc->state->enable)
891 continue;
892
893
894
895 if (old_state->legacy_cursor_update)
896 continue;
897
898 if (!framebuffer_changed(dev, old_state, crtc))
899 continue;
900
901 ret = drm_crtc_vblank_get(crtc);
902 if (ret != 0)
903 continue;
904
905 old_crtc_state->enable = true;
906 old_crtc_state->last_vblank_count = drm_vblank_count(dev, i);
907 }
908
909 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
910 if (!old_crtc_state->enable)
911 continue;
912
913 ret = wait_event_timeout(dev->vblank[i].queue,
914 old_crtc_state->last_vblank_count !=
915 drm_vblank_count(dev, i),
916 msecs_to_jiffies(50));
917
918 drm_crtc_vblank_put(crtc);
919 }
920}
921EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936int drm_atomic_helper_commit(struct drm_device *dev,
937 struct drm_atomic_state *state,
938 bool async)
939{
940 int ret;
941
942 if (async)
943 return -EBUSY;
944
945 ret = drm_atomic_helper_prepare_planes(dev, state);
946 if (ret)
947 return ret;
948
949
950
951
952
953
954
955 drm_atomic_helper_swap_state(dev, state);
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973 wait_for_fences(dev, state);
974
975 drm_atomic_helper_commit_modeset_disables(dev, state);
976
977 drm_atomic_helper_commit_planes(dev, state);
978
979 drm_atomic_helper_commit_modeset_enables(dev, state);
980
981 drm_atomic_helper_wait_for_vblanks(dev, state);
982
983 drm_atomic_helper_cleanup_planes(dev, state);
984
985 drm_atomic_state_free(state);
986
987 return 0;
988}
989EXPORT_SYMBOL(drm_atomic_helper_commit);
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041int drm_atomic_helper_prepare_planes(struct drm_device *dev,
1042 struct drm_atomic_state *state)
1043{
1044 int nplanes = dev->mode_config.num_total_plane;
1045 int ret, i;
1046
1047 for (i = 0; i < nplanes; i++) {
1048 const struct drm_plane_helper_funcs *funcs;
1049 struct drm_plane *plane = state->planes[i];
1050 struct drm_plane_state *plane_state = state->plane_states[i];
1051 struct drm_framebuffer *fb;
1052
1053 if (!plane)
1054 continue;
1055
1056 funcs = plane->helper_private;
1057
1058 fb = plane_state->fb;
1059
1060 if (fb && funcs->prepare_fb) {
1061 ret = funcs->prepare_fb(plane, fb, plane_state);
1062 if (ret)
1063 goto fail;
1064 }
1065 }
1066
1067 return 0;
1068
1069fail:
1070 for (i--; i >= 0; i--) {
1071 const struct drm_plane_helper_funcs *funcs;
1072 struct drm_plane *plane = state->planes[i];
1073 struct drm_plane_state *plane_state = state->plane_states[i];
1074 struct drm_framebuffer *fb;
1075
1076 if (!plane)
1077 continue;
1078
1079 funcs = plane->helper_private;
1080
1081 fb = state->plane_states[i]->fb;
1082
1083 if (fb && funcs->cleanup_fb)
1084 funcs->cleanup_fb(plane, fb, plane_state);
1085
1086 }
1087
1088 return ret;
1089}
1090EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105void drm_atomic_helper_commit_planes(struct drm_device *dev,
1106 struct drm_atomic_state *old_state)
1107{
1108 struct drm_crtc *crtc;
1109 struct drm_crtc_state *old_crtc_state;
1110 struct drm_plane *plane;
1111 struct drm_plane_state *old_plane_state;
1112 int i;
1113
1114 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
1115 const struct drm_crtc_helper_funcs *funcs;
1116
1117 funcs = crtc->helper_private;
1118
1119 if (!funcs || !funcs->atomic_begin)
1120 continue;
1121
1122 funcs->atomic_begin(crtc);
1123 }
1124
1125 for_each_plane_in_state(old_state, plane, old_plane_state, i) {
1126 const struct drm_plane_helper_funcs *funcs;
1127
1128 funcs = plane->helper_private;
1129
1130 if (!funcs)
1131 continue;
1132
1133 old_plane_state = old_state->plane_states[i];
1134
1135
1136
1137
1138 if (drm_atomic_plane_disabling(plane, old_plane_state) &&
1139 funcs->atomic_disable)
1140 funcs->atomic_disable(plane, old_plane_state);
1141 else
1142 funcs->atomic_update(plane, old_plane_state);
1143 }
1144
1145 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
1146 const struct drm_crtc_helper_funcs *funcs;
1147
1148 funcs = crtc->helper_private;
1149
1150 if (!funcs || !funcs->atomic_flush)
1151 continue;
1152
1153 funcs->atomic_flush(crtc);
1154 }
1155}
1156EXPORT_SYMBOL(drm_atomic_helper_commit_planes);
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
1171 struct drm_atomic_state *old_state)
1172{
1173 struct drm_plane *plane;
1174 struct drm_plane_state *plane_state;
1175 int i;
1176
1177 for_each_plane_in_state(old_state, plane, plane_state, i) {
1178 const struct drm_plane_helper_funcs *funcs;
1179 struct drm_framebuffer *old_fb;
1180
1181 funcs = plane->helper_private;
1182
1183 old_fb = plane_state->fb;
1184
1185 if (old_fb && funcs->cleanup_fb)
1186 funcs->cleanup_fb(plane, old_fb, plane_state);
1187 }
1188}
1189EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216void drm_atomic_helper_swap_state(struct drm_device *dev,
1217 struct drm_atomic_state *state)
1218{
1219 int i;
1220
1221 for (i = 0; i < dev->mode_config.num_connector; i++) {
1222 struct drm_connector *connector = state->connectors[i];
1223
1224 if (!connector)
1225 continue;
1226
1227 connector->state->state = state;
1228 swap(state->connector_states[i], connector->state);
1229 connector->state->state = NULL;
1230 }
1231
1232 for (i = 0; i < dev->mode_config.num_crtc; i++) {
1233 struct drm_crtc *crtc = state->crtcs[i];
1234
1235 if (!crtc)
1236 continue;
1237
1238 crtc->state->state = state;
1239 swap(state->crtc_states[i], crtc->state);
1240 crtc->state->state = NULL;
1241 }
1242
1243 for (i = 0; i < dev->mode_config.num_total_plane; i++) {
1244 struct drm_plane *plane = state->planes[i];
1245
1246 if (!plane)
1247 continue;
1248
1249 plane->state->state = state;
1250 swap(state->plane_states[i], plane->state);
1251 plane->state->state = NULL;
1252 }
1253}
1254EXPORT_SYMBOL(drm_atomic_helper_swap_state);
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275int drm_atomic_helper_update_plane(struct drm_plane *plane,
1276 struct drm_crtc *crtc,
1277 struct drm_framebuffer *fb,
1278 int crtc_x, int crtc_y,
1279 unsigned int crtc_w, unsigned int crtc_h,
1280 uint32_t src_x, uint32_t src_y,
1281 uint32_t src_w, uint32_t src_h)
1282{
1283 struct drm_atomic_state *state;
1284 struct drm_plane_state *plane_state;
1285 int ret = 0;
1286
1287 state = drm_atomic_state_alloc(plane->dev);
1288 if (!state)
1289 return -ENOMEM;
1290
1291 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
1292retry:
1293 plane_state = drm_atomic_get_plane_state(state, plane);
1294 if (IS_ERR(plane_state)) {
1295 ret = PTR_ERR(plane_state);
1296 goto fail;
1297 }
1298
1299 ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
1300 if (ret != 0)
1301 goto fail;
1302 drm_atomic_set_fb_for_plane(plane_state, fb);
1303 plane_state->crtc_x = crtc_x;
1304 plane_state->crtc_y = crtc_y;
1305 plane_state->crtc_h = crtc_h;
1306 plane_state->crtc_w = crtc_w;
1307 plane_state->src_x = src_x;
1308 plane_state->src_y = src_y;
1309 plane_state->src_h = src_h;
1310 plane_state->src_w = src_w;
1311
1312 ret = drm_atomic_commit(state);
1313 if (ret != 0)
1314 goto fail;
1315
1316 if (plane == crtc->cursor)
1317 state->legacy_cursor_update = true;
1318
1319
1320 return 0;
1321fail:
1322 if (ret == -EDEADLK)
1323 goto backoff;
1324
1325 drm_atomic_state_free(state);
1326
1327 return ret;
1328backoff:
1329 drm_atomic_state_clear(state);
1330 drm_atomic_legacy_backoff(state);
1331
1332
1333
1334
1335
1336
1337 plane->old_fb = plane->fb;
1338
1339 goto retry;
1340}
1341EXPORT_SYMBOL(drm_atomic_helper_update_plane);
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352int drm_atomic_helper_disable_plane(struct drm_plane *plane)
1353{
1354 struct drm_atomic_state *state;
1355 struct drm_plane_state *plane_state;
1356 int ret = 0;
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366 if (!plane->crtc)
1367 return 0;
1368
1369 state = drm_atomic_state_alloc(plane->dev);
1370 if (!state)
1371 return -ENOMEM;
1372
1373 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(plane->crtc);
1374retry:
1375 plane_state = drm_atomic_get_plane_state(state, plane);
1376 if (IS_ERR(plane_state)) {
1377 ret = PTR_ERR(plane_state);
1378 goto fail;
1379 }
1380
1381 ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
1382 if (ret != 0)
1383 goto fail;
1384 drm_atomic_set_fb_for_plane(plane_state, NULL);
1385 plane_state->crtc_x = 0;
1386 plane_state->crtc_y = 0;
1387 plane_state->crtc_h = 0;
1388 plane_state->crtc_w = 0;
1389 plane_state->src_x = 0;
1390 plane_state->src_y = 0;
1391 plane_state->src_h = 0;
1392 plane_state->src_w = 0;
1393
1394 if (plane == plane->crtc->cursor)
1395 state->legacy_cursor_update = true;
1396
1397 ret = drm_atomic_commit(state);
1398 if (ret != 0)
1399 goto fail;
1400
1401
1402 return 0;
1403fail:
1404 if (ret == -EDEADLK)
1405 goto backoff;
1406
1407 drm_atomic_state_free(state);
1408
1409 return ret;
1410backoff:
1411 drm_atomic_state_clear(state);
1412 drm_atomic_legacy_backoff(state);
1413
1414
1415
1416
1417
1418
1419 plane->old_fb = plane->fb;
1420
1421 goto retry;
1422}
1423EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
1424
1425static int update_output_state(struct drm_atomic_state *state,
1426 struct drm_mode_set *set)
1427{
1428 struct drm_device *dev = set->crtc->dev;
1429 struct drm_crtc *crtc;
1430 struct drm_crtc_state *crtc_state;
1431 struct drm_connector *connector;
1432 struct drm_connector_state *conn_state;
1433 int ret, i, j;
1434
1435 ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
1436 state->acquire_ctx);
1437 if (ret)
1438 return ret;
1439
1440
1441 for (i = 0; i < set->num_connectors; i++) {
1442 conn_state = drm_atomic_get_connector_state(state,
1443 set->connectors[i]);
1444 if (IS_ERR(conn_state))
1445 return PTR_ERR(conn_state);
1446 }
1447
1448 for_each_crtc_in_state(state, crtc, crtc_state, i) {
1449 ret = drm_atomic_add_affected_connectors(state, crtc);
1450 if (ret)
1451 return ret;
1452 }
1453
1454
1455 for_each_connector_in_state(state, connector, conn_state, i) {
1456 if (conn_state->crtc == set->crtc) {
1457 ret = drm_atomic_set_crtc_for_connector(conn_state,
1458 NULL);
1459 if (ret)
1460 return ret;
1461 }
1462
1463 for (j = 0; j < set->num_connectors; j++) {
1464 if (set->connectors[j] == connector) {
1465 ret = drm_atomic_set_crtc_for_connector(conn_state,
1466 set->crtc);
1467 if (ret)
1468 return ret;
1469 break;
1470 }
1471 }
1472 }
1473
1474 for_each_crtc_in_state(state, crtc, crtc_state, i) {
1475
1476
1477
1478
1479 if (crtc == set->crtc)
1480 continue;
1481
1482 crtc_state->enable =
1483 drm_atomic_connectors_for_crtc(state, crtc);
1484 }
1485
1486 return 0;
1487}
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498int drm_atomic_helper_set_config(struct drm_mode_set *set)
1499{
1500 struct drm_atomic_state *state;
1501 struct drm_crtc *crtc = set->crtc;
1502 struct drm_crtc_state *crtc_state;
1503 struct drm_plane_state *primary_state;
1504 int ret = 0;
1505
1506 state = drm_atomic_state_alloc(crtc->dev);
1507 if (!state)
1508 return -ENOMEM;
1509
1510 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
1511retry:
1512 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1513 if (IS_ERR(crtc_state)) {
1514 ret = PTR_ERR(crtc_state);
1515 goto fail;
1516 }
1517
1518 primary_state = drm_atomic_get_plane_state(state, crtc->primary);
1519 if (IS_ERR(primary_state)) {
1520 ret = PTR_ERR(primary_state);
1521 goto fail;
1522 }
1523
1524 if (!set->mode) {
1525 WARN_ON(set->fb);
1526 WARN_ON(set->num_connectors);
1527
1528 crtc_state->enable = false;
1529 crtc_state->active = false;
1530
1531 ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
1532 if (ret != 0)
1533 goto fail;
1534
1535 drm_atomic_set_fb_for_plane(primary_state, NULL);
1536
1537 goto commit;
1538 }
1539
1540 WARN_ON(!set->fb);
1541 WARN_ON(!set->num_connectors);
1542
1543 crtc_state->enable = true;
1544 crtc_state->active = true;
1545 drm_mode_copy(&crtc_state->mode, set->mode);
1546
1547 ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
1548 if (ret != 0)
1549 goto fail;
1550 drm_atomic_set_fb_for_plane(primary_state, set->fb);
1551 primary_state->crtc_x = 0;
1552 primary_state->crtc_y = 0;
1553 primary_state->crtc_h = set->mode->vdisplay;
1554 primary_state->crtc_w = set->mode->hdisplay;
1555 primary_state->src_x = set->x << 16;
1556 primary_state->src_y = set->y << 16;
1557 primary_state->src_h = set->mode->vdisplay << 16;
1558 primary_state->src_w = set->mode->hdisplay << 16;
1559
1560commit:
1561 ret = update_output_state(state, set);
1562 if (ret)
1563 goto fail;
1564
1565 ret = drm_atomic_commit(state);
1566 if (ret != 0)
1567 goto fail;
1568
1569
1570 return 0;
1571fail:
1572 if (ret == -EDEADLK)
1573 goto backoff;
1574
1575 drm_atomic_state_free(state);
1576
1577 return ret;
1578backoff:
1579 drm_atomic_state_clear(state);
1580 drm_atomic_legacy_backoff(state);
1581
1582
1583
1584
1585
1586
1587 crtc->primary->old_fb = crtc->primary->fb;
1588
1589 goto retry;
1590}
1591EXPORT_SYMBOL(drm_atomic_helper_set_config);
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605int
1606drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc,
1607 struct drm_property *property,
1608 uint64_t val)
1609{
1610 struct drm_atomic_state *state;
1611 struct drm_crtc_state *crtc_state;
1612 int ret = 0;
1613
1614 state = drm_atomic_state_alloc(crtc->dev);
1615 if (!state)
1616 return -ENOMEM;
1617
1618
1619 state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
1620retry:
1621 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1622 if (IS_ERR(crtc_state)) {
1623 ret = PTR_ERR(crtc_state);
1624 goto fail;
1625 }
1626
1627 ret = drm_atomic_crtc_set_property(crtc, crtc_state,
1628 property, val);
1629 if (ret)
1630 goto fail;
1631
1632 ret = drm_atomic_commit(state);
1633 if (ret != 0)
1634 goto fail;
1635
1636
1637 return 0;
1638fail:
1639 if (ret == -EDEADLK)
1640 goto backoff;
1641
1642 drm_atomic_state_free(state);
1643
1644 return ret;
1645backoff:
1646 drm_atomic_state_clear(state);
1647 drm_atomic_legacy_backoff(state);
1648
1649 goto retry;
1650}
1651EXPORT_SYMBOL(drm_atomic_helper_crtc_set_property);
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665int
1666drm_atomic_helper_plane_set_property(struct drm_plane *plane,
1667 struct drm_property *property,
1668 uint64_t val)
1669{
1670 struct drm_atomic_state *state;
1671 struct drm_plane_state *plane_state;
1672 int ret = 0;
1673
1674 state = drm_atomic_state_alloc(plane->dev);
1675 if (!state)
1676 return -ENOMEM;
1677
1678
1679 state->acquire_ctx = plane->dev->mode_config.acquire_ctx;
1680retry:
1681 plane_state = drm_atomic_get_plane_state(state, plane);
1682 if (IS_ERR(plane_state)) {
1683 ret = PTR_ERR(plane_state);
1684 goto fail;
1685 }
1686
1687 ret = drm_atomic_plane_set_property(plane, plane_state,
1688 property, val);
1689 if (ret)
1690 goto fail;
1691
1692 ret = drm_atomic_commit(state);
1693 if (ret != 0)
1694 goto fail;
1695
1696
1697 return 0;
1698fail:
1699 if (ret == -EDEADLK)
1700 goto backoff;
1701
1702 drm_atomic_state_free(state);
1703
1704 return ret;
1705backoff:
1706 drm_atomic_state_clear(state);
1707 drm_atomic_legacy_backoff(state);
1708
1709 goto retry;
1710}
1711EXPORT_SYMBOL(drm_atomic_helper_plane_set_property);
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725int
1726drm_atomic_helper_connector_set_property(struct drm_connector *connector,
1727 struct drm_property *property,
1728 uint64_t val)
1729{
1730 struct drm_atomic_state *state;
1731 struct drm_connector_state *connector_state;
1732 int ret = 0;
1733
1734 state = drm_atomic_state_alloc(connector->dev);
1735 if (!state)
1736 return -ENOMEM;
1737
1738
1739 state->acquire_ctx = connector->dev->mode_config.acquire_ctx;
1740retry:
1741 connector_state = drm_atomic_get_connector_state(state, connector);
1742 if (IS_ERR(connector_state)) {
1743 ret = PTR_ERR(connector_state);
1744 goto fail;
1745 }
1746
1747 ret = drm_atomic_connector_set_property(connector, connector_state,
1748 property, val);
1749 if (ret)
1750 goto fail;
1751
1752 ret = drm_atomic_commit(state);
1753 if (ret != 0)
1754 goto fail;
1755
1756
1757 return 0;
1758fail:
1759 if (ret == -EDEADLK)
1760 goto backoff;
1761
1762 drm_atomic_state_free(state);
1763
1764 return ret;
1765backoff:
1766 drm_atomic_state_clear(state);
1767 drm_atomic_legacy_backoff(state);
1768
1769 goto retry;
1770}
1771EXPORT_SYMBOL(drm_atomic_helper_connector_set_property);
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
1790 struct drm_framebuffer *fb,
1791 struct drm_pending_vblank_event *event,
1792 uint32_t flags)
1793{
1794 struct drm_plane *plane = crtc->primary;
1795 struct drm_atomic_state *state;
1796 struct drm_plane_state *plane_state;
1797 struct drm_crtc_state *crtc_state;
1798 int ret = 0;
1799
1800 if (flags & DRM_MODE_PAGE_FLIP_ASYNC)
1801 return -EINVAL;
1802
1803 state = drm_atomic_state_alloc(plane->dev);
1804 if (!state)
1805 return -ENOMEM;
1806
1807 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
1808retry:
1809 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1810 if (IS_ERR(crtc_state)) {
1811 ret = PTR_ERR(crtc_state);
1812 goto fail;
1813 }
1814 crtc_state->event = event;
1815
1816 plane_state = drm_atomic_get_plane_state(state, plane);
1817 if (IS_ERR(plane_state)) {
1818 ret = PTR_ERR(plane_state);
1819 goto fail;
1820 }
1821
1822 ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
1823 if (ret != 0)
1824 goto fail;
1825 drm_atomic_set_fb_for_plane(plane_state, fb);
1826
1827 ret = drm_atomic_async_commit(state);
1828 if (ret != 0)
1829 goto fail;
1830
1831
1832
1833 plane->fb = plane->state->fb;
1834
1835
1836 return 0;
1837fail:
1838 if (ret == -EDEADLK)
1839 goto backoff;
1840
1841 drm_atomic_state_free(state);
1842
1843 return ret;
1844backoff:
1845 drm_atomic_state_clear(state);
1846 drm_atomic_legacy_backoff(state);
1847
1848
1849
1850
1851
1852
1853 plane->old_fb = plane->fb;
1854
1855 goto retry;
1856}
1857EXPORT_SYMBOL(drm_atomic_helper_page_flip);
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
1870 int mode)
1871{
1872 struct drm_mode_config *config = &connector->dev->mode_config;
1873 struct drm_atomic_state *state;
1874 struct drm_crtc_state *crtc_state;
1875 struct drm_crtc *crtc;
1876 struct drm_connector *tmp_connector;
1877 int ret;
1878 bool active = false;
1879
1880 if (mode != DRM_MODE_DPMS_ON)
1881 mode = DRM_MODE_DPMS_OFF;
1882
1883 connector->dpms = mode;
1884 crtc = connector->state->crtc;
1885
1886 if (!crtc)
1887 return;
1888
1889
1890 state = drm_atomic_state_alloc(connector->dev);
1891 if (!state)
1892 return;
1893
1894 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
1895retry:
1896 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1897 if (IS_ERR(crtc_state))
1898 return;
1899
1900 WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
1901
1902 list_for_each_entry(tmp_connector, &config->connector_list, head) {
1903 if (tmp_connector->state->crtc != crtc)
1904 continue;
1905
1906 if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
1907 active = true;
1908 break;
1909 }
1910 }
1911 crtc_state->active = active;
1912
1913 ret = drm_atomic_commit(state);
1914 if (ret != 0)
1915 goto fail;
1916
1917
1918 return;
1919fail:
1920 if (ret == -EDEADLK)
1921 goto backoff;
1922
1923 drm_atomic_state_free(state);
1924
1925 WARN(1, "Driver bug: Changing ->active failed with ret=%i\n", ret);
1926
1927 return;
1928backoff:
1929 drm_atomic_state_clear(state);
1930 drm_atomic_legacy_backoff(state);
1931
1932 goto retry;
1933}
1934EXPORT_SYMBOL(drm_atomic_helper_connector_dpms);
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
1959{
1960 kfree(crtc->state);
1961 crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
1962
1963 if (crtc->state)
1964 crtc->state->crtc = crtc;
1965}
1966EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
1977 struct drm_crtc_state *state)
1978{
1979 memcpy(state, crtc->state, sizeof(*state));
1980
1981 state->mode_changed = false;
1982 state->active_changed = false;
1983 state->planes_changed = false;
1984 state->event = NULL;
1985}
1986EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
1987
1988
1989
1990
1991
1992
1993
1994
1995struct drm_crtc_state *
1996drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc)
1997{
1998 struct drm_crtc_state *state;
1999
2000 if (WARN_ON(!crtc->state))
2001 return NULL;
2002
2003 state = kmalloc(sizeof(*state), GFP_KERNEL);
2004 if (state)
2005 __drm_atomic_helper_crtc_duplicate_state(crtc, state);
2006
2007 return state;
2008}
2009EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
2021 struct drm_crtc_state *state)
2022{
2023
2024
2025
2026
2027
2028}
2029EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
2040 struct drm_crtc_state *state)
2041{
2042 __drm_atomic_helper_crtc_destroy_state(crtc, state);
2043 kfree(state);
2044}
2045EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
2046
2047
2048
2049
2050
2051
2052
2053
2054void drm_atomic_helper_plane_reset(struct drm_plane *plane)
2055{
2056 if (plane->state && plane->state->fb)
2057 drm_framebuffer_unreference(plane->state->fb);
2058
2059 kfree(plane->state);
2060 plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
2061
2062 if (plane->state)
2063 plane->state->plane = plane;
2064}
2065EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
2076 struct drm_plane_state *state)
2077{
2078 memcpy(state, plane->state, sizeof(*state));
2079
2080 if (state->fb)
2081 drm_framebuffer_reference(state->fb);
2082}
2083EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
2084
2085
2086
2087
2088
2089
2090
2091
2092struct drm_plane_state *
2093drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane)
2094{
2095 struct drm_plane_state *state;
2096
2097 if (WARN_ON(!plane->state))
2098 return NULL;
2099
2100 state = kmalloc(sizeof(*state), GFP_KERNEL);
2101 if (state)
2102 __drm_atomic_helper_plane_duplicate_state(plane, state);
2103
2104 return state;
2105}
2106EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117void __drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
2118 struct drm_plane_state *state)
2119{
2120 if (state->fb)
2121 drm_framebuffer_unreference(state->fb);
2122}
2123EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
2134 struct drm_plane_state *state)
2135{
2136 __drm_atomic_helper_plane_destroy_state(plane, state);
2137 kfree(state);
2138}
2139EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149void drm_atomic_helper_connector_reset(struct drm_connector *connector)
2150{
2151 kfree(connector->state);
2152 connector->state = kzalloc(sizeof(*connector->state), GFP_KERNEL);
2153
2154 if (connector->state)
2155 connector->state->connector = connector;
2156}
2157EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167void
2168__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
2169 struct drm_connector_state *state)
2170{
2171 memcpy(state, connector->state, sizeof(*state));
2172}
2173EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
2174
2175
2176
2177
2178
2179
2180
2181
2182struct drm_connector_state *
2183drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
2184{
2185 struct drm_connector_state *state;
2186
2187 if (WARN_ON(!connector->state))
2188 return NULL;
2189
2190 state = kmalloc(sizeof(*state), GFP_KERNEL);
2191 if (state)
2192 __drm_atomic_helper_connector_duplicate_state(connector, state);
2193
2194 return state;
2195}
2196EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207void
2208__drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
2209 struct drm_connector_state *state)
2210{
2211
2212
2213
2214
2215
2216}
2217EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
2228 struct drm_connector_state *state)
2229{
2230 __drm_atomic_helper_connector_destroy_state(connector, state);
2231 kfree(state);
2232}
2233EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
2234