1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#include <drm/drmP.h>
30#include <drm/drm_atomic.h>
31#include <drm/drm_mode.h>
32#include <drm/drm_plane_helper.h>
33#include <drm/drm_print.h>
34#include <linux/sync_file.h>
35
36#include "drm_crtc_internal.h"
37
38void __drm_crtc_commit_free(struct kref *kref)
39{
40 struct drm_crtc_commit *commit =
41 container_of(kref, struct drm_crtc_commit, ref);
42
43 kfree(commit);
44}
45EXPORT_SYMBOL(__drm_crtc_commit_free);
46
47
48
49
50
51
52
53
54
55void drm_atomic_state_default_release(struct drm_atomic_state *state)
56{
57 kfree(state->connectors);
58 kfree(state->crtcs);
59 kfree(state->planes);
60 kfree(state->private_objs);
61}
62EXPORT_SYMBOL(drm_atomic_state_default_release);
63
64
65
66
67
68
69
70
71
72int
73drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
74{
75 kref_init(&state->ref);
76
77
78
79
80 state->allow_modeset = true;
81
82 state->crtcs = kcalloc(dev->mode_config.num_crtc,
83 sizeof(*state->crtcs), GFP_KERNEL);
84 if (!state->crtcs)
85 goto fail;
86 state->planes = kcalloc(dev->mode_config.num_total_plane,
87 sizeof(*state->planes), GFP_KERNEL);
88 if (!state->planes)
89 goto fail;
90
91 state->dev = dev;
92
93 DRM_DEBUG_ATOMIC("Allocated atomic state %p\n", state);
94
95 return 0;
96fail:
97 drm_atomic_state_default_release(state);
98 return -ENOMEM;
99}
100EXPORT_SYMBOL(drm_atomic_state_init);
101
102
103
104
105
106
107
108struct drm_atomic_state *
109drm_atomic_state_alloc(struct drm_device *dev)
110{
111 struct drm_mode_config *config = &dev->mode_config;
112
113 if (!config->funcs->atomic_state_alloc) {
114 struct drm_atomic_state *state;
115
116 state = kzalloc(sizeof(*state), GFP_KERNEL);
117 if (!state)
118 return NULL;
119 if (drm_atomic_state_init(dev, state) < 0) {
120 kfree(state);
121 return NULL;
122 }
123 return state;
124 }
125
126 return config->funcs->atomic_state_alloc(dev);
127}
128EXPORT_SYMBOL(drm_atomic_state_alloc);
129
130
131
132
133
134
135
136
137void drm_atomic_state_default_clear(struct drm_atomic_state *state)
138{
139 struct drm_device *dev = state->dev;
140 struct drm_mode_config *config = &dev->mode_config;
141 int i;
142
143 DRM_DEBUG_ATOMIC("Clearing atomic state %p\n", state);
144
145 for (i = 0; i < state->num_connector; i++) {
146 struct drm_connector *connector = state->connectors[i].ptr;
147
148 if (!connector)
149 continue;
150
151 connector->funcs->atomic_destroy_state(connector,
152 state->connectors[i].state);
153 state->connectors[i].ptr = NULL;
154 state->connectors[i].state = NULL;
155 drm_connector_put(connector);
156 }
157
158 for (i = 0; i < config->num_crtc; i++) {
159 struct drm_crtc *crtc = state->crtcs[i].ptr;
160
161 if (!crtc)
162 continue;
163
164 crtc->funcs->atomic_destroy_state(crtc,
165 state->crtcs[i].state);
166
167 if (state->crtcs[i].commit) {
168 kfree(state->crtcs[i].commit->event);
169 state->crtcs[i].commit->event = NULL;
170 drm_crtc_commit_put(state->crtcs[i].commit);
171 }
172
173 state->crtcs[i].commit = NULL;
174 state->crtcs[i].ptr = NULL;
175 state->crtcs[i].state = NULL;
176 }
177
178 for (i = 0; i < config->num_total_plane; i++) {
179 struct drm_plane *plane = state->planes[i].ptr;
180
181 if (!plane)
182 continue;
183
184 plane->funcs->atomic_destroy_state(plane,
185 state->planes[i].state);
186 state->planes[i].ptr = NULL;
187 state->planes[i].state = NULL;
188 }
189
190 for (i = 0; i < state->num_private_objs; i++) {
191 void *obj_state = state->private_objs[i].obj_state;
192
193 state->private_objs[i].funcs->destroy_state(obj_state);
194 state->private_objs[i].obj = NULL;
195 state->private_objs[i].obj_state = NULL;
196 state->private_objs[i].funcs = NULL;
197 }
198 state->num_private_objs = 0;
199
200}
201EXPORT_SYMBOL(drm_atomic_state_default_clear);
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217void drm_atomic_state_clear(struct drm_atomic_state *state)
218{
219 struct drm_device *dev = state->dev;
220 struct drm_mode_config *config = &dev->mode_config;
221
222 if (config->funcs->atomic_state_clear)
223 config->funcs->atomic_state_clear(state);
224 else
225 drm_atomic_state_default_clear(state);
226}
227EXPORT_SYMBOL(drm_atomic_state_clear);
228
229
230
231
232
233
234
235
236void __drm_atomic_state_free(struct kref *ref)
237{
238 struct drm_atomic_state *state = container_of(ref, typeof(*state), ref);
239 struct drm_mode_config *config = &state->dev->mode_config;
240
241 drm_atomic_state_clear(state);
242
243 DRM_DEBUG_ATOMIC("Freeing atomic state %p\n", state);
244
245 if (config->funcs->atomic_state_free) {
246 config->funcs->atomic_state_free(state);
247 } else {
248 drm_atomic_state_default_release(state);
249 kfree(state);
250 }
251}
252EXPORT_SYMBOL(__drm_atomic_state_free);
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269struct drm_crtc_state *
270drm_atomic_get_crtc_state(struct drm_atomic_state *state,
271 struct drm_crtc *crtc)
272{
273 int ret, index = drm_crtc_index(crtc);
274 struct drm_crtc_state *crtc_state;
275
276 WARN_ON(!state->acquire_ctx);
277
278 crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);
279 if (crtc_state)
280 return crtc_state;
281
282 ret = drm_modeset_lock(&crtc->mutex, state->acquire_ctx);
283 if (ret)
284 return ERR_PTR(ret);
285
286 crtc_state = crtc->funcs->atomic_duplicate_state(crtc);
287 if (!crtc_state)
288 return ERR_PTR(-ENOMEM);
289
290 state->crtcs[index].state = crtc_state;
291 state->crtcs[index].old_state = crtc->state;
292 state->crtcs[index].new_state = crtc_state;
293 state->crtcs[index].ptr = crtc;
294 crtc_state->state = state;
295
296 DRM_DEBUG_ATOMIC("Added [CRTC:%d:%s] %p state to %p\n",
297 crtc->base.id, crtc->name, crtc_state, state);
298
299 return crtc_state;
300}
301EXPORT_SYMBOL(drm_atomic_get_crtc_state);
302
303static void set_out_fence_for_crtc(struct drm_atomic_state *state,
304 struct drm_crtc *crtc, s32 __user *fence_ptr)
305{
306 state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
307}
308
309static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
310 struct drm_crtc *crtc)
311{
312 s32 __user *fence_ptr;
313
314 fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
315 state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
316
317 return fence_ptr;
318}
319
320
321
322
323
324
325
326
327
328
329
330
331int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
332 const struct drm_display_mode *mode)
333{
334 struct drm_mode_modeinfo umode;
335
336
337 if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
338 return 0;
339
340 drm_property_blob_put(state->mode_blob);
341 state->mode_blob = NULL;
342
343 if (mode) {
344 drm_mode_convert_to_umode(&umode, mode);
345 state->mode_blob =
346 drm_property_create_blob(state->crtc->dev,
347 sizeof(umode),
348 &umode);
349 if (IS_ERR(state->mode_blob))
350 return PTR_ERR(state->mode_blob);
351
352 drm_mode_copy(&state->mode, mode);
353 state->enable = true;
354 DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
355 mode->name, state);
356 } else {
357 memset(&state->mode, 0, sizeof(state->mode));
358 state->enable = false;
359 DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n",
360 state);
361 }
362
363 return 0;
364}
365EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
381 struct drm_property_blob *blob)
382{
383 if (blob == state->mode_blob)
384 return 0;
385
386 drm_property_blob_put(state->mode_blob);
387 state->mode_blob = NULL;
388
389 memset(&state->mode, 0, sizeof(state->mode));
390
391 if (blob) {
392 if (blob->length != sizeof(struct drm_mode_modeinfo) ||
393 drm_mode_convert_umode(&state->mode,
394 (const struct drm_mode_modeinfo *)
395 blob->data))
396 return -EINVAL;
397
398 state->mode_blob = drm_property_blob_get(blob);
399 state->enable = true;
400 DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
401 state->mode.name, state);
402 } else {
403 state->enable = false;
404 DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n",
405 state);
406 }
407
408 return 0;
409}
410EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
411
412
413
414
415
416
417
418
419
420
421static void
422drm_atomic_replace_property_blob(struct drm_property_blob **blob,
423 struct drm_property_blob *new_blob,
424 bool *replaced)
425{
426 struct drm_property_blob *old_blob = *blob;
427
428 if (old_blob == new_blob)
429 return;
430
431 drm_property_blob_put(old_blob);
432 if (new_blob)
433 drm_property_blob_get(new_blob);
434 *blob = new_blob;
435 *replaced = true;
436
437 return;
438}
439
440static int
441drm_atomic_replace_property_blob_from_id(struct drm_device *dev,
442 struct drm_property_blob **blob,
443 uint64_t blob_id,
444 ssize_t expected_size,
445 bool *replaced)
446{
447 struct drm_property_blob *new_blob = NULL;
448
449 if (blob_id != 0) {
450 new_blob = drm_property_lookup_blob(dev, blob_id);
451 if (new_blob == NULL)
452 return -EINVAL;
453
454 if (expected_size > 0 && expected_size != new_blob->length) {
455 drm_property_blob_put(new_blob);
456 return -EINVAL;
457 }
458 }
459
460 drm_atomic_replace_property_blob(blob, new_blob, replaced);
461 drm_property_blob_put(new_blob);
462
463 return 0;
464}
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
482 struct drm_crtc_state *state, struct drm_property *property,
483 uint64_t val)
484{
485 struct drm_device *dev = crtc->dev;
486 struct drm_mode_config *config = &dev->mode_config;
487 bool replaced = false;
488 int ret;
489
490 if (property == config->prop_active)
491 state->active = val;
492 else if (property == config->prop_mode_id) {
493 struct drm_property_blob *mode =
494 drm_property_lookup_blob(dev, val);
495 ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
496 drm_property_blob_put(mode);
497 return ret;
498 } else if (property == config->degamma_lut_property) {
499 ret = drm_atomic_replace_property_blob_from_id(dev,
500 &state->degamma_lut,
501 val,
502 -1,
503 &replaced);
504 state->color_mgmt_changed |= replaced;
505 return ret;
506 } else if (property == config->ctm_property) {
507 ret = drm_atomic_replace_property_blob_from_id(dev,
508 &state->ctm,
509 val,
510 sizeof(struct drm_color_ctm),
511 &replaced);
512 state->color_mgmt_changed |= replaced;
513 return ret;
514 } else if (property == config->gamma_lut_property) {
515 ret = drm_atomic_replace_property_blob_from_id(dev,
516 &state->gamma_lut,
517 val,
518 -1,
519 &replaced);
520 state->color_mgmt_changed |= replaced;
521 return ret;
522 } else if (property == config->prop_out_fence_ptr) {
523 s32 __user *fence_ptr = u64_to_user_ptr(val);
524
525 if (!fence_ptr)
526 return 0;
527
528 if (put_user(-1, fence_ptr))
529 return -EFAULT;
530
531 set_out_fence_for_crtc(state->state, crtc, fence_ptr);
532 } else if (crtc->funcs->atomic_set_property)
533 return crtc->funcs->atomic_set_property(crtc, state, property, val);
534 else
535 return -EINVAL;
536
537 return 0;
538}
539EXPORT_SYMBOL(drm_atomic_crtc_set_property);
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556static int
557drm_atomic_crtc_get_property(struct drm_crtc *crtc,
558 const struct drm_crtc_state *state,
559 struct drm_property *property, uint64_t *val)
560{
561 struct drm_device *dev = crtc->dev;
562 struct drm_mode_config *config = &dev->mode_config;
563
564 if (property == config->prop_active)
565 *val = state->active;
566 else if (property == config->prop_mode_id)
567 *val = (state->mode_blob) ? state->mode_blob->base.id : 0;
568 else if (property == config->degamma_lut_property)
569 *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0;
570 else if (property == config->ctm_property)
571 *val = (state->ctm) ? state->ctm->base.id : 0;
572 else if (property == config->gamma_lut_property)
573 *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
574 else if (property == config->prop_out_fence_ptr)
575 *val = 0;
576 else if (crtc->funcs->atomic_get_property)
577 return crtc->funcs->atomic_get_property(crtc, state, property, val);
578 else
579 return -EINVAL;
580
581 return 0;
582}
583
584
585
586
587
588
589
590
591
592
593
594static int drm_atomic_crtc_check(struct drm_crtc *crtc,
595 struct drm_crtc_state *state)
596{
597
598
599
600
601
602
603
604
605 if (state->active && !state->enable) {
606 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active without enabled\n",
607 crtc->base.id, crtc->name);
608 return -EINVAL;
609 }
610
611
612
613
614 if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&
615 WARN_ON(state->enable && !state->mode_blob)) {
616 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled without mode blob\n",
617 crtc->base.id, crtc->name);
618 return -EINVAL;
619 }
620
621 if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&
622 WARN_ON(!state->enable && state->mode_blob)) {
623 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] disabled with mode blob\n",
624 crtc->base.id, crtc->name);
625 return -EINVAL;
626 }
627
628
629
630
631
632
633
634
635
636
637
638 if (state->event && !state->active && !crtc->state->active) {
639 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requesting event but off\n",
640 crtc->base.id, crtc->name);
641 return -EINVAL;
642 }
643
644 return 0;
645}
646
647static void drm_atomic_crtc_print_state(struct drm_printer *p,
648 const struct drm_crtc_state *state)
649{
650 struct drm_crtc *crtc = state->crtc;
651
652 drm_printf(p, "crtc[%u]: %s\n", crtc->base.id, crtc->name);
653 drm_printf(p, "\tenable=%d\n", state->enable);
654 drm_printf(p, "\tactive=%d\n", state->active);
655 drm_printf(p, "\tplanes_changed=%d\n", state->planes_changed);
656 drm_printf(p, "\tmode_changed=%d\n", state->mode_changed);
657 drm_printf(p, "\tactive_changed=%d\n", state->active_changed);
658 drm_printf(p, "\tconnectors_changed=%d\n", state->connectors_changed);
659 drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed);
660 drm_printf(p, "\tplane_mask=%x\n", state->plane_mask);
661 drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask);
662 drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask);
663 drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode));
664
665 if (crtc->funcs->atomic_print_state)
666 crtc->funcs->atomic_print_state(p, state);
667}
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684struct drm_plane_state *
685drm_atomic_get_plane_state(struct drm_atomic_state *state,
686 struct drm_plane *plane)
687{
688 int ret, index = drm_plane_index(plane);
689 struct drm_plane_state *plane_state;
690
691 WARN_ON(!state->acquire_ctx);
692
693 plane_state = drm_atomic_get_existing_plane_state(state, plane);
694 if (plane_state)
695 return plane_state;
696
697 ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx);
698 if (ret)
699 return ERR_PTR(ret);
700
701 plane_state = plane->funcs->atomic_duplicate_state(plane);
702 if (!plane_state)
703 return ERR_PTR(-ENOMEM);
704
705 state->planes[index].state = plane_state;
706 state->planes[index].ptr = plane;
707 state->planes[index].old_state = plane->state;
708 state->planes[index].new_state = plane_state;
709 plane_state->state = state;
710
711 DRM_DEBUG_ATOMIC("Added [PLANE:%d:%s] %p state to %p\n",
712 plane->base.id, plane->name, plane_state, state);
713
714 if (plane_state->crtc) {
715 struct drm_crtc_state *crtc_state;
716
717 crtc_state = drm_atomic_get_crtc_state(state,
718 plane_state->crtc);
719 if (IS_ERR(crtc_state))
720 return ERR_CAST(crtc_state);
721 }
722
723 return plane_state;
724}
725EXPORT_SYMBOL(drm_atomic_get_plane_state);
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742int drm_atomic_plane_set_property(struct drm_plane *plane,
743 struct drm_plane_state *state, struct drm_property *property,
744 uint64_t val)
745{
746 struct drm_device *dev = plane->dev;
747 struct drm_mode_config *config = &dev->mode_config;
748
749 if (property == config->prop_fb_id) {
750 struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, val);
751 drm_atomic_set_fb_for_plane(state, fb);
752 if (fb)
753 drm_framebuffer_put(fb);
754 } else if (property == config->prop_in_fence_fd) {
755 if (state->fence)
756 return -EINVAL;
757
758 if (U642I64(val) == -1)
759 return 0;
760
761 state->fence = sync_file_get_fence(val);
762 if (!state->fence)
763 return -EINVAL;
764
765 } else if (property == config->prop_crtc_id) {
766 struct drm_crtc *crtc = drm_crtc_find(dev, val);
767 return drm_atomic_set_crtc_for_plane(state, crtc);
768 } else if (property == config->prop_crtc_x) {
769 state->crtc_x = U642I64(val);
770 } else if (property == config->prop_crtc_y) {
771 state->crtc_y = U642I64(val);
772 } else if (property == config->prop_crtc_w) {
773 state->crtc_w = val;
774 } else if (property == config->prop_crtc_h) {
775 state->crtc_h = val;
776 } else if (property == config->prop_src_x) {
777 state->src_x = val;
778 } else if (property == config->prop_src_y) {
779 state->src_y = val;
780 } else if (property == config->prop_src_w) {
781 state->src_w = val;
782 } else if (property == config->prop_src_h) {
783 state->src_h = val;
784 } else if (property == plane->rotation_property) {
785 if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK))
786 return -EINVAL;
787 state->rotation = val;
788 } else if (property == plane->zpos_property) {
789 state->zpos = val;
790 } else if (plane->funcs->atomic_set_property) {
791 return plane->funcs->atomic_set_property(plane, state,
792 property, val);
793 } else {
794 return -EINVAL;
795 }
796
797 return 0;
798}
799EXPORT_SYMBOL(drm_atomic_plane_set_property);
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816static int
817drm_atomic_plane_get_property(struct drm_plane *plane,
818 const struct drm_plane_state *state,
819 struct drm_property *property, uint64_t *val)
820{
821 struct drm_device *dev = plane->dev;
822 struct drm_mode_config *config = &dev->mode_config;
823
824 if (property == config->prop_fb_id) {
825 *val = (state->fb) ? state->fb->base.id : 0;
826 } else if (property == config->prop_in_fence_fd) {
827 *val = -1;
828 } else if (property == config->prop_crtc_id) {
829 *val = (state->crtc) ? state->crtc->base.id : 0;
830 } else if (property == config->prop_crtc_x) {
831 *val = I642U64(state->crtc_x);
832 } else if (property == config->prop_crtc_y) {
833 *val = I642U64(state->crtc_y);
834 } else if (property == config->prop_crtc_w) {
835 *val = state->crtc_w;
836 } else if (property == config->prop_crtc_h) {
837 *val = state->crtc_h;
838 } else if (property == config->prop_src_x) {
839 *val = state->src_x;
840 } else if (property == config->prop_src_y) {
841 *val = state->src_y;
842 } else if (property == config->prop_src_w) {
843 *val = state->src_w;
844 } else if (property == config->prop_src_h) {
845 *val = state->src_h;
846 } else if (property == plane->rotation_property) {
847 *val = state->rotation;
848 } else if (property == plane->zpos_property) {
849 *val = state->zpos;
850 } else if (plane->funcs->atomic_get_property) {
851 return plane->funcs->atomic_get_property(plane, state, property, val);
852 } else {
853 return -EINVAL;
854 }
855
856 return 0;
857}
858
859static bool
860plane_switching_crtc(struct drm_atomic_state *state,
861 struct drm_plane *plane,
862 struct drm_plane_state *plane_state)
863{
864 if (!plane->state->crtc || !plane_state->crtc)
865 return false;
866
867 if (plane->state->crtc == plane_state->crtc)
868 return false;
869
870
871
872
873
874
875 return true;
876}
877
878
879
880
881
882
883
884
885
886
887
888static int drm_atomic_plane_check(struct drm_plane *plane,
889 struct drm_plane_state *state)
890{
891 unsigned int fb_width, fb_height;
892 int ret;
893
894
895 if (WARN_ON(state->crtc && !state->fb)) {
896 DRM_DEBUG_ATOMIC("CRTC set but no FB\n");
897 return -EINVAL;
898 } else if (WARN_ON(state->fb && !state->crtc)) {
899 DRM_DEBUG_ATOMIC("FB set but no CRTC\n");
900 return -EINVAL;
901 }
902
903
904 if (!state->crtc)
905 return 0;
906
907
908 if (!(plane->possible_crtcs & drm_crtc_mask(state->crtc))) {
909 DRM_DEBUG_ATOMIC("Invalid crtc for plane\n");
910 return -EINVAL;
911 }
912
913
914 ret = drm_plane_check_pixel_format(plane, state->fb->format->format);
915 if (ret) {
916 struct drm_format_name_buf format_name;
917 DRM_DEBUG_ATOMIC("Invalid pixel format %s\n",
918 drm_get_format_name(state->fb->format->format,
919 &format_name));
920 return ret;
921 }
922
923
924 if (state->crtc_w > INT_MAX ||
925 state->crtc_x > INT_MAX - (int32_t) state->crtc_w ||
926 state->crtc_h > INT_MAX ||
927 state->crtc_y > INT_MAX - (int32_t) state->crtc_h) {
928 DRM_DEBUG_ATOMIC("Invalid CRTC coordinates %ux%u+%d+%d\n",
929 state->crtc_w, state->crtc_h,
930 state->crtc_x, state->crtc_y);
931 return -ERANGE;
932 }
933
934 fb_width = state->fb->width << 16;
935 fb_height = state->fb->height << 16;
936
937
938 if (state->src_w > fb_width ||
939 state->src_x > fb_width - state->src_w ||
940 state->src_h > fb_height ||
941 state->src_y > fb_height - state->src_h) {
942 DRM_DEBUG_ATOMIC("Invalid source coordinates "
943 "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
944 state->src_w >> 16, ((state->src_w & 0xffff) * 15625) >> 10,
945 state->src_h >> 16, ((state->src_h & 0xffff) * 15625) >> 10,
946 state->src_x >> 16, ((state->src_x & 0xffff) * 15625) >> 10,
947 state->src_y >> 16, ((state->src_y & 0xffff) * 15625) >> 10);
948 return -ENOSPC;
949 }
950
951 if (plane_switching_crtc(state->state, plane, state)) {
952 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] switching CRTC directly\n",
953 plane->base.id, plane->name);
954 return -EINVAL;
955 }
956
957 return 0;
958}
959
960static void drm_atomic_plane_print_state(struct drm_printer *p,
961 const struct drm_plane_state *state)
962{
963 struct drm_plane *plane = state->plane;
964 struct drm_rect src = drm_plane_state_src(state);
965 struct drm_rect dest = drm_plane_state_dest(state);
966
967 drm_printf(p, "plane[%u]: %s\n", plane->base.id, plane->name);
968 drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
969 drm_printf(p, "\tfb=%u\n", state->fb ? state->fb->base.id : 0);
970 if (state->fb) {
971 struct drm_framebuffer *fb = state->fb;
972 int i, n = fb->format->num_planes;
973 struct drm_format_name_buf format_name;
974
975 drm_printf(p, "\t\tformat=%s\n",
976 drm_get_format_name(fb->format->format, &format_name));
977 drm_printf(p, "\t\t\tmodifier=0x%llx\n", fb->modifier);
978 drm_printf(p, "\t\tsize=%dx%d\n", fb->width, fb->height);
979 drm_printf(p, "\t\tlayers:\n");
980 for (i = 0; i < n; i++) {
981 drm_printf(p, "\t\t\tpitch[%d]=%u\n", i, fb->pitches[i]);
982 drm_printf(p, "\t\t\toffset[%d]=%u\n", i, fb->offsets[i]);
983 }
984 }
985 drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest));
986 drm_printf(p, "\tsrc-pos=" DRM_RECT_FP_FMT "\n", DRM_RECT_FP_ARG(&src));
987 drm_printf(p, "\trotation=%x\n", state->rotation);
988
989 if (plane->funcs->atomic_print_state)
990 plane->funcs->atomic_print_state(p, state);
991}
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008void *
1009drm_atomic_get_private_obj_state(struct drm_atomic_state *state, void *obj,
1010 const struct drm_private_state_funcs *funcs)
1011{
1012 int index, num_objs, i;
1013 size_t size;
1014 struct __drm_private_objs_state *arr;
1015
1016 for (i = 0; i < state->num_private_objs; i++)
1017 if (obj == state->private_objs[i].obj &&
1018 state->private_objs[i].obj_state)
1019 return state->private_objs[i].obj_state;
1020
1021 num_objs = state->num_private_objs + 1;
1022 size = sizeof(*state->private_objs) * num_objs;
1023 arr = krealloc(state->private_objs, size, GFP_KERNEL);
1024 if (!arr)
1025 return ERR_PTR(-ENOMEM);
1026
1027 state->private_objs = arr;
1028 index = state->num_private_objs;
1029 memset(&state->private_objs[index], 0, sizeof(*state->private_objs));
1030
1031 state->private_objs[index].obj_state = funcs->duplicate_state(state, obj);
1032 if (!state->private_objs[index].obj_state)
1033 return ERR_PTR(-ENOMEM);
1034
1035 state->private_objs[index].obj = obj;
1036 state->private_objs[index].funcs = funcs;
1037 state->num_private_objs = num_objs;
1038
1039 DRM_DEBUG_ATOMIC("Added new private object state %p to %p\n",
1040 state->private_objs[index].obj_state, state);
1041
1042 return state->private_objs[index].obj_state;
1043}
1044EXPORT_SYMBOL(drm_atomic_get_private_obj_state);
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061struct drm_connector_state *
1062drm_atomic_get_connector_state(struct drm_atomic_state *state,
1063 struct drm_connector *connector)
1064{
1065 int ret, index;
1066 struct drm_mode_config *config = &connector->dev->mode_config;
1067 struct drm_connector_state *connector_state;
1068
1069 WARN_ON(!state->acquire_ctx);
1070
1071 ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
1072 if (ret)
1073 return ERR_PTR(ret);
1074
1075 index = drm_connector_index(connector);
1076
1077 if (index >= state->num_connector) {
1078 struct __drm_connnectors_state *c;
1079 int alloc = max(index + 1, config->num_connector);
1080
1081 c = krealloc(state->connectors, alloc * sizeof(*state->connectors), GFP_KERNEL);
1082 if (!c)
1083 return ERR_PTR(-ENOMEM);
1084
1085 state->connectors = c;
1086 memset(&state->connectors[state->num_connector], 0,
1087 sizeof(*state->connectors) * (alloc - state->num_connector));
1088
1089 state->num_connector = alloc;
1090 }
1091
1092 if (state->connectors[index].state)
1093 return state->connectors[index].state;
1094
1095 connector_state = connector->funcs->atomic_duplicate_state(connector);
1096 if (!connector_state)
1097 return ERR_PTR(-ENOMEM);
1098
1099 drm_connector_get(connector);
1100 state->connectors[index].state = connector_state;
1101 state->connectors[index].old_state = connector->state;
1102 state->connectors[index].new_state = connector_state;
1103 state->connectors[index].ptr = connector;
1104 connector_state->state = state;
1105
1106 DRM_DEBUG_ATOMIC("Added [CONNECTOR:%d:%s] %p state to %p\n",
1107 connector->base.id, connector->name,
1108 connector_state, state);
1109
1110 if (connector_state->crtc) {
1111 struct drm_crtc_state *crtc_state;
1112
1113 crtc_state = drm_atomic_get_crtc_state(state,
1114 connector_state->crtc);
1115 if (IS_ERR(crtc_state))
1116 return ERR_CAST(crtc_state);
1117 }
1118
1119 return connector_state;
1120}
1121EXPORT_SYMBOL(drm_atomic_get_connector_state);
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138int drm_atomic_connector_set_property(struct drm_connector *connector,
1139 struct drm_connector_state *state, struct drm_property *property,
1140 uint64_t val)
1141{
1142 struct drm_device *dev = connector->dev;
1143 struct drm_mode_config *config = &dev->mode_config;
1144
1145 if (property == config->prop_crtc_id) {
1146 struct drm_crtc *crtc = drm_crtc_find(dev, val);
1147 return drm_atomic_set_crtc_for_connector(state, crtc);
1148 } else if (property == config->dpms_property) {
1149
1150
1151
1152
1153 return -EINVAL;
1154 } else if (property == config->tv_select_subconnector_property) {
1155 state->tv.subconnector = val;
1156 } else if (property == config->tv_left_margin_property) {
1157 state->tv.margins.left = val;
1158 } else if (property == config->tv_right_margin_property) {
1159 state->tv.margins.right = val;
1160 } else if (property == config->tv_top_margin_property) {
1161 state->tv.margins.top = val;
1162 } else if (property == config->tv_bottom_margin_property) {
1163 state->tv.margins.bottom = val;
1164 } else if (property == config->tv_mode_property) {
1165 state->tv.mode = val;
1166 } else if (property == config->tv_brightness_property) {
1167 state->tv.brightness = val;
1168 } else if (property == config->tv_contrast_property) {
1169 state->tv.contrast = val;
1170 } else if (property == config->tv_flicker_reduction_property) {
1171 state->tv.flicker_reduction = val;
1172 } else if (property == config->tv_overscan_property) {
1173 state->tv.overscan = val;
1174 } else if (property == config->tv_saturation_property) {
1175 state->tv.saturation = val;
1176 } else if (property == config->tv_hue_property) {
1177 state->tv.hue = val;
1178 } else if (property == config->link_status_property) {
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190 if (state->link_status != DRM_LINK_STATUS_GOOD)
1191 state->link_status = val;
1192 } else if (property == config->aspect_ratio_property) {
1193 state->picture_aspect_ratio = val;
1194 } else if (property == connector->scaling_mode_property) {
1195 state->scaling_mode = val;
1196 } else if (connector->funcs->atomic_set_property) {
1197 return connector->funcs->atomic_set_property(connector,
1198 state, property, val);
1199 } else {
1200 return -EINVAL;
1201 }
1202
1203 return 0;
1204}
1205EXPORT_SYMBOL(drm_atomic_connector_set_property);
1206
1207static void drm_atomic_connector_print_state(struct drm_printer *p,
1208 const struct drm_connector_state *state)
1209{
1210 struct drm_connector *connector = state->connector;
1211
1212 drm_printf(p, "connector[%u]: %s\n", connector->base.id, connector->name);
1213 drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
1214
1215 if (connector->funcs->atomic_print_state)
1216 connector->funcs->atomic_print_state(p, state);
1217}
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234static int
1235drm_atomic_connector_get_property(struct drm_connector *connector,
1236 const struct drm_connector_state *state,
1237 struct drm_property *property, uint64_t *val)
1238{
1239 struct drm_device *dev = connector->dev;
1240 struct drm_mode_config *config = &dev->mode_config;
1241
1242 if (property == config->prop_crtc_id) {
1243 *val = (state->crtc) ? state->crtc->base.id : 0;
1244 } else if (property == config->dpms_property) {
1245 *val = connector->dpms;
1246 } else if (property == config->tv_select_subconnector_property) {
1247 *val = state->tv.subconnector;
1248 } else if (property == config->tv_left_margin_property) {
1249 *val = state->tv.margins.left;
1250 } else if (property == config->tv_right_margin_property) {
1251 *val = state->tv.margins.right;
1252 } else if (property == config->tv_top_margin_property) {
1253 *val = state->tv.margins.top;
1254 } else if (property == config->tv_bottom_margin_property) {
1255 *val = state->tv.margins.bottom;
1256 } else if (property == config->tv_mode_property) {
1257 *val = state->tv.mode;
1258 } else if (property == config->tv_brightness_property) {
1259 *val = state->tv.brightness;
1260 } else if (property == config->tv_contrast_property) {
1261 *val = state->tv.contrast;
1262 } else if (property == config->tv_flicker_reduction_property) {
1263 *val = state->tv.flicker_reduction;
1264 } else if (property == config->tv_overscan_property) {
1265 *val = state->tv.overscan;
1266 } else if (property == config->tv_saturation_property) {
1267 *val = state->tv.saturation;
1268 } else if (property == config->tv_hue_property) {
1269 *val = state->tv.hue;
1270 } else if (property == config->link_status_property) {
1271 *val = state->link_status;
1272 } else if (property == config->aspect_ratio_property) {
1273 *val = state->picture_aspect_ratio;
1274 } else if (property == connector->scaling_mode_property) {
1275 *val = state->scaling_mode;
1276 } else if (connector->funcs->atomic_get_property) {
1277 return connector->funcs->atomic_get_property(connector,
1278 state, property, val);
1279 } else {
1280 return -EINVAL;
1281 }
1282
1283 return 0;
1284}
1285
1286int drm_atomic_get_property(struct drm_mode_object *obj,
1287 struct drm_property *property, uint64_t *val)
1288{
1289 struct drm_device *dev = property->dev;
1290 int ret;
1291
1292 switch (obj->type) {
1293 case DRM_MODE_OBJECT_CONNECTOR: {
1294 struct drm_connector *connector = obj_to_connector(obj);
1295 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
1296 ret = drm_atomic_connector_get_property(connector,
1297 connector->state, property, val);
1298 break;
1299 }
1300 case DRM_MODE_OBJECT_CRTC: {
1301 struct drm_crtc *crtc = obj_to_crtc(obj);
1302 WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
1303 ret = drm_atomic_crtc_get_property(crtc,
1304 crtc->state, property, val);
1305 break;
1306 }
1307 case DRM_MODE_OBJECT_PLANE: {
1308 struct drm_plane *plane = obj_to_plane(obj);
1309 WARN_ON(!drm_modeset_is_locked(&plane->mutex));
1310 ret = drm_atomic_plane_get_property(plane,
1311 plane->state, property, val);
1312 break;
1313 }
1314 default:
1315 ret = -EINVAL;
1316 break;
1317 }
1318
1319 return ret;
1320}
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336int
1337drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
1338 struct drm_crtc *crtc)
1339{
1340 struct drm_plane *plane = plane_state->plane;
1341 struct drm_crtc_state *crtc_state;
1342
1343 if (plane_state->crtc) {
1344 crtc_state = drm_atomic_get_crtc_state(plane_state->state,
1345 plane_state->crtc);
1346 if (WARN_ON(IS_ERR(crtc_state)))
1347 return PTR_ERR(crtc_state);
1348
1349 crtc_state->plane_mask &= ~(1 << drm_plane_index(plane));
1350 }
1351
1352 plane_state->crtc = crtc;
1353
1354 if (crtc) {
1355 crtc_state = drm_atomic_get_crtc_state(plane_state->state,
1356 crtc);
1357 if (IS_ERR(crtc_state))
1358 return PTR_ERR(crtc_state);
1359 crtc_state->plane_mask |= (1 << drm_plane_index(plane));
1360 }
1361
1362 if (crtc)
1363 DRM_DEBUG_ATOMIC("Link plane state %p to [CRTC:%d:%s]\n",
1364 plane_state, crtc->base.id, crtc->name);
1365 else
1366 DRM_DEBUG_ATOMIC("Link plane state %p to [NOCRTC]\n",
1367 plane_state);
1368
1369 return 0;
1370}
1371EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383void
1384drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
1385 struct drm_framebuffer *fb)
1386{
1387 if (fb)
1388 DRM_DEBUG_ATOMIC("Set [FB:%d] for plane state %p\n",
1389 fb->base.id, plane_state);
1390 else
1391 DRM_DEBUG_ATOMIC("Set [NOFB] for plane state %p\n",
1392 plane_state);
1393
1394 drm_framebuffer_assign(&plane_state->fb, fb);
1395}
1396EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414void
1415drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
1416 struct dma_fence *fence)
1417{
1418 if (plane_state->fence) {
1419 dma_fence_put(fence);
1420 return;
1421 }
1422
1423 plane_state->fence = fence;
1424}
1425EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441int
1442drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
1443 struct drm_crtc *crtc)
1444{
1445 struct drm_crtc_state *crtc_state;
1446
1447 if (conn_state->crtc == crtc)
1448 return 0;
1449
1450 if (conn_state->crtc) {
1451 crtc_state = drm_atomic_get_new_crtc_state(conn_state->state,
1452 conn_state->crtc);
1453
1454 crtc_state->connector_mask &=
1455 ~(1 << drm_connector_index(conn_state->connector));
1456
1457 drm_connector_put(conn_state->connector);
1458 conn_state->crtc = NULL;
1459 }
1460
1461 if (crtc) {
1462 crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
1463 if (IS_ERR(crtc_state))
1464 return PTR_ERR(crtc_state);
1465
1466 crtc_state->connector_mask |=
1467 1 << drm_connector_index(conn_state->connector);
1468
1469 drm_connector_get(conn_state->connector);
1470 conn_state->crtc = crtc;
1471
1472 DRM_DEBUG_ATOMIC("Link connector state %p to [CRTC:%d:%s]\n",
1473 conn_state, crtc->base.id, crtc->name);
1474 } else {
1475 DRM_DEBUG_ATOMIC("Link connector state %p to [NOCRTC]\n",
1476 conn_state);
1477 }
1478
1479 return 0;
1480}
1481EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500int
1501drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
1502 struct drm_crtc *crtc)
1503{
1504 struct drm_mode_config *config = &state->dev->mode_config;
1505 struct drm_connector *connector;
1506 struct drm_connector_state *conn_state;
1507 struct drm_connector_list_iter conn_iter;
1508 struct drm_crtc_state *crtc_state;
1509 int ret;
1510
1511 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1512 if (IS_ERR(crtc_state))
1513 return PTR_ERR(crtc_state);
1514
1515 ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
1516 if (ret)
1517 return ret;
1518
1519 DRM_DEBUG_ATOMIC("Adding all current connectors for [CRTC:%d:%s] to %p\n",
1520 crtc->base.id, crtc->name, state);
1521
1522
1523
1524
1525
1526 drm_connector_list_iter_begin(state->dev, &conn_iter);
1527 drm_for_each_connector_iter(connector, &conn_iter) {
1528 if (!(crtc_state->connector_mask & (1 << drm_connector_index(connector))))
1529 continue;
1530
1531 conn_state = drm_atomic_get_connector_state(state, connector);
1532 if (IS_ERR(conn_state)) {
1533 drm_connector_list_iter_end(&conn_iter);
1534 return PTR_ERR(conn_state);
1535 }
1536 }
1537 drm_connector_list_iter_end(&conn_iter);
1538
1539 return 0;
1540}
1541EXPORT_SYMBOL(drm_atomic_add_affected_connectors);
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563int
1564drm_atomic_add_affected_planes(struct drm_atomic_state *state,
1565 struct drm_crtc *crtc)
1566{
1567 struct drm_plane *plane;
1568
1569 WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc));
1570
1571 drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) {
1572 struct drm_plane_state *plane_state =
1573 drm_atomic_get_plane_state(state, plane);
1574
1575 if (IS_ERR(plane_state))
1576 return PTR_ERR(plane_state);
1577 }
1578 return 0;
1579}
1580EXPORT_SYMBOL(drm_atomic_add_affected_planes);
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
1591{
1592 struct drm_device *dev = state->dev;
1593 int ret;
1594 bool global = false;
1595
1596 if (WARN_ON(dev->mode_config.acquire_ctx == state->acquire_ctx)) {
1597 global = true;
1598
1599 dev->mode_config.acquire_ctx = NULL;
1600 }
1601
1602retry:
1603 drm_modeset_backoff(state->acquire_ctx);
1604
1605 ret = drm_modeset_lock_all_ctx(dev, state->acquire_ctx);
1606 if (ret)
1607 goto retry;
1608
1609 if (global)
1610 dev->mode_config.acquire_ctx = state->acquire_ctx;
1611}
1612EXPORT_SYMBOL(drm_atomic_legacy_backoff);
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625int drm_atomic_check_only(struct drm_atomic_state *state)
1626{
1627 struct drm_device *dev = state->dev;
1628 struct drm_mode_config *config = &dev->mode_config;
1629 struct drm_plane *plane;
1630 struct drm_plane_state *plane_state;
1631 struct drm_crtc *crtc;
1632 struct drm_crtc_state *crtc_state;
1633 int i, ret = 0;
1634
1635 DRM_DEBUG_ATOMIC("checking %p\n", state);
1636
1637 for_each_new_plane_in_state(state, plane, plane_state, i) {
1638 ret = drm_atomic_plane_check(plane, plane_state);
1639 if (ret) {
1640 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] atomic core check failed\n",
1641 plane->base.id, plane->name);
1642 return ret;
1643 }
1644 }
1645
1646 for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
1647 ret = drm_atomic_crtc_check(crtc, crtc_state);
1648 if (ret) {
1649 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic core check failed\n",
1650 crtc->base.id, crtc->name);
1651 return ret;
1652 }
1653 }
1654
1655 if (config->funcs->atomic_check)
1656 ret = config->funcs->atomic_check(state->dev, state);
1657
1658 if (ret)
1659 return ret;
1660
1661 if (!state->allow_modeset) {
1662 for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
1663 if (drm_atomic_crtc_needs_modeset(crtc_state)) {
1664 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requires full modeset\n",
1665 crtc->base.id, crtc->name);
1666 return -EINVAL;
1667 }
1668 }
1669 }
1670
1671 return 0;
1672}
1673EXPORT_SYMBOL(drm_atomic_check_only);
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689int drm_atomic_commit(struct drm_atomic_state *state)
1690{
1691 struct drm_mode_config *config = &state->dev->mode_config;
1692 int ret;
1693
1694 ret = drm_atomic_check_only(state);
1695 if (ret)
1696 return ret;
1697
1698 DRM_DEBUG_ATOMIC("committing %p\n", state);
1699
1700 return config->funcs->atomic_commit(state->dev, state, false);
1701}
1702EXPORT_SYMBOL(drm_atomic_commit);
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718int drm_atomic_nonblocking_commit(struct drm_atomic_state *state)
1719{
1720 struct drm_mode_config *config = &state->dev->mode_config;
1721 int ret;
1722
1723 ret = drm_atomic_check_only(state);
1724 if (ret)
1725 return ret;
1726
1727 DRM_DEBUG_ATOMIC("committing %p nonblocking\n", state);
1728
1729 return config->funcs->atomic_commit(state->dev, state, true);
1730}
1731EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
1732
1733static void drm_atomic_print_state(const struct drm_atomic_state *state)
1734{
1735 struct drm_printer p = drm_info_printer(state->dev->dev);
1736 struct drm_plane *plane;
1737 struct drm_plane_state *plane_state;
1738 struct drm_crtc *crtc;
1739 struct drm_crtc_state *crtc_state;
1740 struct drm_connector *connector;
1741 struct drm_connector_state *connector_state;
1742 int i;
1743
1744 DRM_DEBUG_ATOMIC("checking %p\n", state);
1745
1746 for_each_new_plane_in_state(state, plane, plane_state, i)
1747 drm_atomic_plane_print_state(&p, plane_state);
1748
1749 for_each_new_crtc_in_state(state, crtc, crtc_state, i)
1750 drm_atomic_crtc_print_state(&p, crtc_state);
1751
1752 for_each_new_connector_in_state(state, connector, connector_state, i)
1753 drm_atomic_connector_print_state(&p, connector_state);
1754}
1755
1756static void __drm_state_dump(struct drm_device *dev, struct drm_printer *p,
1757 bool take_locks)
1758{
1759 struct drm_mode_config *config = &dev->mode_config;
1760 struct drm_plane *plane;
1761 struct drm_crtc *crtc;
1762 struct drm_connector *connector;
1763 struct drm_connector_list_iter conn_iter;
1764
1765 if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
1766 return;
1767
1768 list_for_each_entry(plane, &config->plane_list, head) {
1769 if (take_locks)
1770 drm_modeset_lock(&plane->mutex, NULL);
1771 drm_atomic_plane_print_state(p, plane->state);
1772 if (take_locks)
1773 drm_modeset_unlock(&plane->mutex);
1774 }
1775
1776 list_for_each_entry(crtc, &config->crtc_list, head) {
1777 if (take_locks)
1778 drm_modeset_lock(&crtc->mutex, NULL);
1779 drm_atomic_crtc_print_state(p, crtc->state);
1780 if (take_locks)
1781 drm_modeset_unlock(&crtc->mutex);
1782 }
1783
1784 drm_connector_list_iter_begin(dev, &conn_iter);
1785 if (take_locks)
1786 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
1787 drm_for_each_connector_iter(connector, &conn_iter)
1788 drm_atomic_connector_print_state(p, connector->state);
1789 if (take_locks)
1790 drm_modeset_unlock(&dev->mode_config.connection_mutex);
1791 drm_connector_list_iter_end(&conn_iter);
1792}
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809void drm_state_dump(struct drm_device *dev, struct drm_printer *p)
1810{
1811 __drm_state_dump(dev, p, false);
1812}
1813EXPORT_SYMBOL(drm_state_dump);
1814
1815#ifdef CONFIG_DEBUG_FS
1816static int drm_state_info(struct seq_file *m, void *data)
1817{
1818 struct drm_info_node *node = (struct drm_info_node *) m->private;
1819 struct drm_device *dev = node->minor->dev;
1820 struct drm_printer p = drm_seq_file_printer(m);
1821
1822 __drm_state_dump(dev, &p, true);
1823
1824 return 0;
1825}
1826
1827
1828static const struct drm_info_list drm_atomic_debugfs_list[] = {
1829 {"state", drm_state_info, 0},
1830};
1831
1832int drm_atomic_debugfs_init(struct drm_minor *minor)
1833{
1834 return drm_debugfs_create_files(drm_atomic_debugfs_list,
1835 ARRAY_SIZE(drm_atomic_debugfs_list),
1836 minor->debugfs_root, minor);
1837}
1838#endif
1839
1840
1841
1842
1843
1844static struct drm_pending_vblank_event *create_vblank_event(
1845 struct drm_device *dev, uint64_t user_data)
1846{
1847 struct drm_pending_vblank_event *e = NULL;
1848
1849 e = kzalloc(sizeof *e, GFP_KERNEL);
1850 if (!e)
1851 return NULL;
1852
1853 e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
1854 e->event.base.length = sizeof(e->event);
1855 e->event.user_data = user_data;
1856
1857 return e;
1858}
1859
1860static int atomic_set_prop(struct drm_atomic_state *state,
1861 struct drm_mode_object *obj, struct drm_property *prop,
1862 uint64_t prop_value)
1863{
1864 struct drm_mode_object *ref;
1865 int ret;
1866
1867 if (!drm_property_change_valid_get(prop, prop_value, &ref))
1868 return -EINVAL;
1869
1870 switch (obj->type) {
1871 case DRM_MODE_OBJECT_CONNECTOR: {
1872 struct drm_connector *connector = obj_to_connector(obj);
1873 struct drm_connector_state *connector_state;
1874
1875 connector_state = drm_atomic_get_connector_state(state, connector);
1876 if (IS_ERR(connector_state)) {
1877 ret = PTR_ERR(connector_state);
1878 break;
1879 }
1880
1881 ret = drm_atomic_connector_set_property(connector,
1882 connector_state, prop, prop_value);
1883 break;
1884 }
1885 case DRM_MODE_OBJECT_CRTC: {
1886 struct drm_crtc *crtc = obj_to_crtc(obj);
1887 struct drm_crtc_state *crtc_state;
1888
1889 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1890 if (IS_ERR(crtc_state)) {
1891 ret = PTR_ERR(crtc_state);
1892 break;
1893 }
1894
1895 ret = drm_atomic_crtc_set_property(crtc,
1896 crtc_state, prop, prop_value);
1897 break;
1898 }
1899 case DRM_MODE_OBJECT_PLANE: {
1900 struct drm_plane *plane = obj_to_plane(obj);
1901 struct drm_plane_state *plane_state;
1902
1903 plane_state = drm_atomic_get_plane_state(state, plane);
1904 if (IS_ERR(plane_state)) {
1905 ret = PTR_ERR(plane_state);
1906 break;
1907 }
1908
1909 ret = drm_atomic_plane_set_property(plane,
1910 plane_state, prop, prop_value);
1911 break;
1912 }
1913 default:
1914 ret = -EINVAL;
1915 break;
1916 }
1917
1918 drm_property_change_valid_put(prop, ref);
1919 return ret;
1920}
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934void drm_atomic_clean_old_fb(struct drm_device *dev,
1935 unsigned plane_mask,
1936 int ret)
1937{
1938 struct drm_plane *plane;
1939
1940
1941
1942
1943
1944
1945 drm_for_each_plane_mask(plane, dev, plane_mask) {
1946 if (ret == 0) {
1947 struct drm_framebuffer *new_fb = plane->state->fb;
1948 if (new_fb)
1949 drm_framebuffer_get(new_fb);
1950 plane->fb = new_fb;
1951 plane->crtc = plane->state->crtc;
1952
1953 if (plane->old_fb)
1954 drm_framebuffer_put(plane->old_fb);
1955 }
1956 plane->old_fb = NULL;
1957 }
1958}
1959EXPORT_SYMBOL(drm_atomic_clean_old_fb);
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013struct drm_out_fence_state {
2014 s32 __user *out_fence_ptr;
2015 struct sync_file *sync_file;
2016 int fd;
2017};
2018
2019static int setup_out_fence(struct drm_out_fence_state *fence_state,
2020 struct dma_fence *fence)
2021{
2022 fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
2023 if (fence_state->fd < 0)
2024 return fence_state->fd;
2025
2026 if (put_user(fence_state->fd, fence_state->out_fence_ptr))
2027 return -EFAULT;
2028
2029 fence_state->sync_file = sync_file_create(fence);
2030 if (!fence_state->sync_file)
2031 return -ENOMEM;
2032
2033 return 0;
2034}
2035
2036static int prepare_crtc_signaling(struct drm_device *dev,
2037 struct drm_atomic_state *state,
2038 struct drm_mode_atomic *arg,
2039 struct drm_file *file_priv,
2040 struct drm_out_fence_state **fence_state,
2041 unsigned int *num_fences)
2042{
2043 struct drm_crtc *crtc;
2044 struct drm_crtc_state *crtc_state;
2045 int i, ret;
2046
2047 if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
2048 return 0;
2049
2050 for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
2051 s32 __user *fence_ptr;
2052
2053 fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
2054
2055 if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
2056 struct drm_pending_vblank_event *e;
2057
2058 e = create_vblank_event(dev, arg->user_data);
2059 if (!e)
2060 return -ENOMEM;
2061
2062 crtc_state->event = e;
2063 }
2064
2065 if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
2066 struct drm_pending_vblank_event *e = crtc_state->event;
2067
2068 if (!file_priv)
2069 continue;
2070
2071 ret = drm_event_reserve_init(dev, file_priv, &e->base,
2072 &e->event.base);
2073 if (ret) {
2074 kfree(e);
2075 crtc_state->event = NULL;
2076 return ret;
2077 }
2078 }
2079
2080 if (fence_ptr) {
2081 struct dma_fence *fence;
2082 struct drm_out_fence_state *f;
2083
2084 f = krealloc(*fence_state, sizeof(**fence_state) *
2085 (*num_fences + 1), GFP_KERNEL);
2086 if (!f)
2087 return -ENOMEM;
2088
2089 memset(&f[*num_fences], 0, sizeof(*f));
2090
2091 f[*num_fences].out_fence_ptr = fence_ptr;
2092 *fence_state = f;
2093
2094 fence = drm_crtc_create_fence(crtc);
2095 if (!fence)
2096 return -ENOMEM;
2097
2098 ret = setup_out_fence(&f[(*num_fences)++], fence);
2099 if (ret) {
2100 dma_fence_put(fence);
2101 return ret;
2102 }
2103
2104 crtc_state->event->base.fence = fence;
2105 }
2106 }
2107
2108 return 0;
2109}
2110
2111static void complete_crtc_signaling(struct drm_device *dev,
2112 struct drm_atomic_state *state,
2113 struct drm_out_fence_state *fence_state,
2114 unsigned int num_fences,
2115 bool install_fds)
2116{
2117 struct drm_crtc *crtc;
2118 struct drm_crtc_state *crtc_state;
2119 int i;
2120
2121 if (install_fds) {
2122 for (i = 0; i < num_fences; i++)
2123 fd_install(fence_state[i].fd,
2124 fence_state[i].sync_file->file);
2125
2126 kfree(fence_state);
2127 return;
2128 }
2129
2130 for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
2131 struct drm_pending_vblank_event *event = crtc_state->event;
2132
2133
2134
2135
2136
2137 if (event && (event->base.fence || event->base.file_priv)) {
2138 drm_event_cancel_free(dev, &event->base);
2139 crtc_state->event = NULL;
2140 }
2141 }
2142
2143 if (!fence_state)
2144 return;
2145
2146 for (i = 0; i < num_fences; i++) {
2147 if (fence_state[i].sync_file)
2148 fput(fence_state[i].sync_file->file);
2149 if (fence_state[i].fd >= 0)
2150 put_unused_fd(fence_state[i].fd);
2151
2152
2153 if (fence_state[i].out_fence_ptr &&
2154 put_user(-1, fence_state[i].out_fence_ptr))
2155 DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
2156 }
2157
2158 kfree(fence_state);
2159}
2160
2161int drm_mode_atomic_ioctl(struct drm_device *dev,
2162 void *data, struct drm_file *file_priv)
2163{
2164 struct drm_mode_atomic *arg = data;
2165 uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
2166 uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
2167 uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
2168 uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
2169 unsigned int copied_objs, copied_props;
2170 struct drm_atomic_state *state;
2171 struct drm_modeset_acquire_ctx ctx;
2172 struct drm_plane *plane;
2173 struct drm_out_fence_state *fence_state;
2174 unsigned plane_mask;
2175 int ret = 0;
2176 unsigned int i, j, num_fences;
2177
2178
2179 if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
2180 return -EINVAL;
2181
2182
2183
2184
2185
2186 if (!file_priv->atomic)
2187 return -EINVAL;
2188
2189 if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS)
2190 return -EINVAL;
2191
2192 if (arg->reserved)
2193 return -EINVAL;
2194
2195 if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) &&
2196 !dev->mode_config.async_page_flip)
2197 return -EINVAL;
2198
2199
2200 if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
2201 (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
2202 return -EINVAL;
2203
2204 drm_modeset_acquire_init(&ctx, 0);
2205
2206 state = drm_atomic_state_alloc(dev);
2207 if (!state)
2208 return -ENOMEM;
2209
2210 state->acquire_ctx = &ctx;
2211 state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
2212
2213retry:
2214 plane_mask = 0;
2215 copied_objs = 0;
2216 copied_props = 0;
2217 fence_state = NULL;
2218 num_fences = 0;
2219
2220 for (i = 0; i < arg->count_objs; i++) {
2221 uint32_t obj_id, count_props;
2222 struct drm_mode_object *obj;
2223
2224 if (get_user(obj_id, objs_ptr + copied_objs)) {
2225 ret = -EFAULT;
2226 goto out;
2227 }
2228
2229 obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY);
2230 if (!obj) {
2231 ret = -ENOENT;
2232 goto out;
2233 }
2234
2235 if (!obj->properties) {
2236 drm_mode_object_put(obj);
2237 ret = -ENOENT;
2238 goto out;
2239 }
2240
2241 if (get_user(count_props, count_props_ptr + copied_objs)) {
2242 drm_mode_object_put(obj);
2243 ret = -EFAULT;
2244 goto out;
2245 }
2246
2247 copied_objs++;
2248
2249 for (j = 0; j < count_props; j++) {
2250 uint32_t prop_id;
2251 uint64_t prop_value;
2252 struct drm_property *prop;
2253
2254 if (get_user(prop_id, props_ptr + copied_props)) {
2255 drm_mode_object_put(obj);
2256 ret = -EFAULT;
2257 goto out;
2258 }
2259
2260 prop = drm_mode_obj_find_prop_id(obj, prop_id);
2261 if (!prop) {
2262 drm_mode_object_put(obj);
2263 ret = -ENOENT;
2264 goto out;
2265 }
2266
2267 if (copy_from_user(&prop_value,
2268 prop_values_ptr + copied_props,
2269 sizeof(prop_value))) {
2270 drm_mode_object_put(obj);
2271 ret = -EFAULT;
2272 goto out;
2273 }
2274
2275 ret = atomic_set_prop(state, obj, prop, prop_value);
2276 if (ret) {
2277 drm_mode_object_put(obj);
2278 goto out;
2279 }
2280
2281 copied_props++;
2282 }
2283
2284 if (obj->type == DRM_MODE_OBJECT_PLANE && count_props &&
2285 !(arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)) {
2286 plane = obj_to_plane(obj);
2287 plane_mask |= (1 << drm_plane_index(plane));
2288 plane->old_fb = plane->fb;
2289 }
2290 drm_mode_object_put(obj);
2291 }
2292
2293 ret = prepare_crtc_signaling(dev, state, arg, file_priv, &fence_state,
2294 &num_fences);
2295 if (ret)
2296 goto out;
2297
2298 if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
2299 ret = drm_atomic_check_only(state);
2300 } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
2301 ret = drm_atomic_nonblocking_commit(state);
2302 } else {
2303 if (unlikely(drm_debug & DRM_UT_STATE))
2304 drm_atomic_print_state(state);
2305
2306 ret = drm_atomic_commit(state);
2307 }
2308
2309out:
2310 drm_atomic_clean_old_fb(dev, plane_mask, ret);
2311
2312 complete_crtc_signaling(dev, state, fence_state, num_fences, !ret);
2313
2314 if (ret == -EDEADLK) {
2315 drm_atomic_state_clear(state);
2316 drm_modeset_backoff(&ctx);
2317 goto retry;
2318 }
2319
2320 drm_atomic_state_put(state);
2321
2322 drm_modeset_drop_locks(&ctx);
2323 drm_modeset_acquire_fini(&ctx);
2324
2325 return ret;
2326}
2327