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/drm_atomic_uapi.h>
30#include <drm/drm_atomic.h>
31#include <drm/drm_print.h>
32#include <drm/drm_drv.h>
33#include <drm/drm_writeback.h>
34#include <drm/drm_vblank.h>
35
36#include <linux/dma-fence.h>
37#include <linux/uaccess.h>
38#include <linux/sync_file.h>
39#include <linux/file.h>
40
41#include "drm_crtc_internal.h"
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
65 const struct drm_display_mode *mode)
66{
67 struct drm_crtc *crtc = state->crtc;
68 struct drm_mode_modeinfo umode;
69
70
71 if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
72 return 0;
73
74 drm_property_blob_put(state->mode_blob);
75 state->mode_blob = NULL;
76
77 if (mode) {
78 drm_mode_convert_to_umode(&umode, mode);
79 state->mode_blob =
80 drm_property_create_blob(state->crtc->dev,
81 sizeof(umode),
82 &umode);
83 if (IS_ERR(state->mode_blob))
84 return PTR_ERR(state->mode_blob);
85
86 drm_mode_copy(&state->mode, mode);
87 state->enable = true;
88 DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
89 mode->name, crtc->base.id, crtc->name, state);
90 } else {
91 memset(&state->mode, 0, sizeof(state->mode));
92 state->enable = false;
93 DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
94 crtc->base.id, crtc->name, state);
95 }
96
97 return 0;
98}
99EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
115 struct drm_property_blob *blob)
116{
117 struct drm_crtc *crtc = state->crtc;
118
119 if (blob == state->mode_blob)
120 return 0;
121
122 drm_property_blob_put(state->mode_blob);
123 state->mode_blob = NULL;
124
125 memset(&state->mode, 0, sizeof(state->mode));
126
127 if (blob) {
128 int ret;
129
130 if (blob->length != sizeof(struct drm_mode_modeinfo)) {
131 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] bad mode blob length: %zu\n",
132 crtc->base.id, crtc->name,
133 blob->length);
134 return -EINVAL;
135 }
136
137 ret = drm_mode_convert_umode(crtc->dev,
138 &state->mode, blob->data);
139 if (ret) {
140 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n",
141 crtc->base.id, crtc->name,
142 ret, drm_get_mode_status_name(state->mode.status));
143 drm_mode_debug_printmodeline(&state->mode);
144 return -EINVAL;
145 }
146
147 state->mode_blob = drm_property_blob_get(blob);
148 state->enable = true;
149 DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
150 state->mode.name, crtc->base.id, crtc->name,
151 state);
152 } else {
153 state->enable = false;
154 DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
155 crtc->base.id, crtc->name, state);
156 }
157
158 return 0;
159}
160EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176int
177drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
178 struct drm_crtc *crtc)
179{
180 struct drm_plane *plane = plane_state->plane;
181 struct drm_crtc_state *crtc_state;
182
183 if (plane_state->crtc == crtc)
184 return 0;
185 if (plane_state->crtc) {
186 crtc_state = drm_atomic_get_crtc_state(plane_state->state,
187 plane_state->crtc);
188 if (WARN_ON(IS_ERR(crtc_state)))
189 return PTR_ERR(crtc_state);
190
191 crtc_state->plane_mask &= ~drm_plane_mask(plane);
192 }
193
194 plane_state->crtc = crtc;
195
196 if (crtc) {
197 crtc_state = drm_atomic_get_crtc_state(plane_state->state,
198 crtc);
199 if (IS_ERR(crtc_state))
200 return PTR_ERR(crtc_state);
201 crtc_state->plane_mask |= drm_plane_mask(plane);
202 }
203
204 if (crtc)
205 DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n",
206 plane->base.id, plane->name, plane_state,
207 crtc->base.id, crtc->name);
208 else
209 DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [NOCRTC]\n",
210 plane->base.id, plane->name, plane_state);
211
212 return 0;
213}
214EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
215
216
217
218
219
220
221
222
223
224
225
226void
227drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
228 struct drm_framebuffer *fb)
229{
230 struct drm_plane *plane = plane_state->plane;
231
232 if (fb)
233 DRM_DEBUG_ATOMIC("Set [FB:%d] for [PLANE:%d:%s] state %p\n",
234 fb->base.id, plane->base.id, plane->name,
235 plane_state);
236 else
237 DRM_DEBUG_ATOMIC("Set [NOFB] for [PLANE:%d:%s] state %p\n",
238 plane->base.id, plane->name, plane_state);
239
240 drm_framebuffer_assign(&plane_state->fb, fb);
241}
242EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268void
269drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
270 struct dma_fence *fence)
271{
272 if (plane_state->fence) {
273 dma_fence_put(fence);
274 return;
275 }
276
277 plane_state->fence = fence;
278}
279EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295int
296drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
297 struct drm_crtc *crtc)
298{
299 struct drm_connector *connector = conn_state->connector;
300 struct drm_crtc_state *crtc_state;
301
302 if (conn_state->crtc == crtc)
303 return 0;
304
305 if (conn_state->crtc) {
306 crtc_state = drm_atomic_get_new_crtc_state(conn_state->state,
307 conn_state->crtc);
308
309 crtc_state->connector_mask &=
310 ~drm_connector_mask(conn_state->connector);
311
312 drm_connector_put(conn_state->connector);
313 conn_state->crtc = NULL;
314 }
315
316 if (crtc) {
317 crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
318 if (IS_ERR(crtc_state))
319 return PTR_ERR(crtc_state);
320
321 crtc_state->connector_mask |=
322 drm_connector_mask(conn_state->connector);
323
324 drm_connector_get(conn_state->connector);
325 conn_state->crtc = crtc;
326
327 DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n",
328 connector->base.id, connector->name,
329 conn_state, crtc->base.id, crtc->name);
330 } else {
331 DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n",
332 connector->base.id, connector->name,
333 conn_state);
334 }
335
336 return 0;
337}
338EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
339
340static void set_out_fence_for_crtc(struct drm_atomic_state *state,
341 struct drm_crtc *crtc, s32 __user *fence_ptr)
342{
343 state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
344}
345
346static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
347 struct drm_crtc *crtc)
348{
349 s32 __user *fence_ptr;
350
351 fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
352 state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
353
354 return fence_ptr;
355}
356
357static int set_out_fence_for_connector(struct drm_atomic_state *state,
358 struct drm_connector *connector,
359 s32 __user *fence_ptr)
360{
361 unsigned int index = drm_connector_index(connector);
362
363 if (!fence_ptr)
364 return 0;
365
366 if (put_user(-1, fence_ptr))
367 return -EFAULT;
368
369 state->connectors[index].out_fence_ptr = fence_ptr;
370
371 return 0;
372}
373
374static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state,
375 struct drm_connector *connector)
376{
377 unsigned int index = drm_connector_index(connector);
378 s32 __user *fence_ptr;
379
380 fence_ptr = state->connectors[index].out_fence_ptr;
381 state->connectors[index].out_fence_ptr = NULL;
382
383 return fence_ptr;
384}
385
386static int
387drm_atomic_replace_property_blob_from_id(struct drm_device *dev,
388 struct drm_property_blob **blob,
389 uint64_t blob_id,
390 ssize_t expected_size,
391 ssize_t expected_elem_size,
392 bool *replaced)
393{
394 struct drm_property_blob *new_blob = NULL;
395
396 if (blob_id != 0) {
397 new_blob = drm_property_lookup_blob(dev, blob_id);
398 if (new_blob == NULL)
399 return -EINVAL;
400
401 if (expected_size > 0 &&
402 new_blob->length != expected_size) {
403 drm_property_blob_put(new_blob);
404 return -EINVAL;
405 }
406 if (expected_elem_size > 0 &&
407 new_blob->length % expected_elem_size != 0) {
408 drm_property_blob_put(new_blob);
409 return -EINVAL;
410 }
411 }
412
413 *replaced |= drm_property_replace_blob(blob, new_blob);
414 drm_property_blob_put(new_blob);
415
416 return 0;
417}
418
419static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
420 struct drm_crtc_state *state, struct drm_property *property,
421 uint64_t val)
422{
423 struct drm_device *dev = crtc->dev;
424 struct drm_mode_config *config = &dev->mode_config;
425 bool replaced = false;
426 int ret;
427
428 if (property == config->prop_active)
429 state->active = val;
430 else if (property == config->prop_mode_id) {
431 struct drm_property_blob *mode =
432 drm_property_lookup_blob(dev, val);
433 ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
434 drm_property_blob_put(mode);
435 return ret;
436 } else if (property == config->prop_vrr_enabled) {
437 state->vrr_enabled = val;
438 } else if (property == config->degamma_lut_property) {
439 ret = drm_atomic_replace_property_blob_from_id(dev,
440 &state->degamma_lut,
441 val,
442 -1, sizeof(struct drm_color_lut),
443 &replaced);
444 state->color_mgmt_changed |= replaced;
445 return ret;
446 } else if (property == config->ctm_property) {
447 ret = drm_atomic_replace_property_blob_from_id(dev,
448 &state->ctm,
449 val,
450 sizeof(struct drm_color_ctm), -1,
451 &replaced);
452 state->color_mgmt_changed |= replaced;
453 return ret;
454 } else if (property == config->gamma_lut_property) {
455 ret = drm_atomic_replace_property_blob_from_id(dev,
456 &state->gamma_lut,
457 val,
458 -1, sizeof(struct drm_color_lut),
459 &replaced);
460 state->color_mgmt_changed |= replaced;
461 return ret;
462 } else if (property == config->prop_out_fence_ptr) {
463 s32 __user *fence_ptr = u64_to_user_ptr(val);
464
465 if (!fence_ptr)
466 return 0;
467
468 if (put_user(-1, fence_ptr))
469 return -EFAULT;
470
471 set_out_fence_for_crtc(state->state, crtc, fence_ptr);
472 } else if (crtc->funcs->atomic_set_property) {
473 return crtc->funcs->atomic_set_property(crtc, state, property, val);
474 } else {
475 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
476 crtc->base.id, crtc->name,
477 property->base.id, property->name);
478 return -EINVAL;
479 }
480
481 return 0;
482}
483
484static int
485drm_atomic_crtc_get_property(struct drm_crtc *crtc,
486 const struct drm_crtc_state *state,
487 struct drm_property *property, uint64_t *val)
488{
489 struct drm_device *dev = crtc->dev;
490 struct drm_mode_config *config = &dev->mode_config;
491
492 if (property == config->prop_active)
493 *val = drm_atomic_crtc_effectively_active(state);
494 else if (property == config->prop_mode_id)
495 *val = (state->mode_blob) ? state->mode_blob->base.id : 0;
496 else if (property == config->prop_vrr_enabled)
497 *val = state->vrr_enabled;
498 else if (property == config->degamma_lut_property)
499 *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0;
500 else if (property == config->ctm_property)
501 *val = (state->ctm) ? state->ctm->base.id : 0;
502 else if (property == config->gamma_lut_property)
503 *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
504 else if (property == config->prop_out_fence_ptr)
505 *val = 0;
506 else if (crtc->funcs->atomic_get_property)
507 return crtc->funcs->atomic_get_property(crtc, state, property, val);
508 else
509 return -EINVAL;
510
511 return 0;
512}
513
514static int drm_atomic_plane_set_property(struct drm_plane *plane,
515 struct drm_plane_state *state, struct drm_file *file_priv,
516 struct drm_property *property, uint64_t val)
517{
518 struct drm_device *dev = plane->dev;
519 struct drm_mode_config *config = &dev->mode_config;
520 bool replaced = false;
521 int ret;
522
523 if (property == config->prop_fb_id) {
524 struct drm_framebuffer *fb;
525
526 fb = drm_framebuffer_lookup(dev, file_priv, val);
527 drm_atomic_set_fb_for_plane(state, fb);
528 if (fb)
529 drm_framebuffer_put(fb);
530 } else if (property == config->prop_in_fence_fd) {
531 if (state->fence)
532 return -EINVAL;
533
534 if (U642I64(val) == -1)
535 return 0;
536
537 state->fence = sync_file_get_fence(val);
538 if (!state->fence)
539 return -EINVAL;
540
541 } else if (property == config->prop_crtc_id) {
542 struct drm_crtc *crtc = drm_crtc_find(dev, file_priv, val);
543
544 if (val && !crtc)
545 return -EACCES;
546 return drm_atomic_set_crtc_for_plane(state, crtc);
547 } else if (property == config->prop_crtc_x) {
548 state->crtc_x = U642I64(val);
549 } else if (property == config->prop_crtc_y) {
550 state->crtc_y = U642I64(val);
551 } else if (property == config->prop_crtc_w) {
552 state->crtc_w = val;
553 } else if (property == config->prop_crtc_h) {
554 state->crtc_h = val;
555 } else if (property == config->prop_src_x) {
556 state->src_x = val;
557 } else if (property == config->prop_src_y) {
558 state->src_y = val;
559 } else if (property == config->prop_src_w) {
560 state->src_w = val;
561 } else if (property == config->prop_src_h) {
562 state->src_h = val;
563 } else if (property == plane->alpha_property) {
564 state->alpha = val;
565 } else if (property == plane->blend_mode_property) {
566 state->pixel_blend_mode = val;
567 } else if (property == plane->rotation_property) {
568 if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) {
569 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n",
570 plane->base.id, plane->name, val);
571 return -EINVAL;
572 }
573 state->rotation = val;
574 } else if (property == plane->zpos_property) {
575 state->zpos = val;
576 } else if (property == plane->color_encoding_property) {
577 state->color_encoding = val;
578 } else if (property == plane->color_range_property) {
579 state->color_range = val;
580 } else if (property == config->prop_fb_damage_clips) {
581 ret = drm_atomic_replace_property_blob_from_id(dev,
582 &state->fb_damage_clips,
583 val,
584 -1,
585 sizeof(struct drm_rect),
586 &replaced);
587 return ret;
588 } else if (plane->funcs->atomic_set_property) {
589 return plane->funcs->atomic_set_property(plane, state,
590 property, val);
591 } else {
592 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
593 plane->base.id, plane->name,
594 property->base.id, property->name);
595 return -EINVAL;
596 }
597
598 return 0;
599}
600
601static int
602drm_atomic_plane_get_property(struct drm_plane *plane,
603 const struct drm_plane_state *state,
604 struct drm_property *property, uint64_t *val)
605{
606 struct drm_device *dev = plane->dev;
607 struct drm_mode_config *config = &dev->mode_config;
608
609 if (property == config->prop_fb_id) {
610 *val = (state->fb) ? state->fb->base.id : 0;
611 } else if (property == config->prop_in_fence_fd) {
612 *val = -1;
613 } else if (property == config->prop_crtc_id) {
614 *val = (state->crtc) ? state->crtc->base.id : 0;
615 } else if (property == config->prop_crtc_x) {
616 *val = I642U64(state->crtc_x);
617 } else if (property == config->prop_crtc_y) {
618 *val = I642U64(state->crtc_y);
619 } else if (property == config->prop_crtc_w) {
620 *val = state->crtc_w;
621 } else if (property == config->prop_crtc_h) {
622 *val = state->crtc_h;
623 } else if (property == config->prop_src_x) {
624 *val = state->src_x;
625 } else if (property == config->prop_src_y) {
626 *val = state->src_y;
627 } else if (property == config->prop_src_w) {
628 *val = state->src_w;
629 } else if (property == config->prop_src_h) {
630 *val = state->src_h;
631 } else if (property == plane->alpha_property) {
632 *val = state->alpha;
633 } else if (property == plane->blend_mode_property) {
634 *val = state->pixel_blend_mode;
635 } else if (property == plane->rotation_property) {
636 *val = state->rotation;
637 } else if (property == plane->zpos_property) {
638 *val = state->zpos;
639 } else if (property == plane->color_encoding_property) {
640 *val = state->color_encoding;
641 } else if (property == plane->color_range_property) {
642 *val = state->color_range;
643 } else if (property == config->prop_fb_damage_clips) {
644 *val = (state->fb_damage_clips) ?
645 state->fb_damage_clips->base.id : 0;
646 } else if (plane->funcs->atomic_get_property) {
647 return plane->funcs->atomic_get_property(plane, state, property, val);
648 } else {
649 return -EINVAL;
650 }
651
652 return 0;
653}
654
655static int drm_atomic_set_writeback_fb_for_connector(
656 struct drm_connector_state *conn_state,
657 struct drm_framebuffer *fb)
658{
659 int ret;
660
661 ret = drm_writeback_set_fb(conn_state, fb);
662 if (ret < 0)
663 return ret;
664
665 if (fb)
666 DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n",
667 fb->base.id, conn_state);
668 else
669 DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n",
670 conn_state);
671
672 return 0;
673}
674
675static int drm_atomic_connector_set_property(struct drm_connector *connector,
676 struct drm_connector_state *state, struct drm_file *file_priv,
677 struct drm_property *property, uint64_t val)
678{
679 struct drm_device *dev = connector->dev;
680 struct drm_mode_config *config = &dev->mode_config;
681 bool replaced = false;
682 int ret;
683
684 if (property == config->prop_crtc_id) {
685 struct drm_crtc *crtc = drm_crtc_find(dev, file_priv, val);
686
687 if (val && !crtc)
688 return -EACCES;
689 return drm_atomic_set_crtc_for_connector(state, crtc);
690 } else if (property == config->dpms_property) {
691
692
693
694
695 return -EINVAL;
696 } else if (property == config->tv_select_subconnector_property) {
697 state->tv.subconnector = val;
698 } else if (property == config->tv_left_margin_property) {
699 state->tv.margins.left = val;
700 } else if (property == config->tv_right_margin_property) {
701 state->tv.margins.right = val;
702 } else if (property == config->tv_top_margin_property) {
703 state->tv.margins.top = val;
704 } else if (property == config->tv_bottom_margin_property) {
705 state->tv.margins.bottom = val;
706 } else if (property == config->tv_mode_property) {
707 state->tv.mode = val;
708 } else if (property == config->tv_brightness_property) {
709 state->tv.brightness = val;
710 } else if (property == config->tv_contrast_property) {
711 state->tv.contrast = val;
712 } else if (property == config->tv_flicker_reduction_property) {
713 state->tv.flicker_reduction = val;
714 } else if (property == config->tv_overscan_property) {
715 state->tv.overscan = val;
716 } else if (property == config->tv_saturation_property) {
717 state->tv.saturation = val;
718 } else if (property == config->tv_hue_property) {
719 state->tv.hue = val;
720 } else if (property == config->link_status_property) {
721
722
723
724
725
726
727
728
729
730
731
732 if (state->link_status != DRM_LINK_STATUS_GOOD)
733 state->link_status = val;
734 } else if (property == config->hdr_output_metadata_property) {
735 ret = drm_atomic_replace_property_blob_from_id(dev,
736 &state->hdr_output_metadata,
737 val,
738 sizeof(struct hdr_output_metadata), -1,
739 &replaced);
740 return ret;
741 } else if (property == config->aspect_ratio_property) {
742 state->picture_aspect_ratio = val;
743 } else if (property == config->content_type_property) {
744 state->content_type = val;
745 } else if (property == connector->scaling_mode_property) {
746 state->scaling_mode = val;
747 } else if (property == config->content_protection_property) {
748 if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
749 DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
750 return -EINVAL;
751 }
752 state->content_protection = val;
753 } else if (property == config->hdcp_content_type_property) {
754 state->hdcp_content_type = val;
755 } else if (property == connector->colorspace_property) {
756 state->colorspace = val;
757 } else if (property == config->writeback_fb_id_property) {
758 struct drm_framebuffer *fb;
759 int ret;
760
761 fb = drm_framebuffer_lookup(dev, file_priv, val);
762 ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
763 if (fb)
764 drm_framebuffer_put(fb);
765 return ret;
766 } else if (property == config->writeback_out_fence_ptr_property) {
767 s32 __user *fence_ptr = u64_to_user_ptr(val);
768
769 return set_out_fence_for_connector(state->state, connector,
770 fence_ptr);
771 } else if (property == connector->max_bpc_property) {
772 state->max_requested_bpc = val;
773 } else if (connector->funcs->atomic_set_property) {
774 return connector->funcs->atomic_set_property(connector,
775 state, property, val);
776 } else {
777 DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
778 connector->base.id, connector->name,
779 property->base.id, property->name);
780 return -EINVAL;
781 }
782
783 return 0;
784}
785
786static int
787drm_atomic_connector_get_property(struct drm_connector *connector,
788 const struct drm_connector_state *state,
789 struct drm_property *property, uint64_t *val)
790{
791 struct drm_device *dev = connector->dev;
792 struct drm_mode_config *config = &dev->mode_config;
793
794 if (property == config->prop_crtc_id) {
795 *val = (state->crtc) ? state->crtc->base.id : 0;
796 } else if (property == config->dpms_property) {
797 if (state->crtc && state->crtc->state->self_refresh_active)
798 *val = DRM_MODE_DPMS_ON;
799 else
800 *val = connector->dpms;
801 } else if (property == config->tv_select_subconnector_property) {
802 *val = state->tv.subconnector;
803 } else if (property == config->tv_left_margin_property) {
804 *val = state->tv.margins.left;
805 } else if (property == config->tv_right_margin_property) {
806 *val = state->tv.margins.right;
807 } else if (property == config->tv_top_margin_property) {
808 *val = state->tv.margins.top;
809 } else if (property == config->tv_bottom_margin_property) {
810 *val = state->tv.margins.bottom;
811 } else if (property == config->tv_mode_property) {
812 *val = state->tv.mode;
813 } else if (property == config->tv_brightness_property) {
814 *val = state->tv.brightness;
815 } else if (property == config->tv_contrast_property) {
816 *val = state->tv.contrast;
817 } else if (property == config->tv_flicker_reduction_property) {
818 *val = state->tv.flicker_reduction;
819 } else if (property == config->tv_overscan_property) {
820 *val = state->tv.overscan;
821 } else if (property == config->tv_saturation_property) {
822 *val = state->tv.saturation;
823 } else if (property == config->tv_hue_property) {
824 *val = state->tv.hue;
825 } else if (property == config->link_status_property) {
826 *val = state->link_status;
827 } else if (property == config->aspect_ratio_property) {
828 *val = state->picture_aspect_ratio;
829 } else if (property == config->content_type_property) {
830 *val = state->content_type;
831 } else if (property == connector->colorspace_property) {
832 *val = state->colorspace;
833 } else if (property == connector->scaling_mode_property) {
834 *val = state->scaling_mode;
835 } else if (property == config->hdr_output_metadata_property) {
836 *val = state->hdr_output_metadata ?
837 state->hdr_output_metadata->base.id : 0;
838 } else if (property == config->content_protection_property) {
839 *val = state->content_protection;
840 } else if (property == config->hdcp_content_type_property) {
841 *val = state->hdcp_content_type;
842 } else if (property == config->writeback_fb_id_property) {
843
844 *val = 0;
845 } else if (property == config->writeback_out_fence_ptr_property) {
846 *val = 0;
847 } else if (property == connector->max_bpc_property) {
848 *val = state->max_requested_bpc;
849 } else if (connector->funcs->atomic_get_property) {
850 return connector->funcs->atomic_get_property(connector,
851 state, property, val);
852 } else {
853 return -EINVAL;
854 }
855
856 return 0;
857}
858
859int drm_atomic_get_property(struct drm_mode_object *obj,
860 struct drm_property *property, uint64_t *val)
861{
862 struct drm_device *dev = property->dev;
863 int ret;
864
865 switch (obj->type) {
866 case DRM_MODE_OBJECT_CONNECTOR: {
867 struct drm_connector *connector = obj_to_connector(obj);
868
869 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
870 ret = drm_atomic_connector_get_property(connector,
871 connector->state, property, val);
872 break;
873 }
874 case DRM_MODE_OBJECT_CRTC: {
875 struct drm_crtc *crtc = obj_to_crtc(obj);
876
877 WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
878 ret = drm_atomic_crtc_get_property(crtc,
879 crtc->state, property, val);
880 break;
881 }
882 case DRM_MODE_OBJECT_PLANE: {
883 struct drm_plane *plane = obj_to_plane(obj);
884
885 WARN_ON(!drm_modeset_is_locked(&plane->mutex));
886 ret = drm_atomic_plane_get_property(plane,
887 plane->state, property, val);
888 break;
889 }
890 default:
891 ret = -EINVAL;
892 break;
893 }
894
895 return ret;
896}
897
898
899
900
901
902static struct drm_pending_vblank_event *create_vblank_event(
903 struct drm_crtc *crtc, uint64_t user_data)
904{
905 struct drm_pending_vblank_event *e = NULL;
906
907 e = kzalloc(sizeof *e, GFP_KERNEL);
908 if (!e)
909 return NULL;
910
911 e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
912 e->event.base.length = sizeof(e->event);
913 e->event.vbl.crtc_id = crtc->base.id;
914 e->event.vbl.user_data = user_data;
915
916 return e;
917}
918
919int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
920 struct drm_connector *connector,
921 int mode)
922{
923 struct drm_connector *tmp_connector;
924 struct drm_connector_state *new_conn_state;
925 struct drm_crtc *crtc;
926 struct drm_crtc_state *crtc_state;
927 int i, ret, old_mode = connector->dpms;
928 bool active = false;
929
930 ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
931 state->acquire_ctx);
932 if (ret)
933 return ret;
934
935 if (mode != DRM_MODE_DPMS_ON)
936 mode = DRM_MODE_DPMS_OFF;
937 connector->dpms = mode;
938
939 crtc = connector->state->crtc;
940 if (!crtc)
941 goto out;
942 ret = drm_atomic_add_affected_connectors(state, crtc);
943 if (ret)
944 goto out;
945
946 crtc_state = drm_atomic_get_crtc_state(state, crtc);
947 if (IS_ERR(crtc_state)) {
948 ret = PTR_ERR(crtc_state);
949 goto out;
950 }
951
952 for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i) {
953 if (new_conn_state->crtc != crtc)
954 continue;
955 if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
956 active = true;
957 break;
958 }
959 }
960
961 crtc_state->active = active;
962 ret = drm_atomic_commit(state);
963out:
964 if (ret != 0)
965 connector->dpms = old_mode;
966 return ret;
967}
968
969int drm_atomic_set_property(struct drm_atomic_state *state,
970 struct drm_file *file_priv,
971 struct drm_mode_object *obj,
972 struct drm_property *prop,
973 uint64_t prop_value)
974{
975 struct drm_mode_object *ref;
976 int ret;
977
978 if (!drm_property_change_valid_get(prop, prop_value, &ref))
979 return -EINVAL;
980
981 switch (obj->type) {
982 case DRM_MODE_OBJECT_CONNECTOR: {
983 struct drm_connector *connector = obj_to_connector(obj);
984 struct drm_connector_state *connector_state;
985
986 connector_state = drm_atomic_get_connector_state(state, connector);
987 if (IS_ERR(connector_state)) {
988 ret = PTR_ERR(connector_state);
989 break;
990 }
991
992 ret = drm_atomic_connector_set_property(connector,
993 connector_state, file_priv,
994 prop, prop_value);
995 break;
996 }
997 case DRM_MODE_OBJECT_CRTC: {
998 struct drm_crtc *crtc = obj_to_crtc(obj);
999 struct drm_crtc_state *crtc_state;
1000
1001 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1002 if (IS_ERR(crtc_state)) {
1003 ret = PTR_ERR(crtc_state);
1004 break;
1005 }
1006
1007 ret = drm_atomic_crtc_set_property(crtc,
1008 crtc_state, prop, prop_value);
1009 break;
1010 }
1011 case DRM_MODE_OBJECT_PLANE: {
1012 struct drm_plane *plane = obj_to_plane(obj);
1013 struct drm_plane_state *plane_state;
1014
1015 plane_state = drm_atomic_get_plane_state(state, plane);
1016 if (IS_ERR(plane_state)) {
1017 ret = PTR_ERR(plane_state);
1018 break;
1019 }
1020
1021 ret = drm_atomic_plane_set_property(plane,
1022 plane_state, file_priv,
1023 prop, prop_value);
1024 break;
1025 }
1026 default:
1027 ret = -EINVAL;
1028 break;
1029 }
1030
1031 drm_property_change_valid_put(prop, ref);
1032 return ret;
1033}
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087struct drm_out_fence_state {
1088 s32 __user *out_fence_ptr;
1089 struct sync_file *sync_file;
1090 int fd;
1091};
1092
1093static int setup_out_fence(struct drm_out_fence_state *fence_state,
1094 struct dma_fence *fence)
1095{
1096 fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
1097 if (fence_state->fd < 0)
1098 return fence_state->fd;
1099
1100 if (put_user(fence_state->fd, fence_state->out_fence_ptr))
1101 return -EFAULT;
1102
1103 fence_state->sync_file = sync_file_create(fence);
1104 if (!fence_state->sync_file)
1105 return -ENOMEM;
1106
1107 return 0;
1108}
1109
1110static int prepare_signaling(struct drm_device *dev,
1111 struct drm_atomic_state *state,
1112 struct drm_mode_atomic *arg,
1113 struct drm_file *file_priv,
1114 struct drm_out_fence_state **fence_state,
1115 unsigned int *num_fences)
1116{
1117 struct drm_crtc *crtc;
1118 struct drm_crtc_state *crtc_state;
1119 struct drm_connector *conn;
1120 struct drm_connector_state *conn_state;
1121 int i, c = 0, ret;
1122
1123 if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
1124 return 0;
1125
1126 for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
1127 s32 __user *fence_ptr;
1128
1129 fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
1130
1131 if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
1132 struct drm_pending_vblank_event *e;
1133
1134 e = create_vblank_event(crtc, arg->user_data);
1135 if (!e)
1136 return -ENOMEM;
1137
1138 crtc_state->event = e;
1139 }
1140
1141 if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
1142 struct drm_pending_vblank_event *e = crtc_state->event;
1143
1144 if (!file_priv)
1145 continue;
1146
1147 ret = drm_event_reserve_init(dev, file_priv, &e->base,
1148 &e->event.base);
1149 if (ret) {
1150 kfree(e);
1151 crtc_state->event = NULL;
1152 return ret;
1153 }
1154 }
1155
1156 if (fence_ptr) {
1157 struct dma_fence *fence;
1158 struct drm_out_fence_state *f;
1159
1160 f = krealloc(*fence_state, sizeof(**fence_state) *
1161 (*num_fences + 1), GFP_KERNEL);
1162 if (!f)
1163 return -ENOMEM;
1164
1165 memset(&f[*num_fences], 0, sizeof(*f));
1166
1167 f[*num_fences].out_fence_ptr = fence_ptr;
1168 *fence_state = f;
1169
1170 fence = drm_crtc_create_fence(crtc);
1171 if (!fence)
1172 return -ENOMEM;
1173
1174 ret = setup_out_fence(&f[(*num_fences)++], fence);
1175 if (ret) {
1176 dma_fence_put(fence);
1177 return ret;
1178 }
1179
1180 crtc_state->event->base.fence = fence;
1181 }
1182
1183 c++;
1184 }
1185
1186 for_each_new_connector_in_state(state, conn, conn_state, i) {
1187 struct drm_writeback_connector *wb_conn;
1188 struct drm_out_fence_state *f;
1189 struct dma_fence *fence;
1190 s32 __user *fence_ptr;
1191
1192 if (!conn_state->writeback_job)
1193 continue;
1194
1195 fence_ptr = get_out_fence_for_connector(state, conn);
1196 if (!fence_ptr)
1197 continue;
1198
1199 f = krealloc(*fence_state, sizeof(**fence_state) *
1200 (*num_fences + 1), GFP_KERNEL);
1201 if (!f)
1202 return -ENOMEM;
1203
1204 memset(&f[*num_fences], 0, sizeof(*f));
1205
1206 f[*num_fences].out_fence_ptr = fence_ptr;
1207 *fence_state = f;
1208
1209 wb_conn = drm_connector_to_writeback(conn);
1210 fence = drm_writeback_get_out_fence(wb_conn);
1211 if (!fence)
1212 return -ENOMEM;
1213
1214 ret = setup_out_fence(&f[(*num_fences)++], fence);
1215 if (ret) {
1216 dma_fence_put(fence);
1217 return ret;
1218 }
1219
1220 conn_state->writeback_job->out_fence = fence;
1221 }
1222
1223
1224
1225
1226
1227 if (c == 0 && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
1228 return -EINVAL;
1229
1230 return 0;
1231}
1232
1233static void complete_signaling(struct drm_device *dev,
1234 struct drm_atomic_state *state,
1235 struct drm_out_fence_state *fence_state,
1236 unsigned int num_fences,
1237 bool install_fds)
1238{
1239 struct drm_crtc *crtc;
1240 struct drm_crtc_state *crtc_state;
1241 int i;
1242
1243 if (install_fds) {
1244 for (i = 0; i < num_fences; i++)
1245 fd_install(fence_state[i].fd,
1246 fence_state[i].sync_file->file);
1247
1248 kfree(fence_state);
1249 return;
1250 }
1251
1252 for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
1253 struct drm_pending_vblank_event *event = crtc_state->event;
1254
1255
1256
1257
1258
1259 if (event && (event->base.fence || event->base.file_priv)) {
1260 drm_event_cancel_free(dev, &event->base);
1261 crtc_state->event = NULL;
1262 }
1263 }
1264
1265 if (!fence_state)
1266 return;
1267
1268 for (i = 0; i < num_fences; i++) {
1269 if (fence_state[i].sync_file)
1270 fput(fence_state[i].sync_file->file);
1271 if (fence_state[i].fd >= 0)
1272 put_unused_fd(fence_state[i].fd);
1273
1274
1275 if (fence_state[i].out_fence_ptr &&
1276 put_user(-1, fence_state[i].out_fence_ptr))
1277 DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
1278 }
1279
1280 kfree(fence_state);
1281}
1282
1283int drm_mode_atomic_ioctl(struct drm_device *dev,
1284 void *data, struct drm_file *file_priv)
1285{
1286 struct drm_mode_atomic *arg = data;
1287 uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
1288 uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
1289 uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
1290 uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
1291 unsigned int copied_objs, copied_props;
1292 struct drm_atomic_state *state;
1293 struct drm_modeset_acquire_ctx ctx;
1294 struct drm_out_fence_state *fence_state;
1295 int ret = 0;
1296 unsigned int i, j, num_fences;
1297
1298
1299 if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
1300 return -EOPNOTSUPP;
1301
1302
1303
1304
1305
1306 if (!file_priv->atomic)
1307 return -EINVAL;
1308
1309 if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS)
1310 return -EINVAL;
1311
1312 if (arg->reserved)
1313 return -EINVAL;
1314
1315 if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC)
1316 return -EINVAL;
1317
1318
1319 if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
1320 (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
1321 return -EINVAL;
1322
1323 state = drm_atomic_state_alloc(dev);
1324 if (!state)
1325 return -ENOMEM;
1326
1327 drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
1328 state->acquire_ctx = &ctx;
1329 state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
1330
1331retry:
1332 copied_objs = 0;
1333 copied_props = 0;
1334 fence_state = NULL;
1335 num_fences = 0;
1336
1337 for (i = 0; i < arg->count_objs; i++) {
1338 uint32_t obj_id, count_props;
1339 struct drm_mode_object *obj;
1340
1341 if (get_user(obj_id, objs_ptr + copied_objs)) {
1342 ret = -EFAULT;
1343 goto out;
1344 }
1345
1346 obj = drm_mode_object_find(dev, file_priv, obj_id, DRM_MODE_OBJECT_ANY);
1347 if (!obj) {
1348 ret = -ENOENT;
1349 goto out;
1350 }
1351
1352 if (!obj->properties) {
1353 drm_mode_object_put(obj);
1354 ret = -ENOENT;
1355 goto out;
1356 }
1357
1358 if (get_user(count_props, count_props_ptr + copied_objs)) {
1359 drm_mode_object_put(obj);
1360 ret = -EFAULT;
1361 goto out;
1362 }
1363
1364 copied_objs++;
1365
1366 for (j = 0; j < count_props; j++) {
1367 uint32_t prop_id;
1368 uint64_t prop_value;
1369 struct drm_property *prop;
1370
1371 if (get_user(prop_id, props_ptr + copied_props)) {
1372 drm_mode_object_put(obj);
1373 ret = -EFAULT;
1374 goto out;
1375 }
1376
1377 prop = drm_mode_obj_find_prop_id(obj, prop_id);
1378 if (!prop) {
1379 drm_mode_object_put(obj);
1380 ret = -ENOENT;
1381 goto out;
1382 }
1383
1384 if (copy_from_user(&prop_value,
1385 prop_values_ptr + copied_props,
1386 sizeof(prop_value))) {
1387 drm_mode_object_put(obj);
1388 ret = -EFAULT;
1389 goto out;
1390 }
1391
1392 ret = drm_atomic_set_property(state, file_priv,
1393 obj, prop, prop_value);
1394 if (ret) {
1395 drm_mode_object_put(obj);
1396 goto out;
1397 }
1398
1399 copied_props++;
1400 }
1401
1402 drm_mode_object_put(obj);
1403 }
1404
1405 ret = prepare_signaling(dev, state, arg, file_priv, &fence_state,
1406 &num_fences);
1407 if (ret)
1408 goto out;
1409
1410 if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
1411 ret = drm_atomic_check_only(state);
1412 } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
1413 ret = drm_atomic_nonblocking_commit(state);
1414 } else {
1415 if (drm_debug_enabled(DRM_UT_STATE))
1416 drm_atomic_print_state(state);
1417
1418 ret = drm_atomic_commit(state);
1419 }
1420
1421out:
1422 complete_signaling(dev, state, fence_state, num_fences, !ret);
1423
1424 if (ret == -EDEADLK) {
1425 drm_atomic_state_clear(state);
1426 ret = drm_modeset_backoff(&ctx);
1427 if (!ret)
1428 goto retry;
1429 }
1430
1431 drm_atomic_state_put(state);
1432
1433 drm_modeset_drop_locks(&ctx);
1434 drm_modeset_acquire_fini(&ctx);
1435
1436 return ret;
1437}
1438