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->gen_hdr_output_metadata_property) {
742 ret = drm_atomic_replace_property_blob_from_id(dev,
743 &state->gen_hdr_output_metadata,
744 val,
745 sizeof(struct gen_hdr_output_metadata), -1,
746 &replaced);
747 return ret;
748 } else if (property == config->aspect_ratio_property) {
749 state->picture_aspect_ratio = val;
750 } else if (property == config->content_type_property) {
751 state->content_type = val;
752 } else if (property == connector->scaling_mode_property) {
753 state->scaling_mode = val;
754 } else if (property == config->content_protection_property) {
755 if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
756 DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
757 return -EINVAL;
758 }
759 state->content_protection = val;
760 } else if (property == config->hdcp_content_type_property) {
761 state->hdcp_content_type = val;
762 } else if (property == connector->colorspace_property) {
763 state->colorspace = val;
764 } else if (property == config->writeback_fb_id_property) {
765 struct drm_framebuffer *fb;
766 int ret;
767
768 fb = drm_framebuffer_lookup(dev, file_priv, val);
769 ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
770 if (fb)
771 drm_framebuffer_put(fb);
772 return ret;
773 } else if (property == config->writeback_out_fence_ptr_property) {
774 s32 __user *fence_ptr = u64_to_user_ptr(val);
775
776 return set_out_fence_for_connector(state->state, connector,
777 fence_ptr);
778 } else if (property == connector->max_bpc_property) {
779 state->max_requested_bpc = val;
780 } else if (connector->funcs->atomic_set_property) {
781 return connector->funcs->atomic_set_property(connector,
782 state, property, val);
783 } else {
784 DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
785 connector->base.id, connector->name,
786 property->base.id, property->name);
787 return -EINVAL;
788 }
789
790 return 0;
791}
792
793static int
794drm_atomic_connector_get_property(struct drm_connector *connector,
795 const struct drm_connector_state *state,
796 struct drm_property *property, uint64_t *val)
797{
798 struct drm_device *dev = connector->dev;
799 struct drm_mode_config *config = &dev->mode_config;
800
801 if (property == config->prop_crtc_id) {
802 *val = (state->crtc) ? state->crtc->base.id : 0;
803 } else if (property == config->dpms_property) {
804 if (state->crtc && state->crtc->state->self_refresh_active)
805 *val = DRM_MODE_DPMS_ON;
806 else
807 *val = connector->dpms;
808 } else if (property == config->tv_select_subconnector_property) {
809 *val = state->tv.subconnector;
810 } else if (property == config->tv_left_margin_property) {
811 *val = state->tv.margins.left;
812 } else if (property == config->tv_right_margin_property) {
813 *val = state->tv.margins.right;
814 } else if (property == config->tv_top_margin_property) {
815 *val = state->tv.margins.top;
816 } else if (property == config->tv_bottom_margin_property) {
817 *val = state->tv.margins.bottom;
818 } else if (property == config->tv_mode_property) {
819 *val = state->tv.mode;
820 } else if (property == config->tv_brightness_property) {
821 *val = state->tv.brightness;
822 } else if (property == config->tv_contrast_property) {
823 *val = state->tv.contrast;
824 } else if (property == config->tv_flicker_reduction_property) {
825 *val = state->tv.flicker_reduction;
826 } else if (property == config->tv_overscan_property) {
827 *val = state->tv.overscan;
828 } else if (property == config->tv_saturation_property) {
829 *val = state->tv.saturation;
830 } else if (property == config->tv_hue_property) {
831 *val = state->tv.hue;
832 } else if (property == config->link_status_property) {
833 *val = state->link_status;
834 } else if (property == config->aspect_ratio_property) {
835 *val = state->picture_aspect_ratio;
836 } else if (property == config->content_type_property) {
837 *val = state->content_type;
838 } else if (property == connector->colorspace_property) {
839 *val = state->colorspace;
840 } else if (property == connector->scaling_mode_property) {
841 *val = state->scaling_mode;
842 } else if (property == config->hdr_output_metadata_property) {
843 *val = state->hdr_output_metadata ?
844 state->hdr_output_metadata->base.id : 0;
845 } else if (property == config->gen_hdr_output_metadata_property) {
846 *val = state->gen_hdr_output_metadata ?
847 state->gen_hdr_output_metadata->base.id : 0;
848 } else if (property == config->content_protection_property) {
849 *val = state->content_protection;
850 } else if (property == config->hdcp_content_type_property) {
851 *val = state->hdcp_content_type;
852 } else if (property == config->writeback_fb_id_property) {
853
854 *val = 0;
855 } else if (property == config->writeback_out_fence_ptr_property) {
856 *val = 0;
857 } else if (property == connector->max_bpc_property) {
858 *val = state->max_requested_bpc;
859 } else if (connector->funcs->atomic_get_property) {
860 return connector->funcs->atomic_get_property(connector,
861 state, property, val);
862 } else {
863 return -EINVAL;
864 }
865
866 return 0;
867}
868
869int drm_atomic_get_property(struct drm_mode_object *obj,
870 struct drm_property *property, uint64_t *val)
871{
872 struct drm_device *dev = property->dev;
873 int ret;
874
875 switch (obj->type) {
876 case DRM_MODE_OBJECT_CONNECTOR: {
877 struct drm_connector *connector = obj_to_connector(obj);
878
879 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
880 ret = drm_atomic_connector_get_property(connector,
881 connector->state, property, val);
882 break;
883 }
884 case DRM_MODE_OBJECT_CRTC: {
885 struct drm_crtc *crtc = obj_to_crtc(obj);
886
887 WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
888 ret = drm_atomic_crtc_get_property(crtc,
889 crtc->state, property, val);
890 break;
891 }
892 case DRM_MODE_OBJECT_PLANE: {
893 struct drm_plane *plane = obj_to_plane(obj);
894
895 WARN_ON(!drm_modeset_is_locked(&plane->mutex));
896 ret = drm_atomic_plane_get_property(plane,
897 plane->state, property, val);
898 break;
899 }
900 default:
901 ret = -EINVAL;
902 break;
903 }
904
905 return ret;
906}
907
908
909
910
911
912static struct drm_pending_vblank_event *create_vblank_event(
913 struct drm_crtc *crtc, uint64_t user_data)
914{
915 struct drm_pending_vblank_event *e = NULL;
916
917 e = kzalloc(sizeof *e, GFP_KERNEL);
918 if (!e)
919 return NULL;
920
921 e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
922 e->event.base.length = sizeof(e->event);
923 e->event.vbl.crtc_id = crtc->base.id;
924 e->event.vbl.user_data = user_data;
925
926 return e;
927}
928
929int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
930 struct drm_connector *connector,
931 int mode)
932{
933 struct drm_connector *tmp_connector;
934 struct drm_connector_state *new_conn_state;
935 struct drm_crtc *crtc;
936 struct drm_crtc_state *crtc_state;
937 int i, ret, old_mode = connector->dpms;
938 bool active = false;
939
940 ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
941 state->acquire_ctx);
942 if (ret)
943 return ret;
944
945 if (mode != DRM_MODE_DPMS_ON)
946 mode = DRM_MODE_DPMS_OFF;
947 connector->dpms = mode;
948
949 crtc = connector->state->crtc;
950 if (!crtc)
951 goto out;
952 ret = drm_atomic_add_affected_connectors(state, crtc);
953 if (ret)
954 goto out;
955
956 crtc_state = drm_atomic_get_crtc_state(state, crtc);
957 if (IS_ERR(crtc_state)) {
958 ret = PTR_ERR(crtc_state);
959 goto out;
960 }
961
962 for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i) {
963 if (new_conn_state->crtc != crtc)
964 continue;
965 if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
966 active = true;
967 break;
968 }
969 }
970
971 crtc_state->active = active;
972 ret = drm_atomic_commit(state);
973out:
974 if (ret != 0)
975 connector->dpms = old_mode;
976 return ret;
977}
978
979int drm_atomic_set_property(struct drm_atomic_state *state,
980 struct drm_file *file_priv,
981 struct drm_mode_object *obj,
982 struct drm_property *prop,
983 uint64_t prop_value)
984{
985 struct drm_mode_object *ref;
986 int ret;
987
988 if (!drm_property_change_valid_get(prop, prop_value, &ref))
989 return -EINVAL;
990
991 switch (obj->type) {
992 case DRM_MODE_OBJECT_CONNECTOR: {
993 struct drm_connector *connector = obj_to_connector(obj);
994 struct drm_connector_state *connector_state;
995
996 connector_state = drm_atomic_get_connector_state(state, connector);
997 if (IS_ERR(connector_state)) {
998 ret = PTR_ERR(connector_state);
999 break;
1000 }
1001
1002 ret = drm_atomic_connector_set_property(connector,
1003 connector_state, file_priv,
1004 prop, prop_value);
1005 break;
1006 }
1007 case DRM_MODE_OBJECT_CRTC: {
1008 struct drm_crtc *crtc = obj_to_crtc(obj);
1009 struct drm_crtc_state *crtc_state;
1010
1011 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1012 if (IS_ERR(crtc_state)) {
1013 ret = PTR_ERR(crtc_state);
1014 break;
1015 }
1016
1017 ret = drm_atomic_crtc_set_property(crtc,
1018 crtc_state, prop, prop_value);
1019 break;
1020 }
1021 case DRM_MODE_OBJECT_PLANE: {
1022 struct drm_plane *plane = obj_to_plane(obj);
1023 struct drm_plane_state *plane_state;
1024
1025 plane_state = drm_atomic_get_plane_state(state, plane);
1026 if (IS_ERR(plane_state)) {
1027 ret = PTR_ERR(plane_state);
1028 break;
1029 }
1030
1031 ret = drm_atomic_plane_set_property(plane,
1032 plane_state, file_priv,
1033 prop, prop_value);
1034 break;
1035 }
1036 default:
1037 ret = -EINVAL;
1038 break;
1039 }
1040
1041 drm_property_change_valid_put(prop, ref);
1042 return ret;
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
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097struct drm_out_fence_state {
1098 s32 __user *out_fence_ptr;
1099 struct sync_file *sync_file;
1100 int fd;
1101};
1102
1103static int setup_out_fence(struct drm_out_fence_state *fence_state,
1104 struct dma_fence *fence)
1105{
1106 fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
1107 if (fence_state->fd < 0)
1108 return fence_state->fd;
1109
1110 if (put_user(fence_state->fd, fence_state->out_fence_ptr))
1111 return -EFAULT;
1112
1113 fence_state->sync_file = sync_file_create(fence);
1114 if (!fence_state->sync_file)
1115 return -ENOMEM;
1116
1117 return 0;
1118}
1119
1120static int prepare_signaling(struct drm_device *dev,
1121 struct drm_atomic_state *state,
1122 struct drm_mode_atomic *arg,
1123 struct drm_file *file_priv,
1124 struct drm_out_fence_state **fence_state,
1125 unsigned int *num_fences)
1126{
1127 struct drm_crtc *crtc;
1128 struct drm_crtc_state *crtc_state;
1129 struct drm_connector *conn;
1130 struct drm_connector_state *conn_state;
1131 int i, c = 0, ret;
1132
1133 if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
1134 return 0;
1135
1136 for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
1137 s32 __user *fence_ptr;
1138
1139 fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
1140
1141 if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
1142 struct drm_pending_vblank_event *e;
1143
1144 e = create_vblank_event(crtc, arg->user_data);
1145 if (!e)
1146 return -ENOMEM;
1147
1148 crtc_state->event = e;
1149 }
1150
1151 if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
1152 struct drm_pending_vblank_event *e = crtc_state->event;
1153
1154 if (!file_priv)
1155 continue;
1156
1157 ret = drm_event_reserve_init(dev, file_priv, &e->base,
1158 &e->event.base);
1159 if (ret) {
1160 kfree(e);
1161 crtc_state->event = NULL;
1162 return ret;
1163 }
1164 }
1165
1166 if (fence_ptr) {
1167 struct dma_fence *fence;
1168 struct drm_out_fence_state *f;
1169
1170 f = krealloc(*fence_state, sizeof(**fence_state) *
1171 (*num_fences + 1), GFP_KERNEL);
1172 if (!f)
1173 return -ENOMEM;
1174
1175 memset(&f[*num_fences], 0, sizeof(*f));
1176
1177 f[*num_fences].out_fence_ptr = fence_ptr;
1178 *fence_state = f;
1179
1180 fence = drm_crtc_create_fence(crtc);
1181 if (!fence)
1182 return -ENOMEM;
1183
1184 ret = setup_out_fence(&f[(*num_fences)++], fence);
1185 if (ret) {
1186 dma_fence_put(fence);
1187 return ret;
1188 }
1189
1190 crtc_state->event->base.fence = fence;
1191 }
1192
1193 c++;
1194 }
1195
1196 for_each_new_connector_in_state(state, conn, conn_state, i) {
1197 struct drm_writeback_connector *wb_conn;
1198 struct drm_out_fence_state *f;
1199 struct dma_fence *fence;
1200 s32 __user *fence_ptr;
1201
1202 if (!conn_state->writeback_job)
1203 continue;
1204
1205 fence_ptr = get_out_fence_for_connector(state, conn);
1206 if (!fence_ptr)
1207 continue;
1208
1209 f = krealloc(*fence_state, sizeof(**fence_state) *
1210 (*num_fences + 1), GFP_KERNEL);
1211 if (!f)
1212 return -ENOMEM;
1213
1214 memset(&f[*num_fences], 0, sizeof(*f));
1215
1216 f[*num_fences].out_fence_ptr = fence_ptr;
1217 *fence_state = f;
1218
1219 wb_conn = drm_connector_to_writeback(conn);
1220 fence = drm_writeback_get_out_fence(wb_conn);
1221 if (!fence)
1222 return -ENOMEM;
1223
1224 ret = setup_out_fence(&f[(*num_fences)++], fence);
1225 if (ret) {
1226 dma_fence_put(fence);
1227 return ret;
1228 }
1229
1230 conn_state->writeback_job->out_fence = fence;
1231 }
1232
1233
1234
1235
1236
1237 if (c == 0 && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
1238 return -EINVAL;
1239
1240 return 0;
1241}
1242
1243static void complete_signaling(struct drm_device *dev,
1244 struct drm_atomic_state *state,
1245 struct drm_out_fence_state *fence_state,
1246 unsigned int num_fences,
1247 bool install_fds)
1248{
1249 struct drm_crtc *crtc;
1250 struct drm_crtc_state *crtc_state;
1251 int i;
1252
1253 if (install_fds) {
1254 for (i = 0; i < num_fences; i++)
1255 fd_install(fence_state[i].fd,
1256 fence_state[i].sync_file->file);
1257
1258 kfree(fence_state);
1259 return;
1260 }
1261
1262 for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
1263 struct drm_pending_vblank_event *event = crtc_state->event;
1264
1265
1266
1267
1268
1269 if (event && (event->base.fence || event->base.file_priv)) {
1270 drm_event_cancel_free(dev, &event->base);
1271 crtc_state->event = NULL;
1272 }
1273 }
1274
1275 if (!fence_state)
1276 return;
1277
1278 for (i = 0; i < num_fences; i++) {
1279 if (fence_state[i].sync_file)
1280 fput(fence_state[i].sync_file->file);
1281 if (fence_state[i].fd >= 0)
1282 put_unused_fd(fence_state[i].fd);
1283
1284
1285 if (fence_state[i].out_fence_ptr &&
1286 put_user(-1, fence_state[i].out_fence_ptr))
1287 DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
1288 }
1289
1290 kfree(fence_state);
1291}
1292
1293int drm_mode_atomic_ioctl(struct drm_device *dev,
1294 void *data, struct drm_file *file_priv)
1295{
1296 struct drm_mode_atomic *arg = data;
1297 uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
1298 uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
1299 uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
1300 uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
1301 unsigned int copied_objs, copied_props;
1302 struct drm_atomic_state *state;
1303 struct drm_modeset_acquire_ctx ctx;
1304 struct drm_out_fence_state *fence_state;
1305 int ret = 0;
1306 unsigned int i, j, num_fences;
1307
1308
1309 if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
1310 return -EOPNOTSUPP;
1311
1312
1313
1314
1315
1316 if (!file_priv->atomic)
1317 return -EINVAL;
1318
1319 if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS)
1320 return -EINVAL;
1321
1322 if (arg->reserved)
1323 return -EINVAL;
1324
1325 if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC)
1326 return -EINVAL;
1327
1328
1329 if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
1330 (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
1331 return -EINVAL;
1332
1333 state = drm_atomic_state_alloc(dev);
1334 if (!state)
1335 return -ENOMEM;
1336
1337 drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
1338 state->acquire_ctx = &ctx;
1339 state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
1340
1341retry:
1342 copied_objs = 0;
1343 copied_props = 0;
1344 fence_state = NULL;
1345 num_fences = 0;
1346
1347 for (i = 0; i < arg->count_objs; i++) {
1348 uint32_t obj_id, count_props;
1349 struct drm_mode_object *obj;
1350
1351 if (get_user(obj_id, objs_ptr + copied_objs)) {
1352 ret = -EFAULT;
1353 goto out;
1354 }
1355
1356 obj = drm_mode_object_find(dev, file_priv, obj_id, DRM_MODE_OBJECT_ANY);
1357 if (!obj) {
1358 ret = -ENOENT;
1359 goto out;
1360 }
1361
1362 if (!obj->properties) {
1363 drm_mode_object_put(obj);
1364 ret = -ENOENT;
1365 goto out;
1366 }
1367
1368 if (get_user(count_props, count_props_ptr + copied_objs)) {
1369 drm_mode_object_put(obj);
1370 ret = -EFAULT;
1371 goto out;
1372 }
1373
1374 copied_objs++;
1375
1376 for (j = 0; j < count_props; j++) {
1377 uint32_t prop_id;
1378 uint64_t prop_value;
1379 struct drm_property *prop;
1380
1381 if (get_user(prop_id, props_ptr + copied_props)) {
1382 drm_mode_object_put(obj);
1383 ret = -EFAULT;
1384 goto out;
1385 }
1386
1387 prop = drm_mode_obj_find_prop_id(obj, prop_id);
1388 if (!prop) {
1389 drm_mode_object_put(obj);
1390 ret = -ENOENT;
1391 goto out;
1392 }
1393
1394 if (copy_from_user(&prop_value,
1395 prop_values_ptr + copied_props,
1396 sizeof(prop_value))) {
1397 drm_mode_object_put(obj);
1398 ret = -EFAULT;
1399 goto out;
1400 }
1401
1402 ret = drm_atomic_set_property(state, file_priv,
1403 obj, prop, prop_value);
1404 if (ret) {
1405 drm_mode_object_put(obj);
1406 goto out;
1407 }
1408
1409 copied_props++;
1410 }
1411
1412 drm_mode_object_put(obj);
1413 }
1414
1415 ret = prepare_signaling(dev, state, arg, file_priv, &fence_state,
1416 &num_fences);
1417 if (ret)
1418 goto out;
1419
1420 if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
1421 ret = drm_atomic_check_only(state);
1422 } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
1423 ret = drm_atomic_nonblocking_commit(state);
1424 } else {
1425 if (drm_debug_enabled(DRM_UT_STATE))
1426 drm_atomic_print_state(state);
1427
1428 ret = drm_atomic_commit(state);
1429 }
1430
1431out:
1432 complete_signaling(dev, state, fence_state, num_fences, !ret);
1433
1434 if (ret == -EDEADLK) {
1435 drm_atomic_state_clear(state);
1436 ret = drm_modeset_backoff(&ctx);
1437 if (!ret)
1438 goto retry;
1439 }
1440
1441 drm_atomic_state_put(state);
1442
1443 drm_modeset_drop_locks(&ctx);
1444 drm_modeset_acquire_fini(&ctx);
1445
1446 return ret;
1447}
1448