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
56
57
58
59
60
61
62static void
63drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
64 struct drm_plane_state *plane_state,
65 struct drm_plane *plane)
66{
67 struct drm_crtc_state *crtc_state;
68
69 if (plane->state->crtc) {
70 crtc_state = drm_atomic_get_existing_crtc_state(state,
71 plane->state->crtc);
72
73 if (WARN_ON(!crtc_state))
74 return;
75
76 crtc_state->planes_changed = true;
77 }
78
79 if (plane_state->crtc) {
80 crtc_state = drm_atomic_get_existing_crtc_state(state,
81 plane_state->crtc);
82
83 if (WARN_ON(!crtc_state))
84 return;
85
86 crtc_state->planes_changed = true;
87 }
88}
89
90static int handle_conflicting_encoders(struct drm_atomic_state *state,
91 bool disable_conflicting_encoders)
92{
93 struct drm_connector_state *conn_state;
94 struct drm_connector *connector;
95 struct drm_encoder *encoder;
96 unsigned encoder_mask = 0;
97 int i, ret;
98
99
100
101
102
103
104 for_each_connector_in_state(state, connector, conn_state, i) {
105 const struct drm_connector_helper_funcs *funcs = connector->helper_private;
106 struct drm_encoder *new_encoder;
107
108 if (!conn_state->crtc)
109 continue;
110
111 if (funcs->atomic_best_encoder)
112 new_encoder = funcs->atomic_best_encoder(connector, conn_state);
113 else
114 new_encoder = funcs->best_encoder(connector);
115
116 if (new_encoder) {
117 if (encoder_mask & (1 << drm_encoder_index(new_encoder))) {
118 DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] on [CONNECTOR:%d:%s] already assigned\n",
119 new_encoder->base.id, new_encoder->name,
120 connector->base.id, connector->name);
121
122 return -EINVAL;
123 }
124
125 encoder_mask |= 1 << drm_encoder_index(new_encoder);
126 }
127 }
128
129 if (!encoder_mask)
130 return 0;
131
132
133
134
135
136
137
138
139
140
141
142
143 drm_for_each_connector(connector, state->dev) {
144 struct drm_crtc_state *crtc_state;
145
146 if (drm_atomic_get_existing_connector_state(state, connector))
147 continue;
148
149 encoder = connector->state->best_encoder;
150 if (!encoder || !(encoder_mask & (1 << drm_encoder_index(encoder))))
151 continue;
152
153 if (!disable_conflicting_encoders) {
154 DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s] by [CONNECTOR:%d:%s]\n",
155 encoder->base.id, encoder->name,
156 connector->state->crtc->base.id,
157 connector->state->crtc->name,
158 connector->base.id, connector->name);
159 return -EINVAL;
160 }
161
162 conn_state = drm_atomic_get_connector_state(state, connector);
163 if (IS_ERR(conn_state))
164 return PTR_ERR(conn_state);
165
166 DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], disabling [CONNECTOR:%d:%s]\n",
167 encoder->base.id, encoder->name,
168 conn_state->crtc->base.id, conn_state->crtc->name,
169 connector->base.id, connector->name);
170
171 crtc_state = drm_atomic_get_existing_crtc_state(state, conn_state->crtc);
172
173 ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
174 if (ret)
175 return ret;
176
177 if (!crtc_state->connector_mask) {
178 ret = drm_atomic_set_mode_prop_for_crtc(crtc_state,
179 NULL);
180 if (ret < 0)
181 return ret;
182
183 crtc_state->active = false;
184 }
185 }
186
187 return 0;
188}
189
190static void
191set_best_encoder(struct drm_atomic_state *state,
192 struct drm_connector_state *conn_state,
193 struct drm_encoder *encoder)
194{
195 struct drm_crtc_state *crtc_state;
196 struct drm_crtc *crtc;
197
198 if (conn_state->best_encoder) {
199
200 crtc = conn_state->connector->state->crtc;
201
202
203
204
205
206
207
208 WARN_ON(!crtc && encoder != conn_state->best_encoder);
209 if (crtc) {
210 crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);
211
212 crtc_state->encoder_mask &=
213 ~(1 << drm_encoder_index(conn_state->best_encoder));
214 }
215 }
216
217 if (encoder) {
218 crtc = conn_state->crtc;
219 WARN_ON(!crtc);
220 if (crtc) {
221 crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);
222
223 crtc_state->encoder_mask |=
224 1 << drm_encoder_index(encoder);
225 }
226 }
227
228 conn_state->best_encoder = encoder;
229}
230
231static void
232steal_encoder(struct drm_atomic_state *state,
233 struct drm_encoder *encoder)
234{
235 struct drm_crtc_state *crtc_state;
236 struct drm_connector *connector;
237 struct drm_connector_state *connector_state;
238 int i;
239
240 for_each_connector_in_state(state, connector, connector_state, i) {
241 struct drm_crtc *encoder_crtc;
242
243 if (connector_state->best_encoder != encoder)
244 continue;
245
246 encoder_crtc = connector->state->crtc;
247
248 DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], stealing it\n",
249 encoder->base.id, encoder->name,
250 encoder_crtc->base.id, encoder_crtc->name);
251
252 set_best_encoder(state, connector_state, NULL);
253
254 crtc_state = drm_atomic_get_existing_crtc_state(state, encoder_crtc);
255 crtc_state->connectors_changed = true;
256
257 return;
258 }
259}
260
261static int
262update_connector_routing(struct drm_atomic_state *state,
263 struct drm_connector *connector,
264 struct drm_connector_state *connector_state)
265{
266 const struct drm_connector_helper_funcs *funcs;
267 struct drm_encoder *new_encoder;
268 struct drm_crtc_state *crtc_state;
269
270 DRM_DEBUG_ATOMIC("Updating routing for [CONNECTOR:%d:%s]\n",
271 connector->base.id,
272 connector->name);
273
274 if (connector->state->crtc != connector_state->crtc) {
275 if (connector->state->crtc) {
276 crtc_state = drm_atomic_get_existing_crtc_state(state, connector->state->crtc);
277 crtc_state->connectors_changed = true;
278 }
279
280 if (connector_state->crtc) {
281 crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc);
282 crtc_state->connectors_changed = true;
283 }
284 }
285
286 if (!connector_state->crtc) {
287 DRM_DEBUG_ATOMIC("Disabling [CONNECTOR:%d:%s]\n",
288 connector->base.id,
289 connector->name);
290
291 set_best_encoder(state, connector_state, NULL);
292
293 return 0;
294 }
295
296 funcs = connector->helper_private;
297
298 if (funcs->atomic_best_encoder)
299 new_encoder = funcs->atomic_best_encoder(connector,
300 connector_state);
301 else
302 new_encoder = funcs->best_encoder(connector);
303
304 if (!new_encoder) {
305 DRM_DEBUG_ATOMIC("No suitable encoder found for [CONNECTOR:%d:%s]\n",
306 connector->base.id,
307 connector->name);
308 return -EINVAL;
309 }
310
311 if (!drm_encoder_crtc_ok(new_encoder, connector_state->crtc)) {
312 DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d]\n",
313 new_encoder->base.id,
314 new_encoder->name,
315 connector_state->crtc->base.id);
316 return -EINVAL;
317 }
318
319 if (new_encoder == connector_state->best_encoder) {
320 set_best_encoder(state, connector_state, new_encoder);
321
322 DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d:%s]\n",
323 connector->base.id,
324 connector->name,
325 new_encoder->base.id,
326 new_encoder->name,
327 connector_state->crtc->base.id,
328 connector_state->crtc->name);
329
330 return 0;
331 }
332
333 steal_encoder(state, new_encoder);
334
335 set_best_encoder(state, connector_state, new_encoder);
336
337 crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc);
338 crtc_state->connectors_changed = true;
339
340 DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n",
341 connector->base.id,
342 connector->name,
343 new_encoder->base.id,
344 new_encoder->name,
345 connector_state->crtc->base.id,
346 connector_state->crtc->name);
347
348 return 0;
349}
350
351static int
352mode_fixup(struct drm_atomic_state *state)
353{
354 struct drm_crtc *crtc;
355 struct drm_crtc_state *crtc_state;
356 struct drm_connector *connector;
357 struct drm_connector_state *conn_state;
358 int i;
359 bool ret;
360
361 for_each_crtc_in_state(state, crtc, crtc_state, i) {
362 if (!crtc_state->mode_changed &&
363 !crtc_state->connectors_changed)
364 continue;
365
366 drm_mode_copy(&crtc_state->adjusted_mode, &crtc_state->mode);
367 }
368
369 for_each_connector_in_state(state, connector, conn_state, i) {
370 const struct drm_encoder_helper_funcs *funcs;
371 struct drm_encoder *encoder;
372
373 WARN_ON(!!conn_state->best_encoder != !!conn_state->crtc);
374
375 if (!conn_state->crtc || !conn_state->best_encoder)
376 continue;
377
378 crtc_state = drm_atomic_get_existing_crtc_state(state,
379 conn_state->crtc);
380
381
382
383
384
385 encoder = conn_state->best_encoder;
386 funcs = encoder->helper_private;
387 if (!funcs)
388 continue;
389
390 ret = drm_bridge_mode_fixup(encoder->bridge, &crtc_state->mode,
391 &crtc_state->adjusted_mode);
392 if (!ret) {
393 DRM_DEBUG_ATOMIC("Bridge fixup failed\n");
394 return -EINVAL;
395 }
396
397 if (funcs->atomic_check) {
398 ret = funcs->atomic_check(encoder, crtc_state,
399 conn_state);
400 if (ret) {
401 DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] check failed\n",
402 encoder->base.id, encoder->name);
403 return ret;
404 }
405 } else if (funcs->mode_fixup) {
406 ret = funcs->mode_fixup(encoder, &crtc_state->mode,
407 &crtc_state->adjusted_mode);
408 if (!ret) {
409 DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] fixup failed\n",
410 encoder->base.id, encoder->name);
411 return -EINVAL;
412 }
413 }
414 }
415
416 for_each_crtc_in_state(state, crtc, crtc_state, i) {
417 const struct drm_crtc_helper_funcs *funcs;
418
419 if (!crtc_state->mode_changed &&
420 !crtc_state->connectors_changed)
421 continue;
422
423 funcs = crtc->helper_private;
424 if (!funcs->mode_fixup)
425 continue;
426
427 ret = funcs->mode_fixup(crtc, &crtc_state->mode,
428 &crtc_state->adjusted_mode);
429 if (!ret) {
430 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] fixup failed\n",
431 crtc->base.id, crtc->name);
432 return -EINVAL;
433 }
434 }
435
436 return 0;
437}
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466int
467drm_atomic_helper_check_modeset(struct drm_device *dev,
468 struct drm_atomic_state *state)
469{
470 struct drm_crtc *crtc;
471 struct drm_crtc_state *crtc_state;
472 struct drm_connector *connector;
473 struct drm_connector_state *connector_state;
474 int i, ret;
475
476 for_each_crtc_in_state(state, crtc, crtc_state, i) {
477 if (!drm_mode_equal(&crtc->state->mode, &crtc_state->mode)) {
478 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode changed\n",
479 crtc->base.id, crtc->name);
480 crtc_state->mode_changed = true;
481 }
482
483 if (crtc->state->enable != crtc_state->enable) {
484 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enable changed\n",
485 crtc->base.id, crtc->name);
486
487
488
489
490
491
492
493
494
495 crtc_state->mode_changed = true;
496 crtc_state->connectors_changed = true;
497 }
498 }
499
500 ret = handle_conflicting_encoders(state, state->legacy_set_config);
501 if (ret)
502 return ret;
503
504 for_each_connector_in_state(state, connector, connector_state, i) {
505
506
507
508
509
510 ret = update_connector_routing(state, connector,
511 connector_state);
512 if (ret)
513 return ret;
514 }
515
516
517
518
519
520
521
522 for_each_crtc_in_state(state, crtc, crtc_state, i) {
523 bool has_connectors =
524 !!crtc_state->connector_mask;
525
526
527
528
529
530
531 if (crtc->state->active != crtc_state->active) {
532 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active changed\n",
533 crtc->base.id, crtc->name);
534 crtc_state->active_changed = true;
535 }
536
537 if (!drm_atomic_crtc_needs_modeset(crtc_state))
538 continue;
539
540 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] needs all connectors, enable: %c, active: %c\n",
541 crtc->base.id, crtc->name,
542 crtc_state->enable ? 'y' : 'n',
543 crtc_state->active ? 'y' : 'n');
544
545 ret = drm_atomic_add_affected_connectors(state, crtc);
546 if (ret != 0)
547 return ret;
548
549 ret = drm_atomic_add_affected_planes(state, crtc);
550 if (ret != 0)
551 return ret;
552
553 if (crtc_state->enable != has_connectors) {
554 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled/connectors mismatch\n",
555 crtc->base.id, crtc->name);
556
557 return -EINVAL;
558 }
559 }
560
561 return mode_fixup(state);
562}
563EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580int
581drm_atomic_helper_check_planes(struct drm_device *dev,
582 struct drm_atomic_state *state)
583{
584 struct drm_crtc *crtc;
585 struct drm_crtc_state *crtc_state;
586 struct drm_plane *plane;
587 struct drm_plane_state *plane_state;
588 int i, ret = 0;
589
590 for_each_plane_in_state(state, plane, plane_state, i) {
591 const struct drm_plane_helper_funcs *funcs;
592
593 funcs = plane->helper_private;
594
595 drm_atomic_helper_plane_changed(state, plane_state, plane);
596
597 if (!funcs || !funcs->atomic_check)
598 continue;
599
600 ret = funcs->atomic_check(plane, plane_state);
601 if (ret) {
602 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] atomic driver check failed\n",
603 plane->base.id, plane->name);
604 return ret;
605 }
606 }
607
608 for_each_crtc_in_state(state, crtc, crtc_state, i) {
609 const struct drm_crtc_helper_funcs *funcs;
610
611 funcs = crtc->helper_private;
612
613 if (!funcs || !funcs->atomic_check)
614 continue;
615
616 ret = funcs->atomic_check(crtc, state->crtc_states[i]);
617 if (ret) {
618 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic driver check failed\n",
619 crtc->base.id, crtc->name);
620 return ret;
621 }
622 }
623
624 return ret;
625}
626EXPORT_SYMBOL(drm_atomic_helper_check_planes);
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648int drm_atomic_helper_check(struct drm_device *dev,
649 struct drm_atomic_state *state)
650{
651 int ret;
652
653 ret = drm_atomic_helper_check_modeset(dev, state);
654 if (ret)
655 return ret;
656
657 ret = drm_atomic_helper_check_planes(dev, state);
658 if (ret)
659 return ret;
660
661 return ret;
662}
663EXPORT_SYMBOL(drm_atomic_helper_check);
664
665static void
666disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
667{
668 struct drm_connector *connector;
669 struct drm_connector_state *old_conn_state;
670 struct drm_crtc *crtc;
671 struct drm_crtc_state *old_crtc_state;
672 int i;
673
674 for_each_connector_in_state(old_state, connector, old_conn_state, i) {
675 const struct drm_encoder_helper_funcs *funcs;
676 struct drm_encoder *encoder;
677
678
679
680 if (!old_conn_state->crtc)
681 continue;
682
683 old_crtc_state = drm_atomic_get_existing_crtc_state(old_state,
684 old_conn_state->crtc);
685
686 if (!old_crtc_state->active ||
687 !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state))
688 continue;
689
690 encoder = old_conn_state->best_encoder;
691
692
693
694
695 if (WARN_ON(!encoder))
696 continue;
697
698 funcs = encoder->helper_private;
699
700 DRM_DEBUG_ATOMIC("disabling [ENCODER:%d:%s]\n",
701 encoder->base.id, encoder->name);
702
703
704
705
706
707 drm_bridge_disable(encoder->bridge);
708
709
710 if (connector->state->crtc && funcs->prepare)
711 funcs->prepare(encoder);
712 else if (funcs->disable)
713 funcs->disable(encoder);
714 else
715 funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
716
717 drm_bridge_post_disable(encoder->bridge);
718 }
719
720 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
721 const struct drm_crtc_helper_funcs *funcs;
722
723
724 if (!drm_atomic_crtc_needs_modeset(crtc->state))
725 continue;
726
727 if (!old_crtc_state->active)
728 continue;
729
730 funcs = crtc->helper_private;
731
732 DRM_DEBUG_ATOMIC("disabling [CRTC:%d:%s]\n",
733 crtc->base.id, crtc->name);
734
735
736
737 if (crtc->state->enable && funcs->prepare)
738 funcs->prepare(crtc);
739 else if (funcs->disable)
740 funcs->disable(crtc);
741 else
742 funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
743 }
744}
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759void
760drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
761 struct drm_atomic_state *old_state)
762{
763 struct drm_connector *connector;
764 struct drm_connector_state *old_conn_state;
765 struct drm_crtc *crtc;
766 struct drm_crtc_state *old_crtc_state;
767 int i;
768
769
770 for_each_connector_in_state(old_state, connector, old_conn_state, i) {
771 if (connector->encoder) {
772 WARN_ON(!connector->encoder->crtc);
773
774 connector->encoder->crtc = NULL;
775 connector->encoder = NULL;
776 }
777
778 crtc = connector->state->crtc;
779 if ((!crtc && old_conn_state->crtc) ||
780 (crtc && drm_atomic_crtc_needs_modeset(crtc->state))) {
781 struct drm_property *dpms_prop =
782 dev->mode_config.dpms_property;
783 int mode = DRM_MODE_DPMS_OFF;
784
785 if (crtc && crtc->state->active)
786 mode = DRM_MODE_DPMS_ON;
787
788 connector->dpms = mode;
789 drm_object_property_set_value(&connector->base,
790 dpms_prop, mode);
791 }
792 }
793
794
795 for_each_connector_in_state(old_state, connector, old_conn_state, i) {
796 if (!connector->state->crtc)
797 continue;
798
799 if (WARN_ON(!connector->state->best_encoder))
800 continue;
801
802 connector->encoder = connector->state->best_encoder;
803 connector->encoder->crtc = connector->state->crtc;
804 }
805
806
807 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
808 struct drm_plane *primary = crtc->primary;
809
810 crtc->mode = crtc->state->mode;
811 crtc->enabled = crtc->state->enable;
812
813 if (drm_atomic_get_existing_plane_state(old_state, primary) &&
814 primary->state->crtc == crtc) {
815 crtc->x = primary->state->src_x >> 16;
816 crtc->y = primary->state->src_y >> 16;
817 }
818
819 if (crtc->state->enable)
820 drm_calc_timestamping_constants(crtc,
821 &crtc->state->adjusted_mode);
822 }
823}
824EXPORT_SYMBOL(drm_atomic_helper_update_legacy_modeset_state);
825
826static void
827crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
828{
829 struct drm_crtc *crtc;
830 struct drm_crtc_state *old_crtc_state;
831 struct drm_connector *connector;
832 struct drm_connector_state *old_conn_state;
833 int i;
834
835 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
836 const struct drm_crtc_helper_funcs *funcs;
837
838 if (!crtc->state->mode_changed)
839 continue;
840
841 funcs = crtc->helper_private;
842
843 if (crtc->state->enable && funcs->mode_set_nofb) {
844 DRM_DEBUG_ATOMIC("modeset on [CRTC:%d:%s]\n",
845 crtc->base.id, crtc->name);
846
847 funcs->mode_set_nofb(crtc);
848 }
849 }
850
851 for_each_connector_in_state(old_state, connector, old_conn_state, i) {
852 const struct drm_encoder_helper_funcs *funcs;
853 struct drm_crtc_state *new_crtc_state;
854 struct drm_encoder *encoder;
855 struct drm_display_mode *mode, *adjusted_mode;
856
857 if (!connector->state->best_encoder)
858 continue;
859
860 encoder = connector->state->best_encoder;
861 funcs = encoder->helper_private;
862 new_crtc_state = connector->state->crtc->state;
863 mode = &new_crtc_state->mode;
864 adjusted_mode = &new_crtc_state->adjusted_mode;
865
866 if (!new_crtc_state->mode_changed)
867 continue;
868
869 DRM_DEBUG_ATOMIC("modeset on [ENCODER:%d:%s]\n",
870 encoder->base.id, encoder->name);
871
872
873
874
875
876 if (funcs->mode_set)
877 funcs->mode_set(encoder, mode, adjusted_mode);
878
879 drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode);
880 }
881}
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev,
898 struct drm_atomic_state *old_state)
899{
900 disable_outputs(dev, old_state);
901
902 drm_atomic_helper_update_legacy_modeset_state(dev, old_state);
903
904 crtc_set_mode(dev, old_state);
905}
906EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_disables);
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
923 struct drm_atomic_state *old_state)
924{
925 struct drm_crtc *crtc;
926 struct drm_crtc_state *old_crtc_state;
927 struct drm_connector *connector;
928 struct drm_connector_state *old_conn_state;
929 int i;
930
931 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
932 const struct drm_crtc_helper_funcs *funcs;
933
934
935 if (!drm_atomic_crtc_needs_modeset(crtc->state))
936 continue;
937
938 if (!crtc->state->active)
939 continue;
940
941 funcs = crtc->helper_private;
942
943 if (crtc->state->enable) {
944 DRM_DEBUG_ATOMIC("enabling [CRTC:%d:%s]\n",
945 crtc->base.id, crtc->name);
946
947 if (funcs->enable)
948 funcs->enable(crtc);
949 else
950 funcs->commit(crtc);
951 }
952 }
953
954 for_each_connector_in_state(old_state, connector, old_conn_state, i) {
955 const struct drm_encoder_helper_funcs *funcs;
956 struct drm_encoder *encoder;
957
958 if (!connector->state->best_encoder)
959 continue;
960
961 if (!connector->state->crtc->state->active ||
962 !drm_atomic_crtc_needs_modeset(connector->state->crtc->state))
963 continue;
964
965 encoder = connector->state->best_encoder;
966 funcs = encoder->helper_private;
967
968 DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n",
969 encoder->base.id, encoder->name);
970
971
972
973
974
975 drm_bridge_pre_enable(encoder->bridge);
976
977 if (funcs->enable)
978 funcs->enable(encoder);
979 else
980 funcs->commit(encoder);
981
982 drm_bridge_enable(encoder->bridge);
983 }
984}
985EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables);
986
987static void wait_for_fences(struct drm_device *dev,
988 struct drm_atomic_state *state)
989{
990 struct drm_plane *plane;
991 struct drm_plane_state *plane_state;
992 int i;
993
994 for_each_plane_in_state(state, plane, plane_state, i) {
995 if (!plane->state->fence)
996 continue;
997
998 WARN_ON(!plane->state->fb);
999
1000 fence_wait(plane->state->fence, false);
1001 fence_put(plane->state->fence);
1002 plane->state->fence = NULL;
1003 }
1004}
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev,
1021 struct drm_atomic_state *old_state,
1022 struct drm_crtc *crtc)
1023{
1024 struct drm_plane *plane;
1025 struct drm_plane_state *old_plane_state;
1026 int i;
1027
1028 for_each_plane_in_state(old_state, plane, old_plane_state, i) {
1029 if (plane->state->crtc != crtc &&
1030 old_plane_state->crtc != crtc)
1031 continue;
1032
1033 if (plane->state->fb != old_plane_state->fb)
1034 return true;
1035 }
1036
1037 return false;
1038}
1039EXPORT_SYMBOL(drm_atomic_helper_framebuffer_changed);
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052void
1053drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
1054 struct drm_atomic_state *old_state)
1055{
1056 struct drm_crtc *crtc;
1057 struct drm_crtc_state *old_crtc_state;
1058 int i, ret;
1059
1060 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
1061
1062
1063
1064 old_crtc_state->enable = false;
1065
1066 if (!crtc->state->enable)
1067 continue;
1068
1069
1070
1071 if (old_state->legacy_cursor_update)
1072 continue;
1073
1074 if (!drm_atomic_helper_framebuffer_changed(dev,
1075 old_state, crtc))
1076 continue;
1077
1078 ret = drm_crtc_vblank_get(crtc);
1079 if (ret != 0)
1080 continue;
1081
1082 old_crtc_state->enable = true;
1083 old_crtc_state->last_vblank_count = drm_crtc_vblank_count(crtc);
1084 }
1085
1086 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
1087 if (!old_crtc_state->enable)
1088 continue;
1089
1090 ret = wait_event_timeout(dev->vblank[i].queue,
1091 old_crtc_state->last_vblank_count !=
1092 drm_crtc_vblank_count(crtc),
1093 msecs_to_jiffies(50));
1094
1095 drm_crtc_vblank_put(crtc);
1096 }
1097}
1098EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129int drm_atomic_helper_commit(struct drm_device *dev,
1130 struct drm_atomic_state *state,
1131 bool async)
1132{
1133 int ret;
1134
1135 if (async)
1136 return -EBUSY;
1137
1138 ret = drm_atomic_helper_prepare_planes(dev, state);
1139 if (ret)
1140 return ret;
1141
1142
1143
1144
1145
1146
1147
1148 drm_atomic_helper_swap_state(dev, state);
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166 wait_for_fences(dev, state);
1167
1168 drm_atomic_helper_commit_modeset_disables(dev, state);
1169
1170 drm_atomic_helper_commit_planes(dev, state, false);
1171
1172 drm_atomic_helper_commit_modeset_enables(dev, state);
1173
1174 drm_atomic_helper_wait_for_vblanks(dev, state);
1175
1176 drm_atomic_helper_cleanup_planes(dev, state);
1177
1178 drm_atomic_state_free(state);
1179
1180 return 0;
1181}
1182EXPORT_SYMBOL(drm_atomic_helper_commit);
1183
1184
1185
1186
1187
1188
1189
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
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234int drm_atomic_helper_prepare_planes(struct drm_device *dev,
1235 struct drm_atomic_state *state)
1236{
1237 int nplanes = dev->mode_config.num_total_plane;
1238 int ret, i;
1239
1240 for (i = 0; i < nplanes; i++) {
1241 const struct drm_plane_helper_funcs *funcs;
1242 struct drm_plane *plane = state->planes[i];
1243 struct drm_plane_state *plane_state = state->plane_states[i];
1244
1245 if (!plane)
1246 continue;
1247
1248 funcs = plane->helper_private;
1249
1250 if (funcs->prepare_fb) {
1251 ret = funcs->prepare_fb(plane, plane_state);
1252 if (ret)
1253 goto fail;
1254 }
1255 }
1256
1257 return 0;
1258
1259fail:
1260 for (i--; i >= 0; i--) {
1261 const struct drm_plane_helper_funcs *funcs;
1262 struct drm_plane *plane = state->planes[i];
1263 struct drm_plane_state *plane_state = state->plane_states[i];
1264
1265 if (!plane)
1266 continue;
1267
1268 funcs = plane->helper_private;
1269
1270 if (funcs->cleanup_fb)
1271 funcs->cleanup_fb(plane, plane_state);
1272
1273 }
1274
1275 return ret;
1276}
1277EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
1278
1279bool plane_crtc_active(struct drm_plane_state *state)
1280{
1281 return state->crtc && state->crtc->state->active;
1282}
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318void drm_atomic_helper_commit_planes(struct drm_device *dev,
1319 struct drm_atomic_state *old_state,
1320 bool active_only)
1321{
1322 struct drm_crtc *crtc;
1323 struct drm_crtc_state *old_crtc_state;
1324 struct drm_plane *plane;
1325 struct drm_plane_state *old_plane_state;
1326 int i;
1327
1328 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
1329 const struct drm_crtc_helper_funcs *funcs;
1330
1331 funcs = crtc->helper_private;
1332
1333 if (!funcs || !funcs->atomic_begin)
1334 continue;
1335
1336 if (active_only && !crtc->state->active)
1337 continue;
1338
1339 funcs->atomic_begin(crtc, old_crtc_state);
1340 }
1341
1342 for_each_plane_in_state(old_state, plane, old_plane_state, i) {
1343 const struct drm_plane_helper_funcs *funcs;
1344 bool disabling;
1345
1346 funcs = plane->helper_private;
1347
1348 if (!funcs)
1349 continue;
1350
1351 disabling = drm_atomic_plane_disabling(plane, old_plane_state);
1352
1353 if (active_only) {
1354
1355
1356
1357
1358
1359
1360
1361 if (!disabling && !plane_crtc_active(plane->state))
1362 continue;
1363 if (disabling && !plane_crtc_active(old_plane_state))
1364 continue;
1365 }
1366
1367
1368
1369
1370 if (disabling && funcs->atomic_disable)
1371 funcs->atomic_disable(plane, old_plane_state);
1372 else if (plane->state->crtc || disabling)
1373 funcs->atomic_update(plane, old_plane_state);
1374 }
1375
1376 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
1377 const struct drm_crtc_helper_funcs *funcs;
1378
1379 funcs = crtc->helper_private;
1380
1381 if (!funcs || !funcs->atomic_flush)
1382 continue;
1383
1384 if (active_only && !crtc->state->active)
1385 continue;
1386
1387 funcs->atomic_flush(crtc, old_crtc_state);
1388 }
1389}
1390EXPORT_SYMBOL(drm_atomic_helper_commit_planes);
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409void
1410drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state)
1411{
1412 const struct drm_crtc_helper_funcs *crtc_funcs;
1413 struct drm_crtc *crtc = old_crtc_state->crtc;
1414 struct drm_atomic_state *old_state = old_crtc_state->state;
1415 struct drm_plane *plane;
1416 unsigned plane_mask;
1417
1418 plane_mask = old_crtc_state->plane_mask;
1419 plane_mask |= crtc->state->plane_mask;
1420
1421 crtc_funcs = crtc->helper_private;
1422 if (crtc_funcs && crtc_funcs->atomic_begin)
1423 crtc_funcs->atomic_begin(crtc, old_crtc_state);
1424
1425 drm_for_each_plane_mask(plane, crtc->dev, plane_mask) {
1426 struct drm_plane_state *old_plane_state =
1427 drm_atomic_get_existing_plane_state(old_state, plane);
1428 const struct drm_plane_helper_funcs *plane_funcs;
1429
1430 plane_funcs = plane->helper_private;
1431
1432 if (!old_plane_state || !plane_funcs)
1433 continue;
1434
1435 WARN_ON(plane->state->crtc && plane->state->crtc != crtc);
1436
1437 if (drm_atomic_plane_disabling(plane, old_plane_state) &&
1438 plane_funcs->atomic_disable)
1439 plane_funcs->atomic_disable(plane, old_plane_state);
1440 else if (plane->state->crtc ||
1441 drm_atomic_plane_disabling(plane, old_plane_state))
1442 plane_funcs->atomic_update(plane, old_plane_state);
1443 }
1444
1445 if (crtc_funcs && crtc_funcs->atomic_flush)
1446 crtc_funcs->atomic_flush(crtc, old_crtc_state);
1447}
1448EXPORT_SYMBOL(drm_atomic_helper_commit_planes_on_crtc);
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466void drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc *crtc,
1467 bool atomic)
1468{
1469 const struct drm_crtc_helper_funcs *crtc_funcs =
1470 crtc->helper_private;
1471 struct drm_plane *plane;
1472
1473 if (atomic && crtc_funcs && crtc_funcs->atomic_begin)
1474 crtc_funcs->atomic_begin(crtc, NULL);
1475
1476 drm_for_each_plane(plane, crtc->dev) {
1477 const struct drm_plane_helper_funcs *plane_funcs =
1478 plane->helper_private;
1479
1480 if (plane->state->crtc != crtc || !plane_funcs)
1481 continue;
1482
1483 WARN_ON(!plane_funcs->atomic_disable);
1484 if (plane_funcs->atomic_disable)
1485 plane_funcs->atomic_disable(plane, NULL);
1486 }
1487
1488 if (atomic && crtc_funcs && crtc_funcs->atomic_flush)
1489 crtc_funcs->atomic_flush(crtc, NULL);
1490}
1491EXPORT_SYMBOL(drm_atomic_helper_disable_planes_on_crtc);
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
1506 struct drm_atomic_state *old_state)
1507{
1508 struct drm_plane *plane;
1509 struct drm_plane_state *plane_state;
1510 int i;
1511
1512 for_each_plane_in_state(old_state, plane, plane_state, i) {
1513 const struct drm_plane_helper_funcs *funcs;
1514
1515 funcs = plane->helper_private;
1516
1517 if (funcs->cleanup_fb)
1518 funcs->cleanup_fb(plane, plane_state);
1519 }
1520}
1521EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548void drm_atomic_helper_swap_state(struct drm_device *dev,
1549 struct drm_atomic_state *state)
1550{
1551 int i;
1552
1553 for (i = 0; i < state->num_connector; i++) {
1554 struct drm_connector *connector = state->connectors[i];
1555
1556 if (!connector)
1557 continue;
1558
1559 connector->state->state = state;
1560 swap(state->connector_states[i], connector->state);
1561 connector->state->state = NULL;
1562 }
1563
1564 for (i = 0; i < dev->mode_config.num_crtc; i++) {
1565 struct drm_crtc *crtc = state->crtcs[i];
1566
1567 if (!crtc)
1568 continue;
1569
1570 crtc->state->state = state;
1571 swap(state->crtc_states[i], crtc->state);
1572 crtc->state->state = NULL;
1573 }
1574
1575 for (i = 0; i < dev->mode_config.num_total_plane; i++) {
1576 struct drm_plane *plane = state->planes[i];
1577
1578 if (!plane)
1579 continue;
1580
1581 plane->state->state = state;
1582 swap(state->plane_states[i], plane->state);
1583 plane->state->state = NULL;
1584 }
1585}
1586EXPORT_SYMBOL(drm_atomic_helper_swap_state);
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607int drm_atomic_helper_update_plane(struct drm_plane *plane,
1608 struct drm_crtc *crtc,
1609 struct drm_framebuffer *fb,
1610 int crtc_x, int crtc_y,
1611 unsigned int crtc_w, unsigned int crtc_h,
1612 uint32_t src_x, uint32_t src_y,
1613 uint32_t src_w, uint32_t src_h)
1614{
1615 struct drm_atomic_state *state;
1616 struct drm_plane_state *plane_state;
1617 int ret = 0;
1618
1619 state = drm_atomic_state_alloc(plane->dev);
1620 if (!state)
1621 return -ENOMEM;
1622
1623 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
1624retry:
1625 plane_state = drm_atomic_get_plane_state(state, plane);
1626 if (IS_ERR(plane_state)) {
1627 ret = PTR_ERR(plane_state);
1628 goto fail;
1629 }
1630
1631 ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
1632 if (ret != 0)
1633 goto fail;
1634 drm_atomic_set_fb_for_plane(plane_state, fb);
1635 plane_state->crtc_x = crtc_x;
1636 plane_state->crtc_y = crtc_y;
1637 plane_state->crtc_w = crtc_w;
1638 plane_state->crtc_h = crtc_h;
1639 plane_state->src_x = src_x;
1640 plane_state->src_y = src_y;
1641 plane_state->src_w = src_w;
1642 plane_state->src_h = src_h;
1643
1644 if (plane == crtc->cursor)
1645 state->legacy_cursor_update = true;
1646
1647 ret = drm_atomic_commit(state);
1648 if (ret != 0)
1649 goto fail;
1650
1651
1652 return 0;
1653fail:
1654 if (ret == -EDEADLK)
1655 goto backoff;
1656
1657 drm_atomic_state_free(state);
1658
1659 return ret;
1660backoff:
1661 drm_atomic_state_clear(state);
1662 drm_atomic_legacy_backoff(state);
1663
1664
1665
1666
1667
1668
1669 plane->old_fb = plane->fb;
1670
1671 goto retry;
1672}
1673EXPORT_SYMBOL(drm_atomic_helper_update_plane);
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684int drm_atomic_helper_disable_plane(struct drm_plane *plane)
1685{
1686 struct drm_atomic_state *state;
1687 struct drm_plane_state *plane_state;
1688 int ret = 0;
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698 if (!plane->crtc)
1699 return 0;
1700
1701 state = drm_atomic_state_alloc(plane->dev);
1702 if (!state)
1703 return -ENOMEM;
1704
1705 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(plane->crtc);
1706retry:
1707 plane_state = drm_atomic_get_plane_state(state, plane);
1708 if (IS_ERR(plane_state)) {
1709 ret = PTR_ERR(plane_state);
1710 goto fail;
1711 }
1712
1713 if (plane_state->crtc && (plane == plane->crtc->cursor))
1714 plane_state->state->legacy_cursor_update = true;
1715
1716 ret = __drm_atomic_helper_disable_plane(plane, plane_state);
1717 if (ret != 0)
1718 goto fail;
1719
1720 ret = drm_atomic_commit(state);
1721 if (ret != 0)
1722 goto fail;
1723
1724
1725 return 0;
1726fail:
1727 if (ret == -EDEADLK)
1728 goto backoff;
1729
1730 drm_atomic_state_free(state);
1731
1732 return ret;
1733backoff:
1734 drm_atomic_state_clear(state);
1735 drm_atomic_legacy_backoff(state);
1736
1737
1738
1739
1740
1741
1742 plane->old_fb = plane->fb;
1743
1744 goto retry;
1745}
1746EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
1747
1748
1749int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
1750 struct drm_plane_state *plane_state)
1751{
1752 int ret;
1753
1754 ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
1755 if (ret != 0)
1756 return ret;
1757
1758 drm_atomic_set_fb_for_plane(plane_state, NULL);
1759 plane_state->crtc_x = 0;
1760 plane_state->crtc_y = 0;
1761 plane_state->crtc_w = 0;
1762 plane_state->crtc_h = 0;
1763 plane_state->src_x = 0;
1764 plane_state->src_y = 0;
1765 plane_state->src_w = 0;
1766 plane_state->src_h = 0;
1767
1768 return 0;
1769}
1770
1771static int update_output_state(struct drm_atomic_state *state,
1772 struct drm_mode_set *set)
1773{
1774 struct drm_device *dev = set->crtc->dev;
1775 struct drm_crtc *crtc;
1776 struct drm_crtc_state *crtc_state;
1777 struct drm_connector *connector;
1778 struct drm_connector_state *conn_state;
1779 int ret, i;
1780
1781 ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
1782 state->acquire_ctx);
1783 if (ret)
1784 return ret;
1785
1786
1787 ret = drm_atomic_add_affected_connectors(state, set->crtc);
1788 if (ret)
1789 return ret;
1790
1791 for_each_connector_in_state(state, connector, conn_state, i) {
1792 if (conn_state->crtc == set->crtc) {
1793 ret = drm_atomic_set_crtc_for_connector(conn_state,
1794 NULL);
1795 if (ret)
1796 return ret;
1797 }
1798 }
1799
1800
1801 for (i = 0; i < set->num_connectors; i++) {
1802 conn_state = drm_atomic_get_connector_state(state,
1803 set->connectors[i]);
1804 if (IS_ERR(conn_state))
1805 return PTR_ERR(conn_state);
1806
1807 ret = drm_atomic_set_crtc_for_connector(conn_state,
1808 set->crtc);
1809 if (ret)
1810 return ret;
1811 }
1812
1813 for_each_crtc_in_state(state, crtc, crtc_state, i) {
1814
1815
1816
1817
1818 if (crtc == set->crtc)
1819 continue;
1820
1821 if (!crtc_state->connector_mask) {
1822 ret = drm_atomic_set_mode_prop_for_crtc(crtc_state,
1823 NULL);
1824 if (ret < 0)
1825 return ret;
1826
1827 crtc_state->active = false;
1828 }
1829 }
1830
1831 return 0;
1832}
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843int drm_atomic_helper_set_config(struct drm_mode_set *set)
1844{
1845 struct drm_atomic_state *state;
1846 struct drm_crtc *crtc = set->crtc;
1847 int ret = 0;
1848
1849 state = drm_atomic_state_alloc(crtc->dev);
1850 if (!state)
1851 return -ENOMEM;
1852
1853 state->legacy_set_config = true;
1854 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
1855retry:
1856 ret = __drm_atomic_helper_set_config(set, state);
1857 if (ret != 0)
1858 goto fail;
1859
1860 ret = drm_atomic_commit(state);
1861 if (ret != 0)
1862 goto fail;
1863
1864
1865 return 0;
1866fail:
1867 if (ret == -EDEADLK)
1868 goto backoff;
1869
1870 drm_atomic_state_free(state);
1871
1872 return ret;
1873backoff:
1874 drm_atomic_state_clear(state);
1875 drm_atomic_legacy_backoff(state);
1876
1877
1878
1879
1880
1881
1882 crtc->primary->old_fb = crtc->primary->fb;
1883
1884 goto retry;
1885}
1886EXPORT_SYMBOL(drm_atomic_helper_set_config);
1887
1888
1889int __drm_atomic_helper_set_config(struct drm_mode_set *set,
1890 struct drm_atomic_state *state)
1891{
1892 struct drm_crtc_state *crtc_state;
1893 struct drm_plane_state *primary_state;
1894 struct drm_crtc *crtc = set->crtc;
1895 int hdisplay, vdisplay;
1896 int ret;
1897
1898 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1899 if (IS_ERR(crtc_state))
1900 return PTR_ERR(crtc_state);
1901
1902 primary_state = drm_atomic_get_plane_state(state, crtc->primary);
1903 if (IS_ERR(primary_state))
1904 return PTR_ERR(primary_state);
1905
1906 if (!set->mode) {
1907 WARN_ON(set->fb);
1908 WARN_ON(set->num_connectors);
1909
1910 ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
1911 if (ret != 0)
1912 return ret;
1913
1914 crtc_state->active = false;
1915
1916 ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
1917 if (ret != 0)
1918 return ret;
1919
1920 drm_atomic_set_fb_for_plane(primary_state, NULL);
1921
1922 goto commit;
1923 }
1924
1925 WARN_ON(!set->fb);
1926 WARN_ON(!set->num_connectors);
1927
1928 ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode);
1929 if (ret != 0)
1930 return ret;
1931
1932 crtc_state->active = true;
1933
1934 ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
1935 if (ret != 0)
1936 return ret;
1937
1938 drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay);
1939
1940 drm_atomic_set_fb_for_plane(primary_state, set->fb);
1941 primary_state->crtc_x = 0;
1942 primary_state->crtc_y = 0;
1943 primary_state->crtc_w = hdisplay;
1944 primary_state->crtc_h = vdisplay;
1945 primary_state->src_x = set->x << 16;
1946 primary_state->src_y = set->y << 16;
1947 if (primary_state->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) {
1948 primary_state->src_w = vdisplay << 16;
1949 primary_state->src_h = hdisplay << 16;
1950 } else {
1951 primary_state->src_w = hdisplay << 16;
1952 primary_state->src_h = vdisplay << 16;
1953 }
1954
1955commit:
1956 ret = update_output_state(state, set);
1957 if (ret)
1958 return ret;
1959
1960 return 0;
1961}
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984int drm_atomic_helper_disable_all(struct drm_device *dev,
1985 struct drm_modeset_acquire_ctx *ctx)
1986{
1987 struct drm_atomic_state *state;
1988 struct drm_connector *conn;
1989 int err;
1990
1991 state = drm_atomic_state_alloc(dev);
1992 if (!state)
1993 return -ENOMEM;
1994
1995 state->acquire_ctx = ctx;
1996
1997 drm_for_each_connector(conn, dev) {
1998 struct drm_crtc *crtc = conn->state->crtc;
1999 struct drm_crtc_state *crtc_state;
2000
2001 if (!crtc || conn->dpms != DRM_MODE_DPMS_ON)
2002 continue;
2003
2004 crtc_state = drm_atomic_get_crtc_state(state, crtc);
2005 if (IS_ERR(crtc_state)) {
2006 err = PTR_ERR(crtc_state);
2007 goto free;
2008 }
2009
2010 crtc_state->active = false;
2011 }
2012
2013 err = drm_atomic_commit(state);
2014
2015free:
2016 if (err < 0)
2017 drm_atomic_state_free(state);
2018
2019 return err;
2020}
2021EXPORT_SYMBOL(drm_atomic_helper_disable_all);
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev)
2049{
2050 struct drm_modeset_acquire_ctx ctx;
2051 struct drm_atomic_state *state;
2052 int err;
2053
2054 drm_modeset_acquire_init(&ctx, 0);
2055
2056retry:
2057 err = drm_modeset_lock_all_ctx(dev, &ctx);
2058 if (err < 0) {
2059 state = ERR_PTR(err);
2060 goto unlock;
2061 }
2062
2063 state = drm_atomic_helper_duplicate_state(dev, &ctx);
2064 if (IS_ERR(state))
2065 goto unlock;
2066
2067 err = drm_atomic_helper_disable_all(dev, &ctx);
2068 if (err < 0) {
2069 drm_atomic_state_free(state);
2070 state = ERR_PTR(err);
2071 goto unlock;
2072 }
2073
2074unlock:
2075 if (PTR_ERR(state) == -EDEADLK) {
2076 drm_modeset_backoff(&ctx);
2077 goto retry;
2078 }
2079
2080 drm_modeset_drop_locks(&ctx);
2081 drm_modeset_acquire_fini(&ctx);
2082 return state;
2083}
2084EXPORT_SYMBOL(drm_atomic_helper_suspend);
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102int drm_atomic_helper_resume(struct drm_device *dev,
2103 struct drm_atomic_state *state)
2104{
2105 struct drm_mode_config *config = &dev->mode_config;
2106 int err;
2107
2108 drm_mode_config_reset(dev);
2109 drm_modeset_lock_all(dev);
2110 state->acquire_ctx = config->acquire_ctx;
2111 err = drm_atomic_commit(state);
2112 drm_modeset_unlock_all(dev);
2113
2114 return err;
2115}
2116EXPORT_SYMBOL(drm_atomic_helper_resume);
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130int
2131drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc,
2132 struct drm_property *property,
2133 uint64_t val)
2134{
2135 struct drm_atomic_state *state;
2136 struct drm_crtc_state *crtc_state;
2137 int ret = 0;
2138
2139 state = drm_atomic_state_alloc(crtc->dev);
2140 if (!state)
2141 return -ENOMEM;
2142
2143
2144 state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
2145retry:
2146 crtc_state = drm_atomic_get_crtc_state(state, crtc);
2147 if (IS_ERR(crtc_state)) {
2148 ret = PTR_ERR(crtc_state);
2149 goto fail;
2150 }
2151
2152 ret = drm_atomic_crtc_set_property(crtc, crtc_state,
2153 property, val);
2154 if (ret)
2155 goto fail;
2156
2157 ret = drm_atomic_commit(state);
2158 if (ret != 0)
2159 goto fail;
2160
2161
2162 return 0;
2163fail:
2164 if (ret == -EDEADLK)
2165 goto backoff;
2166
2167 drm_atomic_state_free(state);
2168
2169 return ret;
2170backoff:
2171 drm_atomic_state_clear(state);
2172 drm_atomic_legacy_backoff(state);
2173
2174 goto retry;
2175}
2176EXPORT_SYMBOL(drm_atomic_helper_crtc_set_property);
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190int
2191drm_atomic_helper_plane_set_property(struct drm_plane *plane,
2192 struct drm_property *property,
2193 uint64_t val)
2194{
2195 struct drm_atomic_state *state;
2196 struct drm_plane_state *plane_state;
2197 int ret = 0;
2198
2199 state = drm_atomic_state_alloc(plane->dev);
2200 if (!state)
2201 return -ENOMEM;
2202
2203
2204 state->acquire_ctx = plane->dev->mode_config.acquire_ctx;
2205retry:
2206 plane_state = drm_atomic_get_plane_state(state, plane);
2207 if (IS_ERR(plane_state)) {
2208 ret = PTR_ERR(plane_state);
2209 goto fail;
2210 }
2211
2212 ret = drm_atomic_plane_set_property(plane, plane_state,
2213 property, val);
2214 if (ret)
2215 goto fail;
2216
2217 ret = drm_atomic_commit(state);
2218 if (ret != 0)
2219 goto fail;
2220
2221
2222 return 0;
2223fail:
2224 if (ret == -EDEADLK)
2225 goto backoff;
2226
2227 drm_atomic_state_free(state);
2228
2229 return ret;
2230backoff:
2231 drm_atomic_state_clear(state);
2232 drm_atomic_legacy_backoff(state);
2233
2234 goto retry;
2235}
2236EXPORT_SYMBOL(drm_atomic_helper_plane_set_property);
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250int
2251drm_atomic_helper_connector_set_property(struct drm_connector *connector,
2252 struct drm_property *property,
2253 uint64_t val)
2254{
2255 struct drm_atomic_state *state;
2256 struct drm_connector_state *connector_state;
2257 int ret = 0;
2258
2259 state = drm_atomic_state_alloc(connector->dev);
2260 if (!state)
2261 return -ENOMEM;
2262
2263
2264 state->acquire_ctx = connector->dev->mode_config.acquire_ctx;
2265retry:
2266 connector_state = drm_atomic_get_connector_state(state, connector);
2267 if (IS_ERR(connector_state)) {
2268 ret = PTR_ERR(connector_state);
2269 goto fail;
2270 }
2271
2272 ret = drm_atomic_connector_set_property(connector, connector_state,
2273 property, val);
2274 if (ret)
2275 goto fail;
2276
2277 ret = drm_atomic_commit(state);
2278 if (ret != 0)
2279 goto fail;
2280
2281
2282 return 0;
2283fail:
2284 if (ret == -EDEADLK)
2285 goto backoff;
2286
2287 drm_atomic_state_free(state);
2288
2289 return ret;
2290backoff:
2291 drm_atomic_state_clear(state);
2292 drm_atomic_legacy_backoff(state);
2293
2294 goto retry;
2295}
2296EXPORT_SYMBOL(drm_atomic_helper_connector_set_property);
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
2315 struct drm_framebuffer *fb,
2316 struct drm_pending_vblank_event *event,
2317 uint32_t flags)
2318{
2319 struct drm_plane *plane = crtc->primary;
2320 struct drm_atomic_state *state;
2321 struct drm_plane_state *plane_state;
2322 struct drm_crtc_state *crtc_state;
2323 int ret = 0;
2324
2325 if (flags & DRM_MODE_PAGE_FLIP_ASYNC)
2326 return -EINVAL;
2327
2328 state = drm_atomic_state_alloc(plane->dev);
2329 if (!state)
2330 return -ENOMEM;
2331
2332 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
2333retry:
2334 crtc_state = drm_atomic_get_crtc_state(state, crtc);
2335 if (IS_ERR(crtc_state)) {
2336 ret = PTR_ERR(crtc_state);
2337 goto fail;
2338 }
2339 crtc_state->event = event;
2340
2341 plane_state = drm_atomic_get_plane_state(state, plane);
2342 if (IS_ERR(plane_state)) {
2343 ret = PTR_ERR(plane_state);
2344 goto fail;
2345 }
2346
2347 ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
2348 if (ret != 0)
2349 goto fail;
2350 drm_atomic_set_fb_for_plane(plane_state, fb);
2351
2352
2353 state->allow_modeset = false;
2354 if (!crtc_state->active) {
2355 DRM_DEBUG_ATOMIC("[CRTC:%d] disabled, rejecting legacy flip\n",
2356 crtc->base.id);
2357 ret = -EINVAL;
2358 goto fail;
2359 }
2360
2361 ret = drm_atomic_async_commit(state);
2362 if (ret != 0)
2363 goto fail;
2364
2365
2366 return 0;
2367fail:
2368 if (ret == -EDEADLK)
2369 goto backoff;
2370
2371 drm_atomic_state_free(state);
2372
2373 return ret;
2374backoff:
2375 drm_atomic_state_clear(state);
2376 drm_atomic_legacy_backoff(state);
2377
2378
2379
2380
2381
2382
2383 plane->old_fb = plane->fb;
2384
2385 goto retry;
2386}
2387EXPORT_SYMBOL(drm_atomic_helper_page_flip);
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402int drm_atomic_helper_connector_dpms(struct drm_connector *connector,
2403 int mode)
2404{
2405 struct drm_mode_config *config = &connector->dev->mode_config;
2406 struct drm_atomic_state *state;
2407 struct drm_crtc_state *crtc_state;
2408 struct drm_crtc *crtc;
2409 struct drm_connector *tmp_connector;
2410 int ret;
2411 bool active = false;
2412 int old_mode = connector->dpms;
2413
2414 if (mode != DRM_MODE_DPMS_ON)
2415 mode = DRM_MODE_DPMS_OFF;
2416
2417 connector->dpms = mode;
2418 crtc = connector->state->crtc;
2419
2420 if (!crtc)
2421 return 0;
2422
2423 state = drm_atomic_state_alloc(connector->dev);
2424 if (!state)
2425 return -ENOMEM;
2426
2427 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
2428retry:
2429 crtc_state = drm_atomic_get_crtc_state(state, crtc);
2430 if (IS_ERR(crtc_state)) {
2431 ret = PTR_ERR(crtc_state);
2432 goto fail;
2433 }
2434
2435 WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
2436
2437 drm_for_each_connector(tmp_connector, connector->dev) {
2438 if (tmp_connector->state->crtc != crtc)
2439 continue;
2440
2441 if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
2442 active = true;
2443 break;
2444 }
2445 }
2446 crtc_state->active = active;
2447
2448 ret = drm_atomic_commit(state);
2449 if (ret != 0)
2450 goto fail;
2451
2452
2453 return 0;
2454fail:
2455 if (ret == -EDEADLK)
2456 goto backoff;
2457
2458 connector->dpms = old_mode;
2459 drm_atomic_state_free(state);
2460
2461 return ret;
2462backoff:
2463 drm_atomic_state_clear(state);
2464 drm_atomic_legacy_backoff(state);
2465
2466 goto retry;
2467}
2468EXPORT_SYMBOL(drm_atomic_helper_connector_dpms);
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
2499{
2500 if (crtc->state) {
2501 drm_property_unreference_blob(crtc->state->mode_blob);
2502 drm_property_unreference_blob(crtc->state->degamma_lut);
2503 drm_property_unreference_blob(crtc->state->ctm);
2504 drm_property_unreference_blob(crtc->state->gamma_lut);
2505 }
2506 kfree(crtc->state);
2507 crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
2508
2509 if (crtc->state)
2510 crtc->state->crtc = crtc;
2511}
2512EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
2523 struct drm_crtc_state *state)
2524{
2525 memcpy(state, crtc->state, sizeof(*state));
2526
2527 if (state->mode_blob)
2528 drm_property_reference_blob(state->mode_blob);
2529 if (state->degamma_lut)
2530 drm_property_reference_blob(state->degamma_lut);
2531 if (state->ctm)
2532 drm_property_reference_blob(state->ctm);
2533 if (state->gamma_lut)
2534 drm_property_reference_blob(state->gamma_lut);
2535 state->mode_changed = false;
2536 state->active_changed = false;
2537 state->planes_changed = false;
2538 state->connectors_changed = false;
2539 state->color_mgmt_changed = false;
2540 state->event = NULL;
2541}
2542EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
2543
2544
2545
2546
2547
2548
2549
2550
2551struct drm_crtc_state *
2552drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc)
2553{
2554 struct drm_crtc_state *state;
2555
2556 if (WARN_ON(!crtc->state))
2557 return NULL;
2558
2559 state = kmalloc(sizeof(*state), GFP_KERNEL);
2560 if (state)
2561 __drm_atomic_helper_crtc_duplicate_state(crtc, state);
2562
2563 return state;
2564}
2565EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
2577 struct drm_crtc_state *state)
2578{
2579 drm_property_unreference_blob(state->mode_blob);
2580 drm_property_unreference_blob(state->degamma_lut);
2581 drm_property_unreference_blob(state->ctm);
2582 drm_property_unreference_blob(state->gamma_lut);
2583}
2584EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
2595 struct drm_crtc_state *state)
2596{
2597 __drm_atomic_helper_crtc_destroy_state(crtc, state);
2598 kfree(state);
2599}
2600EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
2601
2602
2603
2604
2605
2606
2607
2608
2609void drm_atomic_helper_plane_reset(struct drm_plane *plane)
2610{
2611 if (plane->state && plane->state->fb)
2612 drm_framebuffer_unreference(plane->state->fb);
2613
2614 kfree(plane->state);
2615 plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
2616
2617 if (plane->state) {
2618 plane->state->plane = plane;
2619 plane->state->rotation = BIT(DRM_ROTATE_0);
2620 }
2621}
2622EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
2633 struct drm_plane_state *state)
2634{
2635 memcpy(state, plane->state, sizeof(*state));
2636
2637 if (state->fb)
2638 drm_framebuffer_reference(state->fb);
2639}
2640EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
2641
2642
2643
2644
2645
2646
2647
2648
2649struct drm_plane_state *
2650drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane)
2651{
2652 struct drm_plane_state *state;
2653
2654 if (WARN_ON(!plane->state))
2655 return NULL;
2656
2657 state = kmalloc(sizeof(*state), GFP_KERNEL);
2658 if (state)
2659 __drm_atomic_helper_plane_duplicate_state(plane, state);
2660
2661 return state;
2662}
2663EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674void __drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
2675 struct drm_plane_state *state)
2676{
2677 if (state->fb)
2678 drm_framebuffer_unreference(state->fb);
2679}
2680EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
2691 struct drm_plane_state *state)
2692{
2693 __drm_atomic_helper_plane_destroy_state(plane, state);
2694 kfree(state);
2695}
2696EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709void
2710__drm_atomic_helper_connector_reset(struct drm_connector *connector,
2711 struct drm_connector_state *conn_state)
2712{
2713 if (conn_state)
2714 conn_state->connector = connector;
2715
2716 connector->state = conn_state;
2717}
2718EXPORT_SYMBOL(__drm_atomic_helper_connector_reset);
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728void drm_atomic_helper_connector_reset(struct drm_connector *connector)
2729{
2730 struct drm_connector_state *conn_state =
2731 kzalloc(sizeof(*conn_state), GFP_KERNEL);
2732
2733 kfree(connector->state);
2734 __drm_atomic_helper_connector_reset(connector, conn_state);
2735}
2736EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746void
2747__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
2748 struct drm_connector_state *state)
2749{
2750 memcpy(state, connector->state, sizeof(*state));
2751}
2752EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
2753
2754
2755
2756
2757
2758
2759
2760
2761struct drm_connector_state *
2762drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
2763{
2764 struct drm_connector_state *state;
2765
2766 if (WARN_ON(!connector->state))
2767 return NULL;
2768
2769 state = kmalloc(sizeof(*state), GFP_KERNEL);
2770 if (state)
2771 __drm_atomic_helper_connector_duplicate_state(connector, state);
2772
2773 return state;
2774}
2775EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801struct drm_atomic_state *
2802drm_atomic_helper_duplicate_state(struct drm_device *dev,
2803 struct drm_modeset_acquire_ctx *ctx)
2804{
2805 struct drm_atomic_state *state;
2806 struct drm_connector *conn;
2807 struct drm_plane *plane;
2808 struct drm_crtc *crtc;
2809 int err = 0;
2810
2811 state = drm_atomic_state_alloc(dev);
2812 if (!state)
2813 return ERR_PTR(-ENOMEM);
2814
2815 state->acquire_ctx = ctx;
2816
2817 drm_for_each_crtc(crtc, dev) {
2818 struct drm_crtc_state *crtc_state;
2819
2820 crtc_state = drm_atomic_get_crtc_state(state, crtc);
2821 if (IS_ERR(crtc_state)) {
2822 err = PTR_ERR(crtc_state);
2823 goto free;
2824 }
2825 }
2826
2827 drm_for_each_plane(plane, dev) {
2828 struct drm_plane_state *plane_state;
2829
2830 plane_state = drm_atomic_get_plane_state(state, plane);
2831 if (IS_ERR(plane_state)) {
2832 err = PTR_ERR(plane_state);
2833 goto free;
2834 }
2835 }
2836
2837 drm_for_each_connector(conn, dev) {
2838 struct drm_connector_state *conn_state;
2839
2840 conn_state = drm_atomic_get_connector_state(state, conn);
2841 if (IS_ERR(conn_state)) {
2842 err = PTR_ERR(conn_state);
2843 goto free;
2844 }
2845 }
2846
2847
2848 state->acquire_ctx = NULL;
2849
2850free:
2851 if (err < 0) {
2852 drm_atomic_state_free(state);
2853 state = ERR_PTR(err);
2854 }
2855
2856 return state;
2857}
2858EXPORT_SYMBOL(drm_atomic_helper_duplicate_state);
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869void
2870__drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
2871 struct drm_connector_state *state)
2872{
2873
2874
2875
2876
2877
2878}
2879EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
2890 struct drm_connector_state *state)
2891{
2892 __drm_atomic_helper_connector_destroy_state(connector, state);
2893 kfree(state);
2894}
2895EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
2911 u16 *red, u16 *green, u16 *blue,
2912 uint32_t start, uint32_t size)
2913{
2914 struct drm_device *dev = crtc->dev;
2915 struct drm_mode_config *config = &dev->mode_config;
2916 struct drm_atomic_state *state;
2917 struct drm_crtc_state *crtc_state;
2918 struct drm_property_blob *blob = NULL;
2919 struct drm_color_lut *blob_data;
2920 int i, ret = 0;
2921
2922 state = drm_atomic_state_alloc(crtc->dev);
2923 if (!state)
2924 return;
2925
2926 blob = drm_property_create_blob(dev,
2927 sizeof(struct drm_color_lut) * size,
2928 NULL);
2929 if (IS_ERR(blob)) {
2930 ret = PTR_ERR(blob);
2931 blob = NULL;
2932 goto fail;
2933 }
2934
2935
2936 blob_data = (struct drm_color_lut *) blob->data;
2937 for (i = 0; i < size; i++) {
2938 blob_data[i].red = red[i];
2939 blob_data[i].green = green[i];
2940 blob_data[i].blue = blue[i];
2941 }
2942
2943 state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
2944retry:
2945 crtc_state = drm_atomic_get_crtc_state(state, crtc);
2946 if (IS_ERR(crtc_state)) {
2947 ret = PTR_ERR(crtc_state);
2948 goto fail;
2949 }
2950
2951
2952 ret = drm_atomic_crtc_set_property(crtc, crtc_state,
2953 config->degamma_lut_property, 0);
2954 if (ret)
2955 goto fail;
2956
2957 ret = drm_atomic_crtc_set_property(crtc, crtc_state,
2958 config->ctm_property, 0);
2959 if (ret)
2960 goto fail;
2961
2962 ret = drm_atomic_crtc_set_property(crtc, crtc_state,
2963 config->gamma_lut_property, blob->base.id);
2964 if (ret)
2965 goto fail;
2966
2967 ret = drm_atomic_commit(state);
2968 if (ret)
2969 goto fail;
2970
2971
2972
2973 drm_property_unreference_blob(blob);
2974
2975 return;
2976fail:
2977 if (ret == -EDEADLK)
2978 goto backoff;
2979
2980 drm_atomic_state_free(state);
2981 drm_property_unreference_blob(blob);
2982
2983 return;
2984backoff:
2985 drm_atomic_state_clear(state);
2986 drm_atomic_legacy_backoff(state);
2987
2988 goto retry;
2989}
2990EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
2991