2 * Copyright (C) 2014 Red Hat
3 * Copyright (C) 2014 Intel Corp.
4 * Copyright (C) 2018 Intel Corp.
5 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
26 * Rob Clark <robdclark@gmail.com>
27 * Daniel Vetter <daniel.vetter@ffwll.ch>
30 #include <drm/drm_atomic_uapi.h>
31 #include <drm/drm_atomic.h>
32 #include <drm/drm_framebuffer.h>
33 #include <drm/drm_print.h>
34 #include <drm/drm_drv.h>
35 #include <drm/drm_writeback.h>
36 #include <drm/drm_vblank.h>
38 #include <linux/dma-fence.h>
39 #include <linux/uaccess.h>
40 #include <linux/sync_file.h>
41 #include <linux/file.h>
43 #include "drm_crtc_internal.h"
48 * This file contains the marshalling and demarshalling glue for the atomic UAPI
49 * in all its forms: The monster ATOMIC IOCTL itself, code for GET_PROPERTY and
50 * SET_PROPERTY IOCTLs. Plus interface functions for compatibility helpers and
51 * drivers which have special needs to construct their own atomic updates, e.g.
52 * for load detect or similar.
56 * drm_atomic_set_mode_for_crtc - set mode for CRTC
57 * @state: the CRTC whose incoming state to update
58 * @mode: kernel-internal mode to use for the CRTC, or NULL to disable
60 * Set a mode (originating from the kernel) on the desired CRTC state and update
61 * the enable property.
64 * Zero on success, error code on failure. Cannot return -EDEADLK.
66 int drm_atomic_set_mode_for_crtc(struct drm_crtc_state
*state
,
67 const struct drm_display_mode
*mode
)
69 struct drm_crtc
*crtc
= state
->crtc
;
70 struct drm_mode_modeinfo umode
;
72 /* Early return for no change. */
73 if (mode
&& memcmp(&state
->mode
, mode
, sizeof(*mode
)) == 0)
76 drm_property_blob_put(state
->mode_blob
);
77 state
->mode_blob
= NULL
;
80 struct drm_property_blob
*blob
;
82 drm_mode_convert_to_umode(&umode
, mode
);
83 blob
= drm_property_create_blob(crtc
->dev
,
84 sizeof(umode
), &umode
);
88 drm_mode_copy(&state
->mode
, mode
);
90 state
->mode_blob
= blob
;
92 drm_dbg_atomic(crtc
->dev
,
93 "Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
94 mode
->name
, crtc
->base
.id
, crtc
->name
, state
);
96 memset(&state
->mode
, 0, sizeof(state
->mode
));
97 state
->enable
= false;
98 drm_dbg_atomic(crtc
->dev
,
99 "Set [NOMODE] for [CRTC:%d:%s] state %p\n",
100 crtc
->base
.id
, crtc
->name
, state
);
105 EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc
);
108 * drm_atomic_set_mode_prop_for_crtc - set mode for CRTC
109 * @state: the CRTC whose incoming state to update
110 * @blob: pointer to blob property to use for mode
112 * Set a mode (originating from a blob property) on the desired CRTC state.
113 * This function will take a reference on the blob property for the CRTC state,
114 * and release the reference held on the state's existing mode property, if any
118 * Zero on success, error code on failure. Cannot return -EDEADLK.
120 int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state
*state
,
121 struct drm_property_blob
*blob
)
123 struct drm_crtc
*crtc
= state
->crtc
;
125 if (blob
== state
->mode_blob
)
128 drm_property_blob_put(state
->mode_blob
);
129 state
->mode_blob
= NULL
;
131 memset(&state
->mode
, 0, sizeof(state
->mode
));
136 if (blob
->length
!= sizeof(struct drm_mode_modeinfo
)) {
137 drm_dbg_atomic(crtc
->dev
,
138 "[CRTC:%d:%s] bad mode blob length: %zu\n",
139 crtc
->base
.id
, crtc
->name
,
144 ret
= drm_mode_convert_umode(crtc
->dev
,
145 &state
->mode
, blob
->data
);
147 drm_dbg_atomic(crtc
->dev
,
148 "[CRTC:%d:%s] invalid mode (%s, %pe): " DRM_MODE_FMT
"\n",
149 crtc
->base
.id
, crtc
->name
,
150 drm_get_mode_status_name(state
->mode
.status
),
151 ERR_PTR(ret
), DRM_MODE_ARG(&state
->mode
));
155 state
->mode_blob
= drm_property_blob_get(blob
);
156 state
->enable
= true;
157 drm_dbg_atomic(crtc
->dev
,
158 "Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
159 state
->mode
.name
, crtc
->base
.id
, crtc
->name
,
162 state
->enable
= false;
163 drm_dbg_atomic(crtc
->dev
,
164 "Set [NOMODE] for [CRTC:%d:%s] state %p\n",
165 crtc
->base
.id
, crtc
->name
, state
);
170 EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc
);
173 * drm_atomic_set_crtc_for_plane - set CRTC for plane
174 * @plane_state: the plane whose incoming state to update
175 * @crtc: CRTC to use for the plane
177 * Changing the assigned CRTC for a plane requires us to grab the lock and state
178 * for the new CRTC, as needed. This function takes care of all these details
179 * besides updating the pointer in the state object itself.
182 * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
183 * then the w/w mutex code has detected a deadlock and the entire atomic
184 * sequence must be restarted. All other errors are fatal.
187 drm_atomic_set_crtc_for_plane(struct drm_plane_state
*plane_state
,
188 struct drm_crtc
*crtc
)
190 struct drm_plane
*plane
= plane_state
->plane
;
191 struct drm_crtc_state
*crtc_state
;
192 /* Nothing to do for same crtc*/
193 if (plane_state
->crtc
== crtc
)
195 if (plane_state
->crtc
) {
196 crtc_state
= drm_atomic_get_crtc_state(plane_state
->state
,
198 if (WARN_ON(IS_ERR(crtc_state
)))
199 return PTR_ERR(crtc_state
);
201 crtc_state
->plane_mask
&= ~drm_plane_mask(plane
);
204 plane_state
->crtc
= crtc
;
207 crtc_state
= drm_atomic_get_crtc_state(plane_state
->state
,
209 if (IS_ERR(crtc_state
))
210 return PTR_ERR(crtc_state
);
211 crtc_state
->plane_mask
|= drm_plane_mask(plane
);
215 drm_dbg_atomic(plane
->dev
,
216 "Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n",
217 plane
->base
.id
, plane
->name
, plane_state
,
218 crtc
->base
.id
, crtc
->name
);
220 drm_dbg_atomic(plane
->dev
,
221 "Link [PLANE:%d:%s] state %p to [NOCRTC]\n",
222 plane
->base
.id
, plane
->name
, plane_state
);
226 EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane
);
229 * drm_atomic_set_fb_for_plane - set framebuffer for plane
230 * @plane_state: atomic state object for the plane
231 * @fb: fb to use for the plane
233 * Changing the assigned framebuffer for a plane requires us to grab a reference
234 * to the new fb and drop the reference to the old fb, if there is one. This
235 * function takes care of all these details besides updating the pointer in the
236 * state object itself.
239 drm_atomic_set_fb_for_plane(struct drm_plane_state
*plane_state
,
240 struct drm_framebuffer
*fb
)
242 struct drm_plane
*plane
= plane_state
->plane
;
245 drm_dbg_atomic(plane
->dev
,
246 "Set [FB:%d] for [PLANE:%d:%s] state %p\n",
247 fb
->base
.id
, plane
->base
.id
, plane
->name
,
250 drm_dbg_atomic(plane
->dev
,
251 "Set [NOFB] for [PLANE:%d:%s] state %p\n",
252 plane
->base
.id
, plane
->name
, plane_state
);
254 drm_framebuffer_assign(&plane_state
->fb
, fb
);
256 EXPORT_SYMBOL(drm_atomic_set_fb_for_plane
);
259 * drm_atomic_set_crtc_for_connector - set CRTC for connector
260 * @conn_state: atomic state object for the connector
261 * @crtc: CRTC to use for the connector
263 * Changing the assigned CRTC for a connector requires us to grab the lock and
264 * state for the new CRTC, as needed. This function takes care of all these
265 * details besides updating the pointer in the state object itself.
268 * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
269 * then the w/w mutex code has detected a deadlock and the entire atomic
270 * sequence must be restarted. All other errors are fatal.
273 drm_atomic_set_crtc_for_connector(struct drm_connector_state
*conn_state
,
274 struct drm_crtc
*crtc
)
276 struct drm_connector
*connector
= conn_state
->connector
;
277 struct drm_crtc_state
*crtc_state
;
279 if (conn_state
->crtc
== crtc
)
282 if (conn_state
->crtc
) {
283 crtc_state
= drm_atomic_get_new_crtc_state(conn_state
->state
,
286 crtc_state
->connector_mask
&=
287 ~drm_connector_mask(conn_state
->connector
);
289 drm_connector_put(conn_state
->connector
);
290 conn_state
->crtc
= NULL
;
294 crtc_state
= drm_atomic_get_crtc_state(conn_state
->state
, crtc
);
295 if (IS_ERR(crtc_state
))
296 return PTR_ERR(crtc_state
);
298 crtc_state
->connector_mask
|=
299 drm_connector_mask(conn_state
->connector
);
301 drm_connector_get(conn_state
->connector
);
302 conn_state
->crtc
= crtc
;
304 drm_dbg_atomic(connector
->dev
,
305 "Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n",
306 connector
->base
.id
, connector
->name
,
307 conn_state
, crtc
->base
.id
, crtc
->name
);
309 drm_dbg_atomic(connector
->dev
,
310 "Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n",
311 connector
->base
.id
, connector
->name
,
317 EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector
);
319 static void set_out_fence_for_crtc(struct drm_atomic_state
*state
,
320 struct drm_crtc
*crtc
, s32 __user
*fence_ptr
)
322 state
->crtcs
[drm_crtc_index(crtc
)].out_fence_ptr
= fence_ptr
;
325 static s32 __user
*get_out_fence_for_crtc(struct drm_atomic_state
*state
,
326 struct drm_crtc
*crtc
)
328 s32 __user
*fence_ptr
;
330 fence_ptr
= state
->crtcs
[drm_crtc_index(crtc
)].out_fence_ptr
;
331 state
->crtcs
[drm_crtc_index(crtc
)].out_fence_ptr
= NULL
;
336 static int set_out_fence_for_connector(struct drm_atomic_state
*state
,
337 struct drm_connector
*connector
,
338 s32 __user
*fence_ptr
)
340 unsigned int index
= drm_connector_index(connector
);
345 if (put_user(-1, fence_ptr
))
348 state
->connectors
[index
].out_fence_ptr
= fence_ptr
;
353 static s32 __user
*get_out_fence_for_connector(struct drm_atomic_state
*state
,
354 struct drm_connector
*connector
)
356 unsigned int index
= drm_connector_index(connector
);
357 s32 __user
*fence_ptr
;
359 fence_ptr
= state
->connectors
[index
].out_fence_ptr
;
360 state
->connectors
[index
].out_fence_ptr
= NULL
;
365 static int drm_atomic_crtc_set_property(struct drm_crtc
*crtc
,
366 struct drm_crtc_state
*state
, struct drm_property
*property
,
369 struct drm_device
*dev
= crtc
->dev
;
370 struct drm_mode_config
*config
= &dev
->mode_config
;
371 bool replaced
= false;
374 if (property
== config
->prop_active
)
376 else if (property
== config
->prop_mode_id
) {
377 struct drm_property_blob
*mode
=
378 drm_property_lookup_blob(dev
, val
);
379 ret
= drm_atomic_set_mode_prop_for_crtc(state
, mode
);
380 drm_property_blob_put(mode
);
382 } else if (property
== config
->prop_vrr_enabled
) {
383 state
->vrr_enabled
= val
;
384 } else if (property
== config
->degamma_lut_property
) {
385 ret
= drm_property_replace_blob_from_id(dev
,
388 -1, sizeof(struct drm_color_lut
),
390 state
->color_mgmt_changed
|= replaced
;
392 } else if (property
== config
->ctm_property
) {
393 ret
= drm_property_replace_blob_from_id(dev
,
396 sizeof(struct drm_color_ctm
), -1,
398 state
->color_mgmt_changed
|= replaced
;
400 } else if (property
== config
->gamma_lut_property
) {
401 ret
= drm_property_replace_blob_from_id(dev
,
404 -1, sizeof(struct drm_color_lut
),
406 state
->color_mgmt_changed
|= replaced
;
408 } else if (property
== config
->prop_out_fence_ptr
) {
409 s32 __user
*fence_ptr
= u64_to_user_ptr(val
);
414 if (put_user(-1, fence_ptr
))
417 set_out_fence_for_crtc(state
->state
, crtc
, fence_ptr
);
418 } else if (property
== crtc
->scaling_filter_property
) {
419 state
->scaling_filter
= val
;
420 } else if (crtc
->funcs
->atomic_set_property
) {
421 return crtc
->funcs
->atomic_set_property(crtc
, state
, property
, val
);
423 drm_dbg_atomic(crtc
->dev
,
424 "[CRTC:%d:%s] unknown property [PROP:%d:%s]\n",
425 crtc
->base
.id
, crtc
->name
,
426 property
->base
.id
, property
->name
);
434 drm_atomic_crtc_get_property(struct drm_crtc
*crtc
,
435 const struct drm_crtc_state
*state
,
436 struct drm_property
*property
, uint64_t *val
)
438 struct drm_device
*dev
= crtc
->dev
;
439 struct drm_mode_config
*config
= &dev
->mode_config
;
441 if (property
== config
->prop_active
)
442 *val
= drm_atomic_crtc_effectively_active(state
);
443 else if (property
== config
->prop_mode_id
)
444 *val
= (state
->mode_blob
) ? state
->mode_blob
->base
.id
: 0;
445 else if (property
== config
->prop_vrr_enabled
)
446 *val
= state
->vrr_enabled
;
447 else if (property
== config
->degamma_lut_property
)
448 *val
= (state
->degamma_lut
) ? state
->degamma_lut
->base
.id
: 0;
449 else if (property
== config
->ctm_property
)
450 *val
= (state
->ctm
) ? state
->ctm
->base
.id
: 0;
451 else if (property
== config
->gamma_lut_property
)
452 *val
= (state
->gamma_lut
) ? state
->gamma_lut
->base
.id
: 0;
453 else if (property
== config
->prop_out_fence_ptr
)
455 else if (property
== crtc
->scaling_filter_property
)
456 *val
= state
->scaling_filter
;
457 else if (crtc
->funcs
->atomic_get_property
)
458 return crtc
->funcs
->atomic_get_property(crtc
, state
, property
, val
);
461 "[CRTC:%d:%s] unknown property [PROP:%d:%s]\n",
462 crtc
->base
.id
, crtc
->name
,
463 property
->base
.id
, property
->name
);
470 static int drm_atomic_plane_set_property(struct drm_plane
*plane
,
471 struct drm_plane_state
*state
, struct drm_file
*file_priv
,
472 struct drm_property
*property
, uint64_t val
)
474 struct drm_device
*dev
= plane
->dev
;
475 struct drm_mode_config
*config
= &dev
->mode_config
;
476 bool replaced
= false;
479 if (property
== config
->prop_fb_id
) {
480 struct drm_framebuffer
*fb
;
482 fb
= drm_framebuffer_lookup(dev
, file_priv
, val
);
483 drm_atomic_set_fb_for_plane(state
, fb
);
485 drm_framebuffer_put(fb
);
486 } else if (property
== config
->prop_in_fence_fd
) {
490 if (U642I64(val
) == -1)
493 state
->fence
= sync_file_get_fence(val
);
497 } else if (property
== config
->prop_crtc_id
) {
498 struct drm_crtc
*crtc
= drm_crtc_find(dev
, file_priv
, val
);
502 "[PROP:%d:%s] cannot find CRTC with ID %llu\n",
503 property
->base
.id
, property
->name
, val
);
506 return drm_atomic_set_crtc_for_plane(state
, crtc
);
507 } else if (property
== config
->prop_crtc_x
) {
508 state
->crtc_x
= U642I64(val
);
509 } else if (property
== config
->prop_crtc_y
) {
510 state
->crtc_y
= U642I64(val
);
511 } else if (property
== config
->prop_crtc_w
) {
513 } else if (property
== config
->prop_crtc_h
) {
515 } else if (property
== config
->prop_src_x
) {
517 } else if (property
== config
->prop_src_y
) {
519 } else if (property
== config
->prop_src_w
) {
521 } else if (property
== config
->prop_src_h
) {
523 } else if (property
== plane
->alpha_property
) {
525 } else if (property
== plane
->blend_mode_property
) {
526 state
->pixel_blend_mode
= val
;
527 } else if (property
== plane
->rotation_property
) {
528 if (!is_power_of_2(val
& DRM_MODE_ROTATE_MASK
)) {
529 drm_dbg_atomic(plane
->dev
,
530 "[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n",
531 plane
->base
.id
, plane
->name
, val
);
534 state
->rotation
= val
;
535 } else if (property
== plane
->zpos_property
) {
537 } else if (property
== plane
->color_encoding_property
) {
538 state
->color_encoding
= val
;
539 } else if (property
== plane
->color_range_property
) {
540 state
->color_range
= val
;
541 } else if (property
== config
->prop_fb_damage_clips
) {
542 ret
= drm_property_replace_blob_from_id(dev
,
543 &state
->fb_damage_clips
,
546 sizeof(struct drm_mode_rect
),
549 } else if (property
== plane
->scaling_filter_property
) {
550 state
->scaling_filter
= val
;
551 } else if (plane
->funcs
->atomic_set_property
) {
552 return plane
->funcs
->atomic_set_property(plane
, state
,
554 } else if (property
== plane
->hotspot_x_property
) {
555 if (plane
->type
!= DRM_PLANE_TYPE_CURSOR
) {
556 drm_dbg_atomic(plane
->dev
,
557 "[PLANE:%d:%s] is not a cursor plane: 0x%llx\n",
558 plane
->base
.id
, plane
->name
, val
);
561 state
->hotspot_x
= val
;
562 } else if (property
== plane
->hotspot_y_property
) {
563 if (plane
->type
!= DRM_PLANE_TYPE_CURSOR
) {
564 drm_dbg_atomic(plane
->dev
,
565 "[PLANE:%d:%s] is not a cursor plane: 0x%llx\n",
566 plane
->base
.id
, plane
->name
, val
);
569 state
->hotspot_y
= val
;
571 drm_dbg_atomic(plane
->dev
,
572 "[PLANE:%d:%s] unknown property [PROP:%d:%s]\n",
573 plane
->base
.id
, plane
->name
,
574 property
->base
.id
, property
->name
);
582 drm_atomic_plane_get_property(struct drm_plane
*plane
,
583 const struct drm_plane_state
*state
,
584 struct drm_property
*property
, uint64_t *val
)
586 struct drm_device
*dev
= plane
->dev
;
587 struct drm_mode_config
*config
= &dev
->mode_config
;
589 if (property
== config
->prop_fb_id
) {
590 *val
= (state
->fb
) ? state
->fb
->base
.id
: 0;
591 } else if (property
== config
->prop_in_fence_fd
) {
593 } else if (property
== config
->prop_crtc_id
) {
594 *val
= (state
->crtc
) ? state
->crtc
->base
.id
: 0;
595 } else if (property
== config
->prop_crtc_x
) {
596 *val
= I642U64(state
->crtc_x
);
597 } else if (property
== config
->prop_crtc_y
) {
598 *val
= I642U64(state
->crtc_y
);
599 } else if (property
== config
->prop_crtc_w
) {
600 *val
= state
->crtc_w
;
601 } else if (property
== config
->prop_crtc_h
) {
602 *val
= state
->crtc_h
;
603 } else if (property
== config
->prop_src_x
) {
605 } else if (property
== config
->prop_src_y
) {
607 } else if (property
== config
->prop_src_w
) {
609 } else if (property
== config
->prop_src_h
) {
611 } else if (property
== plane
->alpha_property
) {
613 } else if (property
== plane
->blend_mode_property
) {
614 *val
= state
->pixel_blend_mode
;
615 } else if (property
== plane
->rotation_property
) {
616 *val
= state
->rotation
;
617 } else if (property
== plane
->zpos_property
) {
619 } else if (property
== plane
->color_encoding_property
) {
620 *val
= state
->color_encoding
;
621 } else if (property
== plane
->color_range_property
) {
622 *val
= state
->color_range
;
623 } else if (property
== config
->prop_fb_damage_clips
) {
624 *val
= (state
->fb_damage_clips
) ?
625 state
->fb_damage_clips
->base
.id
: 0;
626 } else if (property
== plane
->scaling_filter_property
) {
627 *val
= state
->scaling_filter
;
628 } else if (plane
->funcs
->atomic_get_property
) {
629 return plane
->funcs
->atomic_get_property(plane
, state
, property
, val
);
630 } else if (property
== plane
->hotspot_x_property
) {
631 *val
= state
->hotspot_x
;
632 } else if (property
== plane
->hotspot_y_property
) {
633 *val
= state
->hotspot_y
;
636 "[PLANE:%d:%s] unknown property [PROP:%d:%s]\n",
637 plane
->base
.id
, plane
->name
,
638 property
->base
.id
, property
->name
);
645 static int drm_atomic_set_writeback_fb_for_connector(
646 struct drm_connector_state
*conn_state
,
647 struct drm_framebuffer
*fb
)
650 struct drm_connector
*conn
= conn_state
->connector
;
652 ret
= drm_writeback_set_fb(conn_state
, fb
);
657 drm_dbg_atomic(conn
->dev
,
658 "Set [FB:%d] for connector state %p\n",
659 fb
->base
.id
, conn_state
);
661 drm_dbg_atomic(conn
->dev
,
662 "Set [NOFB] for connector state %p\n",
668 static int drm_atomic_connector_set_property(struct drm_connector
*connector
,
669 struct drm_connector_state
*state
, struct drm_file
*file_priv
,
670 struct drm_property
*property
, uint64_t val
)
672 struct drm_device
*dev
= connector
->dev
;
673 struct drm_mode_config
*config
= &dev
->mode_config
;
674 bool replaced
= false;
677 if (property
== config
->prop_crtc_id
) {
678 struct drm_crtc
*crtc
= drm_crtc_find(dev
, file_priv
, val
);
682 "[PROP:%d:%s] cannot find CRTC with ID %llu\n",
683 property
->base
.id
, property
->name
, val
);
686 return drm_atomic_set_crtc_for_connector(state
, crtc
);
687 } else if (property
== config
->dpms_property
) {
688 /* setting DPMS property requires special handling, which
689 * is done in legacy setprop path for us. Disallow (for
690 * now?) atomic writes to DPMS property:
693 "legacy [PROP:%d:%s] can only be set via legacy uAPI\n",
694 property
->base
.id
, property
->name
);
696 } else if (property
== config
->tv_select_subconnector_property
) {
697 state
->tv
.select_subconnector
= val
;
698 } else if (property
== config
->tv_subconnector_property
) {
699 state
->tv
.subconnector
= val
;
700 } else if (property
== config
->tv_left_margin_property
) {
701 state
->tv
.margins
.left
= val
;
702 } else if (property
== config
->tv_right_margin_property
) {
703 state
->tv
.margins
.right
= val
;
704 } else if (property
== config
->tv_top_margin_property
) {
705 state
->tv
.margins
.top
= val
;
706 } else if (property
== config
->tv_bottom_margin_property
) {
707 state
->tv
.margins
.bottom
= val
;
708 } else if (property
== config
->legacy_tv_mode_property
) {
709 state
->tv
.legacy_mode
= val
;
710 } else if (property
== config
->tv_mode_property
) {
711 state
->tv
.mode
= val
;
712 } else if (property
== config
->tv_brightness_property
) {
713 state
->tv
.brightness
= val
;
714 } else if (property
== config
->tv_contrast_property
) {
715 state
->tv
.contrast
= val
;
716 } else if (property
== config
->tv_flicker_reduction_property
) {
717 state
->tv
.flicker_reduction
= val
;
718 } else if (property
== config
->tv_overscan_property
) {
719 state
->tv
.overscan
= val
;
720 } else if (property
== config
->tv_saturation_property
) {
721 state
->tv
.saturation
= val
;
722 } else if (property
== config
->tv_hue_property
) {
724 } else if (property
== config
->link_status_property
) {
725 /* Never downgrade from GOOD to BAD on userspace's request here,
726 * only hw issues can do that.
728 * For an atomic property the userspace doesn't need to be able
729 * to understand all the properties, but needs to be able to
730 * restore the state it wants on VT switch. So if the userspace
731 * tries to change the link_status from GOOD to BAD, driver
732 * silently rejects it and returns a 0. This prevents userspace
733 * from accidentally breaking the display when it restores the
736 if (state
->link_status
!= DRM_LINK_STATUS_GOOD
)
737 state
->link_status
= val
;
738 } else if (property
== config
->hdr_output_metadata_property
) {
739 ret
= drm_property_replace_blob_from_id(dev
,
740 &state
->hdr_output_metadata
,
742 sizeof(struct hdr_output_metadata
), -1,
745 } else if (property
== config
->aspect_ratio_property
) {
746 state
->picture_aspect_ratio
= val
;
747 } else if (property
== config
->content_type_property
) {
748 state
->content_type
= val
;
749 } else if (property
== connector
->scaling_mode_property
) {
750 state
->scaling_mode
= val
;
751 } else if (property
== config
->content_protection_property
) {
752 if (val
== DRM_MODE_CONTENT_PROTECTION_ENABLED
) {
753 drm_dbg_kms(dev
, "only drivers can set CP Enabled\n");
756 state
->content_protection
= val
;
757 } else if (property
== config
->hdcp_content_type_property
) {
758 state
->hdcp_content_type
= val
;
759 } else if (property
== connector
->colorspace_property
) {
760 state
->colorspace
= val
;
761 } else if (property
== config
->writeback_fb_id_property
) {
762 struct drm_framebuffer
*fb
;
765 fb
= drm_framebuffer_lookup(dev
, file_priv
, val
);
766 ret
= drm_atomic_set_writeback_fb_for_connector(state
, fb
);
768 drm_framebuffer_put(fb
);
770 } else if (property
== config
->writeback_out_fence_ptr_property
) {
771 s32 __user
*fence_ptr
= u64_to_user_ptr(val
);
773 return set_out_fence_for_connector(state
->state
, connector
,
775 } else if (property
== connector
->max_bpc_property
) {
776 state
->max_requested_bpc
= val
;
777 } else if (property
== connector
->privacy_screen_sw_state_property
) {
778 state
->privacy_screen_sw_state
= val
;
779 } else if (property
== connector
->broadcast_rgb_property
) {
780 state
->hdmi
.broadcast_rgb
= val
;
781 } else if (connector
->funcs
->atomic_set_property
) {
782 return connector
->funcs
->atomic_set_property(connector
,
783 state
, property
, val
);
785 drm_dbg_atomic(connector
->dev
,
786 "[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]\n",
787 connector
->base
.id
, connector
->name
,
788 property
->base
.id
, property
->name
);
796 drm_atomic_connector_get_property(struct drm_connector
*connector
,
797 const struct drm_connector_state
*state
,
798 struct drm_property
*property
, uint64_t *val
)
800 struct drm_device
*dev
= connector
->dev
;
801 struct drm_mode_config
*config
= &dev
->mode_config
;
803 if (property
== config
->prop_crtc_id
) {
804 *val
= (state
->crtc
) ? state
->crtc
->base
.id
: 0;
805 } else if (property
== config
->dpms_property
) {
806 if (state
->crtc
&& state
->crtc
->state
->self_refresh_active
)
807 *val
= DRM_MODE_DPMS_ON
;
809 *val
= connector
->dpms
;
810 } else if (property
== config
->tv_select_subconnector_property
) {
811 *val
= state
->tv
.select_subconnector
;
812 } else if (property
== config
->tv_subconnector_property
) {
813 *val
= state
->tv
.subconnector
;
814 } else if (property
== config
->tv_left_margin_property
) {
815 *val
= state
->tv
.margins
.left
;
816 } else if (property
== config
->tv_right_margin_property
) {
817 *val
= state
->tv
.margins
.right
;
818 } else if (property
== config
->tv_top_margin_property
) {
819 *val
= state
->tv
.margins
.top
;
820 } else if (property
== config
->tv_bottom_margin_property
) {
821 *val
= state
->tv
.margins
.bottom
;
822 } else if (property
== config
->legacy_tv_mode_property
) {
823 *val
= state
->tv
.legacy_mode
;
824 } else if (property
== config
->tv_mode_property
) {
825 *val
= state
->tv
.mode
;
826 } else if (property
== config
->tv_brightness_property
) {
827 *val
= state
->tv
.brightness
;
828 } else if (property
== config
->tv_contrast_property
) {
829 *val
= state
->tv
.contrast
;
830 } else if (property
== config
->tv_flicker_reduction_property
) {
831 *val
= state
->tv
.flicker_reduction
;
832 } else if (property
== config
->tv_overscan_property
) {
833 *val
= state
->tv
.overscan
;
834 } else if (property
== config
->tv_saturation_property
) {
835 *val
= state
->tv
.saturation
;
836 } else if (property
== config
->tv_hue_property
) {
837 *val
= state
->tv
.hue
;
838 } else if (property
== config
->link_status_property
) {
839 *val
= state
->link_status
;
840 } else if (property
== config
->aspect_ratio_property
) {
841 *val
= state
->picture_aspect_ratio
;
842 } else if (property
== config
->content_type_property
) {
843 *val
= state
->content_type
;
844 } else if (property
== connector
->colorspace_property
) {
845 *val
= state
->colorspace
;
846 } else if (property
== connector
->scaling_mode_property
) {
847 *val
= state
->scaling_mode
;
848 } else if (property
== config
->hdr_output_metadata_property
) {
849 *val
= state
->hdr_output_metadata
?
850 state
->hdr_output_metadata
->base
.id
: 0;
851 } else if (property
== config
->content_protection_property
) {
852 *val
= state
->content_protection
;
853 } else if (property
== config
->hdcp_content_type_property
) {
854 *val
= state
->hdcp_content_type
;
855 } else if (property
== config
->writeback_fb_id_property
) {
856 /* Writeback framebuffer is one-shot, write and forget */
858 } else if (property
== config
->writeback_out_fence_ptr_property
) {
860 } else if (property
== connector
->max_bpc_property
) {
861 *val
= state
->max_requested_bpc
;
862 } else if (property
== connector
->privacy_screen_sw_state_property
) {
863 *val
= state
->privacy_screen_sw_state
;
864 } else if (property
== connector
->broadcast_rgb_property
) {
865 *val
= state
->hdmi
.broadcast_rgb
;
866 } else if (connector
->funcs
->atomic_get_property
) {
867 return connector
->funcs
->atomic_get_property(connector
,
868 state
, property
, val
);
871 "[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]\n",
872 connector
->base
.id
, connector
->name
,
873 property
->base
.id
, property
->name
);
880 int drm_atomic_get_property(struct drm_mode_object
*obj
,
881 struct drm_property
*property
, uint64_t *val
)
883 struct drm_device
*dev
= property
->dev
;
887 case DRM_MODE_OBJECT_CONNECTOR
: {
888 struct drm_connector
*connector
= obj_to_connector(obj
);
890 WARN_ON(!drm_modeset_is_locked(&dev
->mode_config
.connection_mutex
));
891 ret
= drm_atomic_connector_get_property(connector
,
892 connector
->state
, property
, val
);
895 case DRM_MODE_OBJECT_CRTC
: {
896 struct drm_crtc
*crtc
= obj_to_crtc(obj
);
898 WARN_ON(!drm_modeset_is_locked(&crtc
->mutex
));
899 ret
= drm_atomic_crtc_get_property(crtc
,
900 crtc
->state
, property
, val
);
903 case DRM_MODE_OBJECT_PLANE
: {
904 struct drm_plane
*plane
= obj_to_plane(obj
);
906 WARN_ON(!drm_modeset_is_locked(&plane
->mutex
));
907 ret
= drm_atomic_plane_get_property(plane
,
908 plane
->state
, property
, val
);
912 drm_dbg_atomic(dev
, "[OBJECT:%d] has no properties\n", obj
->id
);
921 * The big monster ioctl
924 static struct drm_pending_vblank_event
*create_vblank_event(
925 struct drm_crtc
*crtc
, uint64_t user_data
)
927 struct drm_pending_vblank_event
*e
= NULL
;
929 e
= kzalloc(sizeof *e
, GFP_KERNEL
);
933 e
->event
.base
.type
= DRM_EVENT_FLIP_COMPLETE
;
934 e
->event
.base
.length
= sizeof(e
->event
);
935 e
->event
.vbl
.crtc_id
= crtc
->base
.id
;
936 e
->event
.vbl
.user_data
= user_data
;
941 int drm_atomic_connector_commit_dpms(struct drm_atomic_state
*state
,
942 struct drm_connector
*connector
,
945 struct drm_connector
*tmp_connector
;
946 struct drm_connector_state
*new_conn_state
;
947 struct drm_crtc
*crtc
;
948 struct drm_crtc_state
*crtc_state
;
949 int i
, ret
, old_mode
= connector
->dpms
;
952 ret
= drm_modeset_lock(&state
->dev
->mode_config
.connection_mutex
,
957 if (mode
!= DRM_MODE_DPMS_ON
)
958 mode
= DRM_MODE_DPMS_OFF
;
959 connector
->dpms
= mode
;
961 crtc
= connector
->state
->crtc
;
964 ret
= drm_atomic_add_affected_connectors(state
, crtc
);
968 crtc_state
= drm_atomic_get_crtc_state(state
, crtc
);
969 if (IS_ERR(crtc_state
)) {
970 ret
= PTR_ERR(crtc_state
);
974 for_each_new_connector_in_state(state
, tmp_connector
, new_conn_state
, i
) {
975 if (new_conn_state
->crtc
!= crtc
)
977 if (tmp_connector
->dpms
== DRM_MODE_DPMS_ON
) {
983 crtc_state
->active
= active
;
984 ret
= drm_atomic_commit(state
);
987 connector
->dpms
= old_mode
;
991 static int drm_atomic_check_prop_changes(int ret
, uint64_t old_val
, uint64_t prop_value
,
992 struct drm_property
*prop
)
994 if (ret
!= 0 || old_val
!= prop_value
) {
995 drm_dbg_atomic(prop
->dev
,
996 "[PROP:%d:%s] No prop can be changed during async flip\n",
997 prop
->base
.id
, prop
->name
);
1004 int drm_atomic_set_property(struct drm_atomic_state
*state
,
1005 struct drm_file
*file_priv
,
1006 struct drm_mode_object
*obj
,
1007 struct drm_property
*prop
,
1011 struct drm_mode_object
*ref
;
1015 if (!drm_property_change_valid_get(prop
, prop_value
, &ref
))
1018 switch (obj
->type
) {
1019 case DRM_MODE_OBJECT_CONNECTOR
: {
1020 struct drm_connector
*connector
= obj_to_connector(obj
);
1021 struct drm_connector_state
*connector_state
;
1023 connector_state
= drm_atomic_get_connector_state(state
, connector
);
1024 if (IS_ERR(connector_state
)) {
1025 ret
= PTR_ERR(connector_state
);
1030 ret
= drm_atomic_connector_get_property(connector
, connector_state
,
1032 ret
= drm_atomic_check_prop_changes(ret
, old_val
, prop_value
, prop
);
1036 ret
= drm_atomic_connector_set_property(connector
,
1037 connector_state
, file_priv
,
1041 case DRM_MODE_OBJECT_CRTC
: {
1042 struct drm_crtc
*crtc
= obj_to_crtc(obj
);
1043 struct drm_crtc_state
*crtc_state
;
1045 crtc_state
= drm_atomic_get_crtc_state(state
, crtc
);
1046 if (IS_ERR(crtc_state
)) {
1047 ret
= PTR_ERR(crtc_state
);
1052 ret
= drm_atomic_crtc_get_property(crtc
, crtc_state
,
1054 ret
= drm_atomic_check_prop_changes(ret
, old_val
, prop_value
, prop
);
1058 ret
= drm_atomic_crtc_set_property(crtc
,
1059 crtc_state
, prop
, prop_value
);
1062 case DRM_MODE_OBJECT_PLANE
: {
1063 struct drm_plane
*plane
= obj_to_plane(obj
);
1064 struct drm_plane_state
*plane_state
;
1065 struct drm_mode_config
*config
= &plane
->dev
->mode_config
;
1067 plane_state
= drm_atomic_get_plane_state(state
, plane
);
1068 if (IS_ERR(plane_state
)) {
1069 ret
= PTR_ERR(plane_state
);
1074 (plane_state
->plane
->type
!= DRM_PLANE_TYPE_PRIMARY
||
1075 (prop
!= config
->prop_fb_id
&&
1076 prop
!= config
->prop_in_fence_fd
&&
1077 prop
!= config
->prop_fb_damage_clips
))) {
1078 ret
= drm_atomic_plane_get_property(plane
, plane_state
,
1080 ret
= drm_atomic_check_prop_changes(ret
, old_val
, prop_value
, prop
);
1084 ret
= drm_atomic_plane_set_property(plane
,
1085 plane_state
, file_priv
,
1090 drm_dbg_atomic(prop
->dev
, "[OBJECT:%d] has no properties\n", obj
->id
);
1095 drm_property_change_valid_put(prop
, ref
);
1100 * DOC: explicit fencing properties
1102 * Explicit fencing allows userspace to control the buffer synchronization
1103 * between devices. A Fence or a group of fences are transferred to/from
1104 * userspace using Sync File fds and there are two DRM properties for that.
1105 * IN_FENCE_FD on each DRM Plane to send fences to the kernel and
1106 * OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
1108 * As a contrast, with implicit fencing the kernel keeps track of any
1109 * ongoing rendering, and automatically ensures that the atomic update waits
1110 * for any pending rendering to complete. This is usually tracked in &struct
1111 * dma_resv which can also contain mandatory kernel fences. Implicit syncing
1112 * is how Linux traditionally worked (e.g. DRI2/3 on X.org), whereas explicit
1113 * fencing is what Android wants.
1116 * Use this property to pass a fence that DRM should wait on before
1117 * proceeding with the Atomic Commit request and show the framebuffer for
1118 * the plane on the screen. The fence can be either a normal fence or a
1119 * merged one, the sync_file framework will handle both cases and use a
1120 * fence_array if a merged fence is received. Passing -1 here means no
1121 * fences to wait on.
1123 * If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag
1124 * it will only check if the Sync File is a valid one.
1126 * On the driver side the fence is stored on the @fence parameter of
1127 * &struct drm_plane_state. Drivers which also support implicit fencing
1128 * should extract the implicit fence using drm_gem_plane_helper_prepare_fb(),
1129 * to make sure there's consistent behaviour between drivers in precedence
1130 * of implicit vs. explicit fencing.
1133 * Use this property to pass a file descriptor pointer to DRM. Once the
1134 * Atomic Commit request call returns OUT_FENCE_PTR will be filled with
1135 * the file descriptor number of a Sync File. This Sync File contains the
1136 * CRTC fence that will be signaled when all framebuffers present on the
1137 * Atomic Commit * request for that given CRTC are scanned out on the
1140 * The Atomic Commit request fails if a invalid pointer is passed. If the
1141 * Atomic Commit request fails for any other reason the out fence fd
1142 * returned will be -1. On a Atomic Commit with the
1143 * DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
1145 * Note that out-fences don't have a special interface to drivers and are
1146 * internally represented by a &struct drm_pending_vblank_event in struct
1147 * &drm_crtc_state, which is also used by the nonblocking atomic commit
1148 * helpers and for the DRM event handling for existing userspace.
1151 struct drm_out_fence_state
{
1152 s32 __user
*out_fence_ptr
;
1153 struct sync_file
*sync_file
;
1157 static int setup_out_fence(struct drm_out_fence_state
*fence_state
,
1158 struct dma_fence
*fence
)
1160 fence_state
->fd
= get_unused_fd_flags(O_CLOEXEC
);
1161 if (fence_state
->fd
< 0)
1162 return fence_state
->fd
;
1164 if (put_user(fence_state
->fd
, fence_state
->out_fence_ptr
))
1167 fence_state
->sync_file
= sync_file_create(fence
);
1168 if (!fence_state
->sync_file
)
1174 static int prepare_signaling(struct drm_device
*dev
,
1175 struct drm_atomic_state
*state
,
1176 struct drm_mode_atomic
*arg
,
1177 struct drm_file
*file_priv
,
1178 struct drm_out_fence_state
**fence_state
,
1179 unsigned int *num_fences
)
1181 struct drm_crtc
*crtc
;
1182 struct drm_crtc_state
*crtc_state
;
1183 struct drm_connector
*conn
;
1184 struct drm_connector_state
*conn_state
;
1187 if (arg
->flags
& DRM_MODE_ATOMIC_TEST_ONLY
)
1190 for_each_new_crtc_in_state(state
, crtc
, crtc_state
, i
) {
1191 s32 __user
*fence_ptr
;
1193 fence_ptr
= get_out_fence_for_crtc(crtc_state
->state
, crtc
);
1195 if (arg
->flags
& DRM_MODE_PAGE_FLIP_EVENT
|| fence_ptr
) {
1196 struct drm_pending_vblank_event
*e
;
1198 e
= create_vblank_event(crtc
, arg
->user_data
);
1202 crtc_state
->event
= e
;
1205 if (arg
->flags
& DRM_MODE_PAGE_FLIP_EVENT
) {
1206 struct drm_pending_vblank_event
*e
= crtc_state
->event
;
1211 ret
= drm_event_reserve_init(dev
, file_priv
, &e
->base
,
1215 crtc_state
->event
= NULL
;
1221 struct dma_fence
*fence
;
1222 struct drm_out_fence_state
*f
;
1224 f
= krealloc(*fence_state
, sizeof(**fence_state
) *
1225 (*num_fences
+ 1), GFP_KERNEL
);
1229 memset(&f
[*num_fences
], 0, sizeof(*f
));
1231 f
[*num_fences
].out_fence_ptr
= fence_ptr
;
1234 fence
= drm_crtc_create_fence(crtc
);
1238 ret
= setup_out_fence(&f
[(*num_fences
)++], fence
);
1240 dma_fence_put(fence
);
1244 crtc_state
->event
->base
.fence
= fence
;
1250 for_each_new_connector_in_state(state
, conn
, conn_state
, i
) {
1251 struct drm_writeback_connector
*wb_conn
;
1252 struct drm_out_fence_state
*f
;
1253 struct dma_fence
*fence
;
1254 s32 __user
*fence_ptr
;
1256 if (!conn_state
->writeback_job
)
1259 fence_ptr
= get_out_fence_for_connector(state
, conn
);
1263 f
= krealloc(*fence_state
, sizeof(**fence_state
) *
1264 (*num_fences
+ 1), GFP_KERNEL
);
1268 memset(&f
[*num_fences
], 0, sizeof(*f
));
1270 f
[*num_fences
].out_fence_ptr
= fence_ptr
;
1273 wb_conn
= drm_connector_to_writeback(conn
);
1274 fence
= drm_writeback_get_out_fence(wb_conn
);
1278 ret
= setup_out_fence(&f
[(*num_fences
)++], fence
);
1280 dma_fence_put(fence
);
1284 conn_state
->writeback_job
->out_fence
= fence
;
1288 * Having this flag means user mode pends on event which will never
1289 * reach due to lack of at least one CRTC for signaling
1291 if (c
== 0 && (arg
->flags
& DRM_MODE_PAGE_FLIP_EVENT
)) {
1292 drm_dbg_atomic(dev
, "need at least one CRTC for DRM_MODE_PAGE_FLIP_EVENT");
1299 static void complete_signaling(struct drm_device
*dev
,
1300 struct drm_atomic_state
*state
,
1301 struct drm_out_fence_state
*fence_state
,
1302 unsigned int num_fences
,
1305 struct drm_crtc
*crtc
;
1306 struct drm_crtc_state
*crtc_state
;
1310 for (i
= 0; i
< num_fences
; i
++)
1311 fd_install(fence_state
[i
].fd
,
1312 fence_state
[i
].sync_file
->file
);
1318 for_each_new_crtc_in_state(state
, crtc
, crtc_state
, i
) {
1319 struct drm_pending_vblank_event
*event
= crtc_state
->event
;
1321 * Free the allocated event. drm_atomic_helper_setup_commit
1322 * can allocate an event too, so only free it if it's ours
1323 * to prevent a double free in drm_atomic_state_clear.
1325 if (event
&& (event
->base
.fence
|| event
->base
.file_priv
)) {
1326 drm_event_cancel_free(dev
, &event
->base
);
1327 crtc_state
->event
= NULL
;
1334 for (i
= 0; i
< num_fences
; i
++) {
1335 if (fence_state
[i
].sync_file
)
1336 fput(fence_state
[i
].sync_file
->file
);
1337 if (fence_state
[i
].fd
>= 0)
1338 put_unused_fd(fence_state
[i
].fd
);
1340 /* If this fails log error to the user */
1341 if (fence_state
[i
].out_fence_ptr
&&
1342 put_user(-1, fence_state
[i
].out_fence_ptr
))
1343 drm_dbg_atomic(dev
, "Couldn't clear out_fence_ptr\n");
1350 set_async_flip(struct drm_atomic_state
*state
)
1352 struct drm_crtc
*crtc
;
1353 struct drm_crtc_state
*crtc_state
;
1356 for_each_new_crtc_in_state(state
, crtc
, crtc_state
, i
) {
1357 crtc_state
->async_flip
= true;
1361 int drm_mode_atomic_ioctl(struct drm_device
*dev
,
1362 void *data
, struct drm_file
*file_priv
)
1364 struct drm_mode_atomic
*arg
= data
;
1365 uint32_t __user
*objs_ptr
= (uint32_t __user
*)(unsigned long)(arg
->objs_ptr
);
1366 uint32_t __user
*count_props_ptr
= (uint32_t __user
*)(unsigned long)(arg
->count_props_ptr
);
1367 uint32_t __user
*props_ptr
= (uint32_t __user
*)(unsigned long)(arg
->props_ptr
);
1368 uint64_t __user
*prop_values_ptr
= (uint64_t __user
*)(unsigned long)(arg
->prop_values_ptr
);
1369 unsigned int copied_objs
, copied_props
;
1370 struct drm_atomic_state
*state
;
1371 struct drm_modeset_acquire_ctx ctx
;
1372 struct drm_out_fence_state
*fence_state
;
1374 unsigned int i
, j
, num_fences
;
1375 bool async_flip
= false;
1377 /* disallow for drivers not supporting atomic: */
1378 if (!drm_core_check_feature(dev
, DRIVER_ATOMIC
))
1381 /* disallow for userspace that has not enabled atomic cap (even
1382 * though this may be a bit overkill, since legacy userspace
1383 * wouldn't know how to call this ioctl)
1385 if (!file_priv
->atomic
) {
1387 "commit failed: atomic cap not enabled\n");
1391 if (arg
->flags
& ~DRM_MODE_ATOMIC_FLAGS
) {
1392 drm_dbg_atomic(dev
, "commit failed: invalid flag\n");
1396 if (arg
->reserved
) {
1397 drm_dbg_atomic(dev
, "commit failed: reserved field set\n");
1401 if (arg
->flags
& DRM_MODE_PAGE_FLIP_ASYNC
) {
1402 if (!dev
->mode_config
.async_page_flip
) {
1404 "commit failed: DRM_MODE_PAGE_FLIP_ASYNC not supported\n");
1411 /* can't test and expect an event at the same time. */
1412 if ((arg
->flags
& DRM_MODE_ATOMIC_TEST_ONLY
) &&
1413 (arg
->flags
& DRM_MODE_PAGE_FLIP_EVENT
)) {
1415 "commit failed: page-flip event requested with test-only commit\n");
1419 state
= drm_atomic_state_alloc(dev
);
1423 drm_modeset_acquire_init(&ctx
, DRM_MODESET_ACQUIRE_INTERRUPTIBLE
);
1424 state
->acquire_ctx
= &ctx
;
1425 state
->allow_modeset
= !!(arg
->flags
& DRM_MODE_ATOMIC_ALLOW_MODESET
);
1433 for (i
= 0; i
< arg
->count_objs
; i
++) {
1434 uint32_t obj_id
, count_props
;
1435 struct drm_mode_object
*obj
;
1437 if (get_user(obj_id
, objs_ptr
+ copied_objs
)) {
1442 obj
= drm_mode_object_find(dev
, file_priv
, obj_id
, DRM_MODE_OBJECT_ANY
);
1444 drm_dbg_atomic(dev
, "cannot find object ID %d", obj_id
);
1449 if (!obj
->properties
) {
1450 drm_dbg_atomic(dev
, "[OBJECT:%d] has no properties", obj_id
);
1451 drm_mode_object_put(obj
);
1456 if (get_user(count_props
, count_props_ptr
+ copied_objs
)) {
1457 drm_mode_object_put(obj
);
1464 for (j
= 0; j
< count_props
; j
++) {
1466 uint64_t prop_value
;
1467 struct drm_property
*prop
;
1469 if (get_user(prop_id
, props_ptr
+ copied_props
)) {
1470 drm_mode_object_put(obj
);
1475 prop
= drm_mode_obj_find_prop_id(obj
, prop_id
);
1478 "[OBJECT:%d] cannot find property ID %d",
1480 drm_mode_object_put(obj
);
1485 if (copy_from_user(&prop_value
,
1486 prop_values_ptr
+ copied_props
,
1487 sizeof(prop_value
))) {
1488 drm_mode_object_put(obj
);
1493 ret
= drm_atomic_set_property(state
, file_priv
, obj
,
1494 prop
, prop_value
, async_flip
);
1496 drm_mode_object_put(obj
);
1503 drm_mode_object_put(obj
);
1506 ret
= prepare_signaling(dev
, state
, arg
, file_priv
, &fence_state
,
1511 if (arg
->flags
& DRM_MODE_PAGE_FLIP_ASYNC
)
1512 set_async_flip(state
);
1514 if (arg
->flags
& DRM_MODE_ATOMIC_TEST_ONLY
) {
1515 ret
= drm_atomic_check_only(state
);
1516 } else if (arg
->flags
& DRM_MODE_ATOMIC_NONBLOCK
) {
1517 ret
= drm_atomic_nonblocking_commit(state
);
1519 ret
= drm_atomic_commit(state
);
1523 complete_signaling(dev
, state
, fence_state
, num_fences
, !ret
);
1525 if (ret
== -EDEADLK
) {
1526 drm_atomic_state_clear(state
);
1527 ret
= drm_modeset_backoff(&ctx
);
1532 drm_atomic_state_put(state
);
1534 drm_modeset_drop_locks(&ctx
);
1535 drm_modeset_acquire_fini(&ctx
);