aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-01-08 18:22:40 -0500
committerDave Airlie <airlied@redhat.com>2015-01-08 18:22:40 -0500
commitc93546a5e32bd788c22aefa072385f3784551c13 (patch)
tree558c75a3424be58551822d1cfe6b284c3173cada
parente5202a2289d746a94703ad937157d398fb2607cf (diff)
parent179f158ccf15fb9425f53d589d1b48eab90449a6 (diff)
Merge tag 'topic/atomic-core-2015-01-05' of git://anongit.freedesktop.org/drm-intel into drm-next
Next batch of atomic work. Most important is the propertification from Rob and the nth iteration of the actual atomic ioctl originally from Ville. Big differences compared to earlier revisions: - Core properties are now fully handled by the core, drivers can only handle driver-specific properties. - Atomic props&ioctl are opt-in per file_priv, userspace needs to explicitly ask for it (like universal plane support). - For now all hidden behind the atomic module option until this has settled a bit. - Atomic modesets are currently not possible since the exact abi for how to handle the mode property is still under discussion. Besides this some cleanup patches from me and the addition of per-object state to global state backpointers to simplify drivers. * tag 'topic/atomic-core-2015-01-05' of git://anongit.freedesktop.org/drm-intel: drm: Ensure universal_planes is set for atomic drm/atomic: Hide drm.ko internal interfaces drm: Atomic modeset ioctl drm/atomic: atomic connector properties drm/atomic: atomic plane properties drm: small property creation cleanup drm/atomic: atomic_check functions drm: add atomic properties drm: refactor getproperties/getconnector drm: tweak getconnector locking drm: add atomic_get_property drm: add atomic_set_property wrappers drm: get rid of direct property value access drm: store property instead of id in obj attachment drm: allow property validation for refcnted props drm/atomic: Introduce state->obj backpointers drm/atomic-helper: Again check modeset *before* plane states drm/atomic-helper: Export both plane and modeset check helpers
-rw-r--r--Documentation/DocBook/drm.tmpl91
-rw-r--r--drivers/gpu/drm/drm_atomic.c730
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c106
-rw-r--r--drivers/gpu/drm/drm_crtc.c345
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c2
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h6
-rw-r--r--drivers/gpu/drm/drm_drv.c4
-rw-r--r--drivers/gpu/drm/drm_ioctl.c13
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c1
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c20
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c2
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h2
-rw-r--r--include/drm/drmP.h4
-rw-r--r--include/drm/drm_atomic.h13
-rw-r--r--include/drm/drm_atomic_helper.h4
-rw-r--r--include/drm/drm_crtc.h70
-rw-r--r--include/uapi/drm/drm.h8
-rw-r--r--include/uapi/drm/drm_mode.h30
19 files changed, 1294 insertions, 159 deletions
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 8a0b2a84f4bf..640c2a30563f 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -239,6 +239,14 @@
239 Driver supports dedicated render nodes. 239 Driver supports dedicated render nodes.
240 </para></listitem> 240 </para></listitem>
241 </varlistentry> 241 </varlistentry>
242 <varlistentry>
243 <term>DRIVER_ATOMIC</term>
244 <listitem><para>
245 Driver supports atomic properties. In this case the driver
246 must implement appropriate obj->atomic_get_property() vfuncs
247 for any modeset objects with driver specific properties.
248 </para></listitem>
249 </varlistentry>
242 </variablelist> 250 </variablelist>
243 </sect3> 251 </sect3>
244 <sect3> 252 <sect3>
@@ -2565,8 +2573,8 @@ void intel_crt_init(struct drm_device *dev)
2565 <td valign="top" >Description/Restrictions</td> 2573 <td valign="top" >Description/Restrictions</td>
2566 </tr> 2574 </tr>
2567 <tr> 2575 <tr>
2568 <td rowspan="25" valign="top" >DRM</td> 2576 <td rowspan="36" valign="top" >DRM</td>
2569 <td rowspan="4" valign="top" >Generic</td> 2577 <td rowspan="5" valign="top" >Connector</td>
2570 <td valign="top" >“EDID”</td> 2578 <td valign="top" >“EDID”</td>
2571 <td valign="top" >BLOB | IMMUTABLE</td> 2579 <td valign="top" >BLOB | IMMUTABLE</td>
2572 <td valign="top" >0</td> 2580 <td valign="top" >0</td>
@@ -2595,7 +2603,14 @@ void intel_crt_init(struct drm_device *dev)
2595 <td valign="top" >Contains tiling information for a connector.</td> 2603 <td valign="top" >Contains tiling information for a connector.</td>
2596 </tr> 2604 </tr>
2597 <tr> 2605 <tr>
2598 <td rowspan="1" valign="top" >Plane</td> 2606 <td valign="top" >“CRTC_ID”</td>
2607 <td valign="top" >OBJECT</td>
2608 <td valign="top" >DRM_MODE_OBJECT_CRTC</td>
2609 <td valign="top" >Connector</td>
2610 <td valign="top" >CRTC that connector is attached to (atomic)</td>
2611 </tr>
2612 <tr>
2613 <td rowspan="11" valign="top" >Plane</td>
2599 <td valign="top" >“type”</td> 2614 <td valign="top" >“type”</td>
2600 <td valign="top" >ENUM | IMMUTABLE</td> 2615 <td valign="top" >ENUM | IMMUTABLE</td>
2601 <td valign="top" >{ "Overlay", "Primary", "Cursor" }</td> 2616 <td valign="top" >{ "Overlay", "Primary", "Cursor" }</td>
@@ -2603,6 +2618,76 @@ void intel_crt_init(struct drm_device *dev)
2603 <td valign="top" >Plane type</td> 2618 <td valign="top" >Plane type</td>
2604 </tr> 2619 </tr>
2605 <tr> 2620 <tr>
2621 <td valign="top" >“SRC_X”</td>
2622 <td valign="top" >RANGE</td>
2623 <td valign="top" >Min=0, Max=UINT_MAX</td>
2624 <td valign="top" >Plane</td>
2625 <td valign="top" >Scanout source x coordinate in 16.16 fixed point (atomic)</td>
2626 </tr>
2627 <tr>
2628 <td valign="top" >“SRC_Y”</td>
2629 <td valign="top" >RANGE</td>
2630 <td valign="top" >Min=0, Max=UINT_MAX</td>
2631 <td valign="top" >Plane</td>
2632 <td valign="top" >Scanout source y coordinate in 16.16 fixed point (atomic)</td>
2633 </tr>
2634 <tr>
2635 <td valign="top" >“SRC_W”</td>
2636 <td valign="top" >RANGE</td>
2637 <td valign="top" >Min=0, Max=UINT_MAX</td>
2638 <td valign="top" >Plane</td>
2639 <td valign="top" >Scanout source width in 16.16 fixed point (atomic)</td>
2640 </tr>
2641 <tr>
2642 <td valign="top" >“SRC_H”</td>
2643 <td valign="top" >RANGE</td>
2644 <td valign="top" >Min=0, Max=UINT_MAX</td>
2645 <td valign="top" >Plane</td>
2646 <td valign="top" >Scanout source height in 16.16 fixed point (atomic)</td>
2647 </tr>
2648 <tr>
2649 <td valign="top" >“CRTC_X”</td>
2650 <td valign="top" >SIGNED_RANGE</td>
2651 <td valign="top" >Min=INT_MIN, Max=INT_MAX</td>
2652 <td valign="top" >Plane</td>
2653 <td valign="top" >Scanout CRTC (destination) x coordinate (atomic)</td>
2654 </tr>
2655 <tr>
2656 <td valign="top" >“CRTC_Y”</td>
2657 <td valign="top" >SIGNED_RANGE</td>
2658 <td valign="top" >Min=INT_MIN, Max=INT_MAX</td>
2659 <td valign="top" >Plane</td>
2660 <td valign="top" >Scanout CRTC (destination) y coordinate (atomic)</td>
2661 </tr>
2662 <tr>
2663 <td valign="top" >“CRTC_W”</td>
2664 <td valign="top" >RANGE</td>
2665 <td valign="top" >Min=0, Max=UINT_MAX</td>
2666 <td valign="top" >Plane</td>
2667 <td valign="top" >Scanout CRTC (destination) width (atomic)</td>
2668 </tr>
2669 <tr>
2670 <td valign="top" >“CRTC_H”</td>
2671 <td valign="top" >RANGE</td>
2672 <td valign="top" >Min=0, Max=UINT_MAX</td>
2673 <td valign="top" >Plane</td>
2674 <td valign="top" >Scanout CRTC (destination) height (atomic)</td>
2675 </tr>
2676 <tr>
2677 <td valign="top" >“FB_ID”</td>
2678 <td valign="top" >OBJECT</td>
2679 <td valign="top" >DRM_MODE_OBJECT_FB</td>
2680 <td valign="top" >Plane</td>
2681 <td valign="top" >Scanout framebuffer (atomic)</td>
2682 </tr>
2683 <tr>
2684 <td valign="top" >“CRTC_ID”</td>
2685 <td valign="top" >OBJECT</td>
2686 <td valign="top" >DRM_MODE_OBJECT_CRTC</td>
2687 <td valign="top" >Plane</td>
2688 <td valign="top" >CRTC that plane is attached to (atomic)</td>
2689 </tr>
2690 <tr>
2606 <td rowspan="2" valign="top" >DVI-I</td> 2691 <td rowspan="2" valign="top" >DVI-I</td>
2607 <td valign="top" >“subconnector”</td> 2692 <td valign="top" >“subconnector”</td>
2608 <td valign="top" >ENUM</td> 2693 <td valign="top" >ENUM</td>
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index ff5f034cc405..1e38dfc8e462 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -56,6 +56,11 @@ drm_atomic_state_alloc(struct drm_device *dev)
56 if (!state) 56 if (!state)
57 return NULL; 57 return NULL;
58 58
59 /* TODO legacy paths should maybe do a better job about
60 * setting this appropriately?
61 */
62 state->allow_modeset = true;
63
59 state->num_connector = ACCESS_ONCE(dev->mode_config.num_connector); 64 state->num_connector = ACCESS_ONCE(dev->mode_config.num_connector);
60 65
61 state->crtcs = kcalloc(dev->mode_config.num_crtc, 66 state->crtcs = kcalloc(dev->mode_config.num_crtc,
@@ -217,6 +222,70 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
217EXPORT_SYMBOL(drm_atomic_get_crtc_state); 222EXPORT_SYMBOL(drm_atomic_get_crtc_state);
218 223
219/** 224/**
225 * drm_atomic_crtc_set_property - set property on CRTC
226 * @crtc: the drm CRTC to set a property on
227 * @state: the state object to update with the new property value
228 * @property: the property to set
229 * @val: the new property value
230 *
231 * Use this instead of calling crtc->atomic_set_property directly.
232 * This function handles generic/core properties and calls out to
233 * driver's ->atomic_set_property() for driver properties. To ensure
234 * consistent behavior you must call this function rather than the
235 * driver hook directly.
236 *
237 * RETURNS:
238 * Zero on success, error code on failure
239 */
240int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
241 struct drm_crtc_state *state, struct drm_property *property,
242 uint64_t val)
243{
244 if (crtc->funcs->atomic_set_property)
245 return crtc->funcs->atomic_set_property(crtc, state, property, val);
246 return -EINVAL;
247}
248EXPORT_SYMBOL(drm_atomic_crtc_set_property);
249
250/*
251 * This function handles generic/core properties and calls out to
252 * driver's ->atomic_get_property() for driver properties. To ensure
253 * consistent behavior you must call this function rather than the
254 * driver hook directly.
255 */
256int drm_atomic_crtc_get_property(struct drm_crtc *crtc,
257 const struct drm_crtc_state *state,
258 struct drm_property *property, uint64_t *val)
259{
260 if (crtc->funcs->atomic_get_property)
261 return crtc->funcs->atomic_get_property(crtc, state, property, val);
262 return -EINVAL;
263}
264
265/**
266 * drm_atomic_crtc_check - check crtc state
267 * @crtc: crtc to check
268 * @state: crtc state to check
269 *
270 * Provides core sanity checks for crtc state.
271 *
272 * RETURNS:
273 * Zero on success, error code on failure
274 */
275static int drm_atomic_crtc_check(struct drm_crtc *crtc,
276 struct drm_crtc_state *state)
277{
278 /* NOTE: we explicitly don't enforce constraints such as primary
279 * layer covering entire screen, since that is something we want
280 * to allow (on hw that supports it). For hw that does not, it
281 * should be checked in driver's crtc->atomic_check() vfunc.
282 *
283 * TODO: Add generic modeset state checks once we support those.
284 */
285 return 0;
286}
287
288/**
220 * drm_atomic_get_plane_state - get plane state 289 * drm_atomic_get_plane_state - get plane state
221 * @state: global atomic state object 290 * @state: global atomic state object
222 * @plane: plane to get state object for 291 * @plane: plane to get state object for
@@ -272,6 +341,183 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
272EXPORT_SYMBOL(drm_atomic_get_plane_state); 341EXPORT_SYMBOL(drm_atomic_get_plane_state);
273 342
274/** 343/**
344 * drm_atomic_plane_set_property - set property on plane
345 * @plane: the drm plane to set a property on
346 * @state: the state object to update with the new property value
347 * @property: the property to set
348 * @val: the new property value
349 *
350 * Use this instead of calling plane->atomic_set_property directly.
351 * This function handles generic/core properties and calls out to
352 * driver's ->atomic_set_property() for driver properties. To ensure
353 * consistent behavior you must call this function rather than the
354 * driver hook directly.
355 *
356 * RETURNS:
357 * Zero on success, error code on failure
358 */
359int drm_atomic_plane_set_property(struct drm_plane *plane,
360 struct drm_plane_state *state, struct drm_property *property,
361 uint64_t val)
362{
363 struct drm_device *dev = plane->dev;
364 struct drm_mode_config *config = &dev->mode_config;
365
366 if (property == config->prop_fb_id) {
367 struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, val);
368 drm_atomic_set_fb_for_plane(state, fb);
369 if (fb)
370 drm_framebuffer_unreference(fb);
371 } else if (property == config->prop_crtc_id) {
372 struct drm_crtc *crtc = drm_crtc_find(dev, val);
373 return drm_atomic_set_crtc_for_plane(state, crtc);
374 } else if (property == config->prop_crtc_x) {
375 state->crtc_x = U642I64(val);
376 } else if (property == config->prop_crtc_y) {
377 state->crtc_y = U642I64(val);
378 } else if (property == config->prop_crtc_w) {
379 state->crtc_w = val;
380 } else if (property == config->prop_crtc_h) {
381 state->crtc_h = val;
382 } else if (property == config->prop_src_x) {
383 state->src_x = val;
384 } else if (property == config->prop_src_y) {
385 state->src_y = val;
386 } else if (property == config->prop_src_w) {
387 state->src_w = val;
388 } else if (property == config->prop_src_h) {
389 state->src_h = val;
390 } else if (plane->funcs->atomic_set_property) {
391 return plane->funcs->atomic_set_property(plane, state,
392 property, val);
393 } else {
394 return -EINVAL;
395 }
396
397 return 0;
398}
399EXPORT_SYMBOL(drm_atomic_plane_set_property);
400
401/*
402 * This function handles generic/core properties and calls out to
403 * driver's ->atomic_get_property() for driver properties. To ensure
404 * consistent behavior you must call this function rather than the
405 * driver hook directly.
406 */
407static int
408drm_atomic_plane_get_property(struct drm_plane *plane,
409 const struct drm_plane_state *state,
410 struct drm_property *property, uint64_t *val)
411{
412 struct drm_device *dev = plane->dev;
413 struct drm_mode_config *config = &dev->mode_config;
414
415 if (property == config->prop_fb_id) {
416 *val = (state->fb) ? state->fb->base.id : 0;
417 } else if (property == config->prop_crtc_id) {
418 *val = (state->crtc) ? state->crtc->base.id : 0;
419 } else if (property == config->prop_crtc_x) {
420 *val = I642U64(state->crtc_x);
421 } else if (property == config->prop_crtc_y) {
422 *val = I642U64(state->crtc_y);
423 } else if (property == config->prop_crtc_w) {
424 *val = state->crtc_w;
425 } else if (property == config->prop_crtc_h) {
426 *val = state->crtc_h;
427 } else if (property == config->prop_src_x) {
428 *val = state->src_x;
429 } else if (property == config->prop_src_y) {
430 *val = state->src_y;
431 } else if (property == config->prop_src_w) {
432 *val = state->src_w;
433 } else if (property == config->prop_src_h) {
434 *val = state->src_h;
435 } else if (plane->funcs->atomic_get_property) {
436 return plane->funcs->atomic_get_property(plane, state, property, val);
437 } else {
438 return -EINVAL;
439 }
440
441 return 0;
442}
443
444/**
445 * drm_atomic_plane_check - check plane state
446 * @plane: plane to check
447 * @state: plane state to check
448 *
449 * Provides core sanity checks for plane state.
450 *
451 * RETURNS:
452 * Zero on success, error code on failure
453 */
454static int drm_atomic_plane_check(struct drm_plane *plane,
455 struct drm_plane_state *state)
456{
457 unsigned int fb_width, fb_height;
458 unsigned int i;
459
460 /* either *both* CRTC and FB must be set, or neither */
461 if (WARN_ON(state->crtc && !state->fb)) {
462 DRM_DEBUG_KMS("CRTC set but no FB\n");
463 return -EINVAL;
464 } else if (WARN_ON(state->fb && !state->crtc)) {
465 DRM_DEBUG_KMS("FB set but no CRTC\n");
466 return -EINVAL;
467 }
468
469 /* if disabled, we don't care about the rest of the state: */
470 if (!state->crtc)
471 return 0;
472
473 /* Check whether this plane is usable on this CRTC */
474 if (!(plane->possible_crtcs & drm_crtc_mask(state->crtc))) {
475 DRM_DEBUG_KMS("Invalid crtc for plane\n");
476 return -EINVAL;
477 }
478
479 /* Check whether this plane supports the fb pixel format. */
480 for (i = 0; i < plane->format_count; i++)
481 if (state->fb->pixel_format == plane->format_types[i])
482 break;
483 if (i == plane->format_count) {
484 DRM_DEBUG_KMS("Invalid pixel format %s\n",
485 drm_get_format_name(state->fb->pixel_format));
486 return -EINVAL;
487 }
488
489 /* Give drivers some help against integer overflows */
490 if (state->crtc_w > INT_MAX ||
491 state->crtc_x > INT_MAX - (int32_t) state->crtc_w ||
492 state->crtc_h > INT_MAX ||
493 state->crtc_y > INT_MAX - (int32_t) state->crtc_h) {
494 DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
495 state->crtc_w, state->crtc_h,
496 state->crtc_x, state->crtc_y);
497 return -ERANGE;
498 }
499
500 fb_width = state->fb->width << 16;
501 fb_height = state->fb->height << 16;
502
503 /* Make sure source coordinates are inside the fb. */
504 if (state->src_w > fb_width ||
505 state->src_x > fb_width - state->src_w ||
506 state->src_h > fb_height ||
507 state->src_y > fb_height - state->src_h) {
508 DRM_DEBUG_KMS("Invalid source coordinates "
509 "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
510 state->src_w >> 16, ((state->src_w & 0xffff) * 15625) >> 10,
511 state->src_h >> 16, ((state->src_h & 0xffff) * 15625) >> 10,
512 state->src_x >> 16, ((state->src_x & 0xffff) * 15625) >> 10,
513 state->src_y >> 16, ((state->src_y & 0xffff) * 15625) >> 10);
514 return -ENOSPC;
515 }
516
517 return 0;
518}
519
520/**
275 * drm_atomic_get_connector_state - get connector state 521 * drm_atomic_get_connector_state - get connector state
276 * @state: global atomic state object 522 * @state: global atomic state object
277 * @connector: connector to get state object for 523 * @connector: connector to get state object for
@@ -343,9 +589,113 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,
343EXPORT_SYMBOL(drm_atomic_get_connector_state); 589EXPORT_SYMBOL(drm_atomic_get_connector_state);
344 590
345/** 591/**
592 * drm_atomic_connector_set_property - set property on connector.
593 * @connector: the drm connector to set a property on
594 * @state: the state object to update with the new property value
595 * @property: the property to set
596 * @val: the new property value
597 *
598 * Use this instead of calling connector->atomic_set_property directly.
599 * This function handles generic/core properties and calls out to
600 * driver's ->atomic_set_property() for driver properties. To ensure
601 * consistent behavior you must call this function rather than the
602 * driver hook directly.
603 *
604 * RETURNS:
605 * Zero on success, error code on failure
606 */
607int drm_atomic_connector_set_property(struct drm_connector *connector,
608 struct drm_connector_state *state, struct drm_property *property,
609 uint64_t val)
610{
611 struct drm_device *dev = connector->dev;
612 struct drm_mode_config *config = &dev->mode_config;
613
614 if (property == config->prop_crtc_id) {
615 struct drm_crtc *crtc = drm_crtc_find(dev, val);
616 return drm_atomic_set_crtc_for_connector(state, crtc);
617 } else if (property == config->dpms_property) {
618 /* setting DPMS property requires special handling, which
619 * is done in legacy setprop path for us. Disallow (for
620 * now?) atomic writes to DPMS property:
621 */
622 return -EINVAL;
623 } else if (connector->funcs->atomic_set_property) {
624 return connector->funcs->atomic_set_property(connector,
625 state, property, val);
626 } else {
627 return -EINVAL;
628 }
629}
630EXPORT_SYMBOL(drm_atomic_connector_set_property);
631
632/*
633 * This function handles generic/core properties and calls out to
634 * driver's ->atomic_get_property() for driver properties. To ensure
635 * consistent behavior you must call this function rather than the
636 * driver hook directly.
637 */
638static int
639drm_atomic_connector_get_property(struct drm_connector *connector,
640 const struct drm_connector_state *state,
641 struct drm_property *property, uint64_t *val)
642{
643 struct drm_device *dev = connector->dev;
644 struct drm_mode_config *config = &dev->mode_config;
645
646 if (property == config->prop_crtc_id) {
647 *val = (state->crtc) ? state->crtc->base.id : 0;
648 } else if (property == config->dpms_property) {
649 *val = connector->dpms;
650 } else if (connector->funcs->atomic_get_property) {
651 return connector->funcs->atomic_get_property(connector,
652 state, property, val);
653 } else {
654 return -EINVAL;
655 }
656
657 return 0;
658}
659
660int drm_atomic_get_property(struct drm_mode_object *obj,
661 struct drm_property *property, uint64_t *val)
662{
663 struct drm_device *dev = property->dev;
664 int ret;
665
666 switch (obj->type) {
667 case DRM_MODE_OBJECT_CONNECTOR: {
668 struct drm_connector *connector = obj_to_connector(obj);
669 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
670 ret = drm_atomic_connector_get_property(connector,
671 connector->state, property, val);
672 break;
673 }
674 case DRM_MODE_OBJECT_CRTC: {
675 struct drm_crtc *crtc = obj_to_crtc(obj);
676 WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
677 ret = drm_atomic_crtc_get_property(crtc,
678 crtc->state, property, val);
679 break;
680 }
681 case DRM_MODE_OBJECT_PLANE: {
682 struct drm_plane *plane = obj_to_plane(obj);
683 WARN_ON(!drm_modeset_is_locked(&plane->mutex));
684 ret = drm_atomic_plane_get_property(plane,
685 plane->state, property, val);
686 break;
687 }
688 default:
689 ret = -EINVAL;
690 break;
691 }
692
693 return ret;
694}
695
696/**
346 * drm_atomic_set_crtc_for_plane - set crtc for plane 697 * drm_atomic_set_crtc_for_plane - set crtc for plane
347 * @state: the incoming atomic state 698 * @plane_state: the plane whose incoming state to update
348 * @plane: the plane whose incoming state to update
349 * @crtc: crtc to use for the plane 699 * @crtc: crtc to use for the plane
350 * 700 *
351 * Changing the assigned crtc for a plane requires us to grab the lock and state 701 * Changing the assigned crtc for a plane requires us to grab the lock and state
@@ -358,16 +708,12 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state);
358 * sequence must be restarted. All other errors are fatal. 708 * sequence must be restarted. All other errors are fatal.
359 */ 709 */
360int 710int
361drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state, 711drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
362 struct drm_plane *plane, struct drm_crtc *crtc) 712 struct drm_crtc *crtc)
363{ 713{
364 struct drm_plane_state *plane_state = 714 struct drm_plane *plane = plane_state->plane;
365 drm_atomic_get_plane_state(state, plane);
366 struct drm_crtc_state *crtc_state; 715 struct drm_crtc_state *crtc_state;
367 716
368 if (WARN_ON(IS_ERR(plane_state)))
369 return PTR_ERR(plane_state);
370
371 if (plane_state->crtc) { 717 if (plane_state->crtc) {
372 crtc_state = drm_atomic_get_crtc_state(plane_state->state, 718 crtc_state = drm_atomic_get_crtc_state(plane_state->state,
373 plane_state->crtc); 719 plane_state->crtc);
@@ -583,14 +929,62 @@ EXPORT_SYMBOL(drm_atomic_legacy_backoff);
583 */ 929 */
584int drm_atomic_check_only(struct drm_atomic_state *state) 930int drm_atomic_check_only(struct drm_atomic_state *state)
585{ 931{
586 struct drm_mode_config *config = &state->dev->mode_config; 932 struct drm_device *dev = state->dev;
933 struct drm_mode_config *config = &dev->mode_config;
934 int nplanes = config->num_total_plane;
935 int ncrtcs = config->num_crtc;
936 int i, ret = 0;
587 937
588 DRM_DEBUG_KMS("checking %p\n", state); 938 DRM_DEBUG_KMS("checking %p\n", state);
589 939
940 for (i = 0; i < nplanes; i++) {
941 struct drm_plane *plane = state->planes[i];
942
943 if (!plane)
944 continue;
945
946 ret = drm_atomic_plane_check(plane, state->plane_states[i]);
947 if (ret) {
948 DRM_DEBUG_KMS("[PLANE:%d] atomic core check failed\n",
949 plane->base.id);
950 return ret;
951 }
952 }
953
954 for (i = 0; i < ncrtcs; i++) {
955 struct drm_crtc *crtc = state->crtcs[i];
956
957 if (!crtc)
958 continue;
959
960 ret = drm_atomic_crtc_check(crtc, state->crtc_states[i]);
961 if (ret) {
962 DRM_DEBUG_KMS("[CRTC:%d] atomic core check failed\n",
963 crtc->base.id);
964 return ret;
965 }
966 }
967
590 if (config->funcs->atomic_check) 968 if (config->funcs->atomic_check)
591 return config->funcs->atomic_check(state->dev, state); 969 ret = config->funcs->atomic_check(state->dev, state);
592 else 970
593 return 0; 971 if (!state->allow_modeset) {
972 for (i = 0; i < ncrtcs; i++) {
973 struct drm_crtc *crtc = state->crtcs[i];
974 struct drm_crtc_state *crtc_state = state->crtc_states[i];
975
976 if (!crtc)
977 continue;
978
979 if (crtc_state->mode_changed) {
980 DRM_DEBUG_KMS("[CRTC:%d] requires full modeset\n",
981 crtc->base.id);
982 return -EINVAL;
983 }
984 }
985 }
986
987 return ret;
594} 988}
595EXPORT_SYMBOL(drm_atomic_check_only); 989EXPORT_SYMBOL(drm_atomic_check_only);
596 990
@@ -655,3 +1049,313 @@ int drm_atomic_async_commit(struct drm_atomic_state *state)
655 return config->funcs->atomic_commit(state->dev, state, true); 1049 return config->funcs->atomic_commit(state->dev, state, true);
656} 1050}
657EXPORT_SYMBOL(drm_atomic_async_commit); 1051EXPORT_SYMBOL(drm_atomic_async_commit);
1052
1053/*
1054 * The big monstor ioctl
1055 */
1056
1057static struct drm_pending_vblank_event *create_vblank_event(
1058 struct drm_device *dev, struct drm_file *file_priv, uint64_t user_data)
1059{
1060 struct drm_pending_vblank_event *e = NULL;
1061 unsigned long flags;
1062
1063 spin_lock_irqsave(&dev->event_lock, flags);
1064 if (file_priv->event_space < sizeof e->event) {
1065 spin_unlock_irqrestore(&dev->event_lock, flags);
1066 goto out;
1067 }
1068 file_priv->event_space -= sizeof e->event;
1069 spin_unlock_irqrestore(&dev->event_lock, flags);
1070
1071 e = kzalloc(sizeof *e, GFP_KERNEL);
1072 if (e == NULL) {
1073 spin_lock_irqsave(&dev->event_lock, flags);
1074 file_priv->event_space += sizeof e->event;
1075 spin_unlock_irqrestore(&dev->event_lock, flags);
1076 goto out;
1077 }
1078
1079 e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
1080 e->event.base.length = sizeof e->event;
1081 e->event.user_data = user_data;
1082 e->base.event = &e->event.base;
1083 e->base.file_priv = file_priv;
1084 e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
1085
1086out:
1087 return e;
1088}
1089
1090static void destroy_vblank_event(struct drm_device *dev,
1091 struct drm_file *file_priv, struct drm_pending_vblank_event *e)
1092{
1093 unsigned long flags;
1094
1095 spin_lock_irqsave(&dev->event_lock, flags);
1096 file_priv->event_space += sizeof e->event;
1097 spin_unlock_irqrestore(&dev->event_lock, flags);
1098 kfree(e);
1099}
1100
1101static int atomic_set_prop(struct drm_atomic_state *state,
1102 struct drm_mode_object *obj, struct drm_property *prop,
1103 uint64_t prop_value)
1104{
1105 struct drm_mode_object *ref;
1106 int ret;
1107
1108 if (!drm_property_change_valid_get(prop, prop_value, &ref))
1109 return -EINVAL;
1110
1111 switch (obj->type) {
1112 case DRM_MODE_OBJECT_CONNECTOR: {
1113 struct drm_connector *connector = obj_to_connector(obj);
1114 struct drm_connector_state *connector_state;
1115
1116 connector_state = drm_atomic_get_connector_state(state, connector);
1117 if (IS_ERR(connector_state)) {
1118 ret = PTR_ERR(connector_state);
1119 break;
1120 }
1121
1122 ret = drm_atomic_connector_set_property(connector,
1123 connector_state, prop, prop_value);
1124 break;
1125 }
1126 case DRM_MODE_OBJECT_CRTC: {
1127 struct drm_crtc *crtc = obj_to_crtc(obj);
1128 struct drm_crtc_state *crtc_state;
1129
1130 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1131 if (IS_ERR(crtc_state)) {
1132 ret = PTR_ERR(crtc_state);
1133 break;
1134 }
1135
1136 ret = drm_atomic_crtc_set_property(crtc,
1137 crtc_state, prop, prop_value);
1138 break;
1139 }
1140 case DRM_MODE_OBJECT_PLANE: {
1141 struct drm_plane *plane = obj_to_plane(obj);
1142 struct drm_plane_state *plane_state;
1143
1144 plane_state = drm_atomic_get_plane_state(state, plane);
1145 if (IS_ERR(plane_state)) {
1146 ret = PTR_ERR(plane_state);
1147 break;
1148 }
1149
1150 ret = drm_atomic_plane_set_property(plane,
1151 plane_state, prop, prop_value);
1152 break;
1153 }
1154 default:
1155 ret = -EINVAL;
1156 break;
1157 }
1158
1159 drm_property_change_valid_put(prop, ref);
1160 return ret;
1161}
1162
1163int drm_mode_atomic_ioctl(struct drm_device *dev,
1164 void *data, struct drm_file *file_priv)
1165{
1166 struct drm_mode_atomic *arg = data;
1167 uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
1168 uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
1169 uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
1170 uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
1171 unsigned int copied_objs, copied_props;
1172 struct drm_atomic_state *state;
1173 struct drm_modeset_acquire_ctx ctx;
1174 struct drm_plane *plane;
1175 unsigned plane_mask = 0;
1176 int ret = 0;
1177 unsigned int i, j;
1178
1179 /* disallow for drivers not supporting atomic: */
1180 if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
1181 return -EINVAL;
1182
1183 /* disallow for userspace that has not enabled atomic cap (even
1184 * though this may be a bit overkill, since legacy userspace
1185 * wouldn't know how to call this ioctl)
1186 */
1187 if (!file_priv->atomic)
1188 return -EINVAL;
1189
1190 if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS)
1191 return -EINVAL;
1192
1193 if (arg->reserved)
1194 return -EINVAL;
1195
1196 if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) &&
1197 !dev->mode_config.async_page_flip)
1198 return -EINVAL;
1199
1200 /* can't test and expect an event at the same time. */
1201 if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
1202 (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
1203 return -EINVAL;
1204
1205 drm_modeset_acquire_init(&ctx, 0);
1206
1207 state = drm_atomic_state_alloc(dev);
1208 if (!state)
1209 return -ENOMEM;
1210
1211 state->acquire_ctx = &ctx;
1212 state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
1213
1214retry:
1215 copied_objs = 0;
1216 copied_props = 0;
1217
1218 for (i = 0; i < arg->count_objs; i++) {
1219 uint32_t obj_id, count_props;
1220 struct drm_mode_object *obj;
1221
1222 if (get_user(obj_id, objs_ptr + copied_objs)) {
1223 ret = -EFAULT;
1224 goto fail;
1225 }
1226
1227 obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY);
1228 if (!obj || !obj->properties) {
1229 ret = -ENOENT;
1230 goto fail;
1231 }
1232
1233 if (obj->type == DRM_MODE_OBJECT_PLANE) {
1234 plane = obj_to_plane(obj);
1235 plane_mask |= (1 << drm_plane_index(plane));
1236 plane->old_fb = plane->fb;
1237 }
1238
1239 if (get_user(count_props, count_props_ptr + copied_objs)) {
1240 ret = -EFAULT;
1241 goto fail;
1242 }
1243
1244 copied_objs++;
1245
1246 for (j = 0; j < count_props; j++) {
1247 uint32_t prop_id;
1248 uint64_t prop_value;
1249 struct drm_property *prop;
1250
1251 if (get_user(prop_id, props_ptr + copied_props)) {
1252 ret = -EFAULT;
1253 goto fail;
1254 }
1255
1256 prop = drm_property_find(dev, prop_id);
1257 if (!prop) {
1258 ret = -ENOENT;
1259 goto fail;
1260 }
1261
1262 if (get_user(prop_value, prop_values_ptr + copied_props)) {
1263 ret = -EFAULT;
1264 goto fail;
1265 }
1266
1267 ret = atomic_set_prop(state, obj, prop, prop_value);
1268 if (ret)
1269 goto fail;
1270
1271 copied_props++;
1272 }
1273 }
1274
1275 if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
1276 int ncrtcs = dev->mode_config.num_crtc;
1277
1278 for (i = 0; i < ncrtcs; i++) {
1279 struct drm_crtc_state *crtc_state = state->crtc_states[i];
1280 struct drm_pending_vblank_event *e;
1281
1282 if (!crtc_state)
1283 continue;
1284
1285 e = create_vblank_event(dev, file_priv, arg->user_data);
1286 if (!e) {
1287 ret = -ENOMEM;
1288 goto fail;
1289 }
1290
1291 crtc_state->event = e;
1292 }
1293 }
1294
1295 if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
1296 ret = drm_atomic_check_only(state);
1297 /* _check_only() does not free state, unlike _commit() */
1298 drm_atomic_state_free(state);
1299 } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
1300 ret = drm_atomic_async_commit(state);
1301 } else {
1302 ret = drm_atomic_commit(state);
1303 }
1304
1305 /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
1306 * locks (ie. while it is still safe to deref plane->state). We
1307 * need to do this here because the driver entry points cannot
1308 * distinguish between legacy and atomic ioctls.
1309 */
1310 drm_for_each_plane_mask(plane, dev, plane_mask) {
1311 if (ret == 0) {
1312 struct drm_framebuffer *new_fb = plane->state->fb;
1313 if (new_fb)
1314 drm_framebuffer_reference(new_fb);
1315 plane->fb = new_fb;
1316 plane->crtc = plane->state->crtc;
1317 } else {
1318 plane->old_fb = NULL;
1319 }
1320 if (plane->old_fb) {
1321 drm_framebuffer_unreference(plane->old_fb);
1322 plane->old_fb = NULL;
1323 }
1324 }
1325
1326 drm_modeset_drop_locks(&ctx);
1327 drm_modeset_acquire_fini(&ctx);
1328
1329 return ret;
1330
1331fail:
1332 if (ret == -EDEADLK)
1333 goto backoff;
1334
1335 if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
1336 int ncrtcs = dev->mode_config.num_crtc;
1337
1338 for (i = 0; i < ncrtcs; i++) {
1339 struct drm_crtc_state *crtc_state = state->crtc_states[i];
1340
1341 if (!crtc_state)
1342 continue;
1343
1344 destroy_vblank_event(dev, file_priv, crtc_state->event);
1345 crtc_state->event = NULL;
1346 }
1347 }
1348
1349 drm_atomic_state_free(state);
1350
1351 drm_modeset_drop_locks(&ctx);
1352 drm_modeset_acquire_fini(&ctx);
1353
1354 return ret;
1355
1356backoff:
1357 drm_atomic_state_clear(state);
1358 drm_modeset_backoff(&ctx);
1359
1360 goto retry;
1361}
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index bbdbe4721573..541ba833ed36 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -330,7 +330,29 @@ mode_fixup(struct drm_atomic_state *state)
330 return 0; 330 return 0;
331} 331}
332 332
333static int 333/**
334 * drm_atomic_helper_check - validate state object for modeset changes
335 * @dev: DRM device
336 * @state: the driver state object
337 *
338 * Check the state object to see if the requested state is physically possible.
339 * This does all the crtc and connector related computations for an atomic
340 * update. It computes and updates crtc_state->mode_changed, adds any additional
341 * connectors needed for full modesets and calls down into ->mode_fixup
342 * functions of the driver backend.
343 *
344 * IMPORTANT:
345 *
346 * Drivers which update ->mode_changed (e.g. in their ->atomic_check hooks if a
347 * plane update can't be done without a full modeset) _must_ call this function
348 * afterwards after that change. It is permitted to call this function multiple
349 * times for the same update, e.g. when the ->atomic_check functions depend upon
350 * the adjusted dotclock for fifo space allocation and watermark computation.
351 *
352 * RETURNS
353 * Zero for success or -errno
354 */
355int
334drm_atomic_helper_check_modeset(struct drm_device *dev, 356drm_atomic_helper_check_modeset(struct drm_device *dev,
335 struct drm_atomic_state *state) 357 struct drm_atomic_state *state)
336{ 358{
@@ -406,23 +428,23 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
406 428
407 return mode_fixup(state); 429 return mode_fixup(state);
408} 430}
431EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
409 432
410/** 433/**
411 * drm_atomic_helper_check - validate state object 434 * drm_atomic_helper_check - validate state object for modeset changes
412 * @dev: DRM device 435 * @dev: DRM device
413 * @state: the driver state object 436 * @state: the driver state object
414 * 437 *
415 * Check the state object to see if the requested state is physically possible. 438 * Check the state object to see if the requested state is physically possible.
416 * Only crtcs and planes have check callbacks, so for any additional (global) 439 * This does all the plane update related checks using by calling into the
417 * checking that a driver needs it can simply wrap that around this function. 440 * ->atomic_check hooks provided by the driver.
418 * Drivers without such needs can directly use this as their ->atomic_check()
419 * callback.
420 * 441 *
421 * RETURNS 442 * RETURNS
422 * Zero for success or -errno 443 * Zero for success or -errno
423 */ 444 */
424int drm_atomic_helper_check(struct drm_device *dev, 445int
425 struct drm_atomic_state *state) 446drm_atomic_helper_check_planes(struct drm_device *dev,
447 struct drm_atomic_state *state)
426{ 448{
427 int nplanes = dev->mode_config.num_total_plane; 449 int nplanes = dev->mode_config.num_total_plane;
428 int ncrtcs = dev->mode_config.num_crtc; 450 int ncrtcs = dev->mode_config.num_crtc;
@@ -445,7 +467,7 @@ int drm_atomic_helper_check(struct drm_device *dev,
445 467
446 ret = funcs->atomic_check(plane, plane_state); 468 ret = funcs->atomic_check(plane, plane_state);
447 if (ret) { 469 if (ret) {
448 DRM_DEBUG_KMS("[PLANE:%d] atomic check failed\n", 470 DRM_DEBUG_KMS("[PLANE:%d] atomic driver check failed\n",
449 plane->base.id); 471 plane->base.id);
450 return ret; 472 return ret;
451 } 473 }
@@ -465,16 +487,49 @@ int drm_atomic_helper_check(struct drm_device *dev,
465 487
466 ret = funcs->atomic_check(crtc, state->crtc_states[i]); 488 ret = funcs->atomic_check(crtc, state->crtc_states[i]);
467 if (ret) { 489 if (ret) {
468 DRM_DEBUG_KMS("[CRTC:%d] atomic check failed\n", 490 DRM_DEBUG_KMS("[CRTC:%d] atomic driver check failed\n",
469 crtc->base.id); 491 crtc->base.id);
470 return ret; 492 return ret;
471 } 493 }
472 } 494 }
473 495
496 return ret;
497}
498EXPORT_SYMBOL(drm_atomic_helper_check_planes);
499
500/**
501 * drm_atomic_helper_check - validate state object
502 * @dev: DRM device
503 * @state: the driver state object
504 *
505 * Check the state object to see if the requested state is physically possible.
506 * Only crtcs and planes have check callbacks, so for any additional (global)
507 * checking that a driver needs it can simply wrap that around this function.
508 * Drivers without such needs can directly use this as their ->atomic_check()
509 * callback.
510 *
511 * This just wraps the two parts of the state checking for planes and modeset
512 * state in the default order: First it calls drm_atomic_helper_check_modeset()
513 * and then drm_atomic_helper_check_planes(). The assumption is that the
514 * ->atomic_check functions depend upon an updated adjusted_mode.clock to
515 * e.g. properly compute watermarks.
516 *
517 * RETURNS
518 * Zero for success or -errno
519 */
520int drm_atomic_helper_check(struct drm_device *dev,
521 struct drm_atomic_state *state)
522{
523 int ret;
524
474 ret = drm_atomic_helper_check_modeset(dev, state); 525 ret = drm_atomic_helper_check_modeset(dev, state);
475 if (ret) 526 if (ret)
476 return ret; 527 return ret;
477 528
529 ret = drm_atomic_helper_check_planes(dev, state);
530 if (ret)
531 return ret;
532
478 return ret; 533 return ret;
479} 534}
480EXPORT_SYMBOL(drm_atomic_helper_check); 535EXPORT_SYMBOL(drm_atomic_helper_check);
@@ -1222,7 +1277,7 @@ retry:
1222 goto fail; 1277 goto fail;
1223 } 1278 }
1224 1279
1225 ret = drm_atomic_set_crtc_for_plane(state, plane, crtc); 1280 ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
1226 if (ret != 0) 1281 if (ret != 0)
1227 goto fail; 1282 goto fail;
1228 drm_atomic_set_fb_for_plane(plane_state, fb); 1283 drm_atomic_set_fb_for_plane(plane_state, fb);
@@ -1301,7 +1356,7 @@ retry:
1301 goto fail; 1356 goto fail;
1302 } 1357 }
1303 1358
1304 ret = drm_atomic_set_crtc_for_plane(state, plane, NULL); 1359 ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
1305 if (ret != 0) 1360 if (ret != 0)
1306 goto fail; 1361 goto fail;
1307 drm_atomic_set_fb_for_plane(plane_state, NULL); 1362 drm_atomic_set_fb_for_plane(plane_state, NULL);
@@ -1464,7 +1519,7 @@ retry:
1464 1519
1465 crtc_state->enable = false; 1520 crtc_state->enable = false;
1466 1521
1467 ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, NULL); 1522 ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
1468 if (ret != 0) 1523 if (ret != 0)
1469 goto fail; 1524 goto fail;
1470 1525
@@ -1479,7 +1534,7 @@ retry:
1479 crtc_state->enable = true; 1534 crtc_state->enable = true;
1480 drm_mode_copy(&crtc_state->mode, set->mode); 1535 drm_mode_copy(&crtc_state->mode, set->mode);
1481 1536
1482 ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, crtc); 1537 ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
1483 if (ret != 0) 1538 if (ret != 0)
1484 goto fail; 1539 goto fail;
1485 drm_atomic_set_fb_for_plane(primary_state, set->fb); 1540 drm_atomic_set_fb_for_plane(primary_state, set->fb);
@@ -1558,8 +1613,8 @@ retry:
1558 goto fail; 1613 goto fail;
1559 } 1614 }
1560 1615
1561 ret = crtc->funcs->atomic_set_property(crtc, crtc_state, 1616 ret = drm_atomic_crtc_set_property(crtc, crtc_state,
1562 property, val); 1617 property, val);
1563 if (ret) 1618 if (ret)
1564 goto fail; 1619 goto fail;
1565 1620
@@ -1617,8 +1672,8 @@ retry:
1617 goto fail; 1672 goto fail;
1618 } 1673 }
1619 1674
1620 ret = plane->funcs->atomic_set_property(plane, plane_state, 1675 ret = drm_atomic_plane_set_property(plane, plane_state,
1621 property, val); 1676 property, val);
1622 if (ret) 1677 if (ret)
1623 goto fail; 1678 goto fail;
1624 1679
@@ -1676,8 +1731,8 @@ retry:
1676 goto fail; 1731 goto fail;
1677 } 1732 }
1678 1733
1679 ret = connector->funcs->atomic_set_property(connector, connector_state, 1734 ret = drm_atomic_connector_set_property(connector, connector_state,
1680 property, val); 1735 property, val);
1681 if (ret) 1736 if (ret)
1682 goto fail; 1737 goto fail;
1683 1738
@@ -1751,7 +1806,7 @@ retry:
1751 goto fail; 1806 goto fail;
1752 } 1807 }
1753 1808
1754 ret = drm_atomic_set_crtc_for_plane(state, plane, crtc); 1809 ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
1755 if (ret != 0) 1810 if (ret != 0)
1756 goto fail; 1811 goto fail;
1757 drm_atomic_set_fb_for_plane(plane_state, fb); 1812 drm_atomic_set_fb_for_plane(plane_state, fb);
@@ -1814,6 +1869,9 @@ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
1814{ 1869{
1815 kfree(crtc->state); 1870 kfree(crtc->state);
1816 crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); 1871 crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
1872
1873 if (crtc->state)
1874 crtc->state->crtc = crtc;
1817} 1875}
1818EXPORT_SYMBOL(drm_atomic_helper_crtc_reset); 1876EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
1819 1877
@@ -1873,6 +1931,9 @@ void drm_atomic_helper_plane_reset(struct drm_plane *plane)
1873 1931
1874 kfree(plane->state); 1932 kfree(plane->state);
1875 plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL); 1933 plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
1934
1935 if (plane->state)
1936 plane->state->plane = plane;
1876} 1937}
1877EXPORT_SYMBOL(drm_atomic_helper_plane_reset); 1938EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
1878 1939
@@ -1930,6 +1991,9 @@ void drm_atomic_helper_connector_reset(struct drm_connector *connector)
1930{ 1991{
1931 kfree(connector->state); 1992 kfree(connector->state);
1932 connector->state = kzalloc(sizeof(*connector->state), GFP_KERNEL); 1993 connector->state = kzalloc(sizeof(*connector->state), GFP_KERNEL);
1994
1995 if (connector->state)
1996 connector->state->connector = connector;
1933} 1997}
1934EXPORT_SYMBOL(drm_atomic_helper_connector_reset); 1998EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
1935 1999
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 2892d746a1e9..7e4acad3f6f9 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -38,6 +38,7 @@
38#include <drm/drm_edid.h> 38#include <drm/drm_edid.h>
39#include <drm/drm_fourcc.h> 39#include <drm/drm_fourcc.h>
40#include <drm/drm_modeset_lock.h> 40#include <drm/drm_modeset_lock.h>
41#include <drm/drm_atomic.h>
41 42
42#include "drm_crtc_internal.h" 43#include "drm_crtc_internal.h"
43#include "drm_internal.h" 44#include "drm_internal.h"
@@ -830,6 +831,7 @@ int drm_connector_init(struct drm_device *dev,
830 const struct drm_connector_funcs *funcs, 831 const struct drm_connector_funcs *funcs,
831 int connector_type) 832 int connector_type)
832{ 833{
834 struct drm_mode_config *config = &dev->mode_config;
833 int ret; 835 int ret;
834 struct ida *connector_ida = 836 struct ida *connector_ida =
835 &drm_connector_enum_list[connector_type].ida; 837 &drm_connector_enum_list[connector_type].ida;
@@ -868,16 +870,20 @@ int drm_connector_init(struct drm_device *dev,
868 870
869 /* We should add connectors at the end to avoid upsetting the connector 871 /* We should add connectors at the end to avoid upsetting the connector
870 * index too much. */ 872 * index too much. */
871 list_add_tail(&connector->head, &dev->mode_config.connector_list); 873 list_add_tail(&connector->head, &config->connector_list);
872 dev->mode_config.num_connector++; 874 config->num_connector++;
873 875
874 if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL) 876 if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
875 drm_object_attach_property(&connector->base, 877 drm_object_attach_property(&connector->base,
876 dev->mode_config.edid_property, 878 config->edid_property,
877 0); 879 0);
878 880
879 drm_object_attach_property(&connector->base, 881 drm_object_attach_property(&connector->base,
880 dev->mode_config.dpms_property, 0); 882 config->dpms_property, 0);
883
884 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
885 drm_object_attach_property(&connector->base, config->prop_crtc_id, 0);
886 }
881 887
882 connector->debugfs_entry = NULL; 888 connector->debugfs_entry = NULL;
883 889
@@ -1168,6 +1174,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
1168 const uint32_t *formats, uint32_t format_count, 1174 const uint32_t *formats, uint32_t format_count,
1169 enum drm_plane_type type) 1175 enum drm_plane_type type)
1170{ 1176{
1177 struct drm_mode_config *config = &dev->mode_config;
1171 int ret; 1178 int ret;
1172 1179
1173 ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); 1180 ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
@@ -1192,15 +1199,28 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
1192 plane->possible_crtcs = possible_crtcs; 1199 plane->possible_crtcs = possible_crtcs;
1193 plane->type = type; 1200 plane->type = type;
1194 1201
1195 list_add_tail(&plane->head, &dev->mode_config.plane_list); 1202 list_add_tail(&plane->head, &config->plane_list);
1196 dev->mode_config.num_total_plane++; 1203 config->num_total_plane++;
1197 if (plane->type == DRM_PLANE_TYPE_OVERLAY) 1204 if (plane->type == DRM_PLANE_TYPE_OVERLAY)
1198 dev->mode_config.num_overlay_plane++; 1205 config->num_overlay_plane++;
1199 1206
1200 drm_object_attach_property(&plane->base, 1207 drm_object_attach_property(&plane->base,
1201 dev->mode_config.plane_type_property, 1208 config->plane_type_property,
1202 plane->type); 1209 plane->type);
1203 1210
1211 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
1212 drm_object_attach_property(&plane->base, config->prop_fb_id, 0);
1213 drm_object_attach_property(&plane->base, config->prop_crtc_id, 0);
1214 drm_object_attach_property(&plane->base, config->prop_crtc_x, 0);
1215 drm_object_attach_property(&plane->base, config->prop_crtc_y, 0);
1216 drm_object_attach_property(&plane->base, config->prop_crtc_w, 0);
1217 drm_object_attach_property(&plane->base, config->prop_crtc_h, 0);
1218 drm_object_attach_property(&plane->base, config->prop_src_x, 0);
1219 drm_object_attach_property(&plane->base, config->prop_src_y, 0);
1220 drm_object_attach_property(&plane->base, config->prop_src_w, 0);
1221 drm_object_attach_property(&plane->base, config->prop_src_h, 0);
1222 }
1223
1204 return 0; 1224 return 0;
1205} 1225}
1206EXPORT_SYMBOL(drm_universal_plane_init); 1226EXPORT_SYMBOL(drm_universal_plane_init);
@@ -1322,50 +1342,109 @@ void drm_plane_force_disable(struct drm_plane *plane)
1322} 1342}
1323EXPORT_SYMBOL(drm_plane_force_disable); 1343EXPORT_SYMBOL(drm_plane_force_disable);
1324 1344
1325static int drm_mode_create_standard_connector_properties(struct drm_device *dev) 1345static int drm_mode_create_standard_properties(struct drm_device *dev)
1326{ 1346{
1327 struct drm_property *edid; 1347 struct drm_property *prop;
1328 struct drm_property *dpms;
1329 struct drm_property *dev_path;
1330 1348
1331 /* 1349 /*
1332 * Standard properties (apply to all connectors) 1350 * Standard properties (apply to all connectors)
1333 */ 1351 */
1334 edid = drm_property_create(dev, DRM_MODE_PROP_BLOB | 1352 prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
1335 DRM_MODE_PROP_IMMUTABLE, 1353 DRM_MODE_PROP_IMMUTABLE,
1336 "EDID", 0); 1354 "EDID", 0);
1337 dev->mode_config.edid_property = edid; 1355 if (!prop)
1356 return -ENOMEM;
1357 dev->mode_config.edid_property = prop;
1338 1358
1339 dpms = drm_property_create_enum(dev, 0, 1359 prop = drm_property_create_enum(dev, 0,
1340 "DPMS", drm_dpms_enum_list, 1360 "DPMS", drm_dpms_enum_list,
1341 ARRAY_SIZE(drm_dpms_enum_list)); 1361 ARRAY_SIZE(drm_dpms_enum_list));
1342 dev->mode_config.dpms_property = dpms; 1362 if (!prop)
1343 1363 return -ENOMEM;
1344 dev_path = drm_property_create(dev, 1364 dev->mode_config.dpms_property = prop;
1345 DRM_MODE_PROP_BLOB |
1346 DRM_MODE_PROP_IMMUTABLE,
1347 "PATH", 0);
1348 dev->mode_config.path_property = dev_path;
1349
1350 dev->mode_config.tile_property = drm_property_create(dev,
1351 DRM_MODE_PROP_BLOB |
1352 DRM_MODE_PROP_IMMUTABLE,
1353 "TILE", 0);
1354 1365
1355 return 0; 1366 prop = drm_property_create(dev,
1356} 1367 DRM_MODE_PROP_BLOB |
1368 DRM_MODE_PROP_IMMUTABLE,
1369 "PATH", 0);
1370 if (!prop)
1371 return -ENOMEM;
1372 dev->mode_config.path_property = prop;
1357 1373
1358static int drm_mode_create_standard_plane_properties(struct drm_device *dev) 1374 prop = drm_property_create(dev,
1359{ 1375 DRM_MODE_PROP_BLOB |
1360 struct drm_property *type; 1376 DRM_MODE_PROP_IMMUTABLE,
1377 "TILE", 0);
1378 if (!prop)
1379 return -ENOMEM;
1380 dev->mode_config.tile_property = prop;
1361 1381
1362 /* 1382 prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1363 * Standard properties (apply to all planes)
1364 */
1365 type = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1366 "type", drm_plane_type_enum_list, 1383 "type", drm_plane_type_enum_list,
1367 ARRAY_SIZE(drm_plane_type_enum_list)); 1384 ARRAY_SIZE(drm_plane_type_enum_list));
1368 dev->mode_config.plane_type_property = type; 1385 if (!prop)
1386 return -ENOMEM;
1387 dev->mode_config.plane_type_property = prop;
1388
1389 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
1390 "SRC_X", 0, UINT_MAX);
1391 if (!prop)
1392 return -ENOMEM;
1393 dev->mode_config.prop_src_x = prop;
1394
1395 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
1396 "SRC_Y", 0, UINT_MAX);
1397 if (!prop)
1398 return -ENOMEM;
1399 dev->mode_config.prop_src_y = prop;
1400
1401 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
1402 "SRC_W", 0, UINT_MAX);
1403 if (!prop)
1404 return -ENOMEM;
1405 dev->mode_config.prop_src_w = prop;
1406
1407 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
1408 "SRC_H", 0, UINT_MAX);
1409 if (!prop)
1410 return -ENOMEM;
1411 dev->mode_config.prop_src_h = prop;
1412
1413 prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
1414 "CRTC_X", INT_MIN, INT_MAX);
1415 if (!prop)
1416 return -ENOMEM;
1417 dev->mode_config.prop_crtc_x = prop;
1418
1419 prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
1420 "CRTC_Y", INT_MIN, INT_MAX);
1421 if (!prop)
1422 return -ENOMEM;
1423 dev->mode_config.prop_crtc_y = prop;
1424
1425 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
1426 "CRTC_W", 0, INT_MAX);
1427 if (!prop)
1428 return -ENOMEM;
1429 dev->mode_config.prop_crtc_w = prop;
1430
1431 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
1432 "CRTC_H", 0, INT_MAX);
1433 if (!prop)
1434 return -ENOMEM;
1435 dev->mode_config.prop_crtc_h = prop;
1436
1437 prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
1438 "FB_ID", DRM_MODE_OBJECT_FB);
1439 if (!prop)
1440 return -ENOMEM;
1441 dev->mode_config.prop_fb_id = prop;
1442
1443 prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
1444 "CRTC_ID", DRM_MODE_OBJECT_CRTC);
1445 if (!prop)
1446 return -ENOMEM;
1447 dev->mode_config.prop_crtc_id = prop;
1369 1448
1370 return 0; 1449 return 0;
1371} 1450}
@@ -1991,6 +2070,44 @@ static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *conne
1991 return connector->encoder; 2070 return connector->encoder;
1992} 2071}
1993 2072
2073/* helper for getconnector and getproperties ioctls */
2074static int get_properties(struct drm_mode_object *obj, bool atomic,
2075 uint32_t __user *prop_ptr, uint64_t __user *prop_values,
2076 uint32_t *arg_count_props)
2077{
2078 int props_count;
2079 int i, ret, copied;
2080
2081 props_count = obj->properties->count;
2082 if (!atomic)
2083 props_count -= obj->properties->atomic_count;
2084
2085 if ((*arg_count_props >= props_count) && props_count) {
2086 for (i = 0, copied = 0; copied < props_count; i++) {
2087 struct drm_property *prop = obj->properties->properties[i];
2088 uint64_t val;
2089
2090 if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic)
2091 continue;
2092
2093 ret = drm_object_property_get_value(obj, prop, &val);
2094 if (ret)
2095 return ret;
2096
2097 if (put_user(prop->base.id, prop_ptr + copied))
2098 return -EFAULT;
2099
2100 if (put_user(val, prop_values + copied))
2101 return -EFAULT;
2102
2103 copied++;
2104 }
2105 }
2106 *arg_count_props = props_count;
2107
2108 return 0;
2109}
2110
1994/** 2111/**
1995 * drm_mode_getconnector - get connector configuration 2112 * drm_mode_getconnector - get connector configuration
1996 * @dev: drm device for the ioctl 2113 * @dev: drm device for the ioctl
@@ -2012,15 +2129,12 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
2012 struct drm_encoder *encoder; 2129 struct drm_encoder *encoder;
2013 struct drm_display_mode *mode; 2130 struct drm_display_mode *mode;
2014 int mode_count = 0; 2131 int mode_count = 0;
2015 int props_count = 0;
2016 int encoders_count = 0; 2132 int encoders_count = 0;
2017 int ret = 0; 2133 int ret = 0;
2018 int copied = 0; 2134 int copied = 0;
2019 int i; 2135 int i;
2020 struct drm_mode_modeinfo u_mode; 2136 struct drm_mode_modeinfo u_mode;
2021 struct drm_mode_modeinfo __user *mode_ptr; 2137 struct drm_mode_modeinfo __user *mode_ptr;
2022 uint32_t __user *prop_ptr;
2023 uint64_t __user *prop_values;
2024 uint32_t __user *encoder_ptr; 2138 uint32_t __user *encoder_ptr;
2025 2139
2026 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2140 if (!drm_core_check_feature(dev, DRIVER_MODESET))
@@ -2031,6 +2145,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
2031 DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id); 2145 DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
2032 2146
2033 mutex_lock(&dev->mode_config.mutex); 2147 mutex_lock(&dev->mode_config.mutex);
2148 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
2034 2149
2035 connector = drm_connector_find(dev, out_resp->connector_id); 2150 connector = drm_connector_find(dev, out_resp->connector_id);
2036 if (!connector) { 2151 if (!connector) {
@@ -2038,8 +2153,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
2038 goto out; 2153 goto out;
2039 } 2154 }
2040 2155
2041 props_count = connector->properties.count;
2042
2043 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) 2156 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
2044 if (connector->encoder_ids[i] != 0) 2157 if (connector->encoder_ids[i] != 0)
2045 encoders_count++; 2158 encoders_count++;
@@ -2062,14 +2175,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
2062 out_resp->mm_height = connector->display_info.height_mm; 2175 out_resp->mm_height = connector->display_info.height_mm;
2063 out_resp->subpixel = connector->display_info.subpixel_order; 2176 out_resp->subpixel = connector->display_info.subpixel_order;
2064 out_resp->connection = connector->status; 2177 out_resp->connection = connector->status;
2065 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
2066
2067 encoder = drm_connector_get_encoder(connector); 2178 encoder = drm_connector_get_encoder(connector);
2068 if (encoder) 2179 if (encoder)
2069 out_resp->encoder_id = encoder->base.id; 2180 out_resp->encoder_id = encoder->base.id;
2070 else 2181 else
2071 out_resp->encoder_id = 0; 2182 out_resp->encoder_id = 0;
2072 drm_modeset_unlock(&dev->mode_config.connection_mutex);
2073 2183
2074 /* 2184 /*
2075 * This ioctl is called twice, once to determine how much space is 2185 * This ioctl is called twice, once to determine how much space is
@@ -2093,26 +2203,12 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
2093 } 2203 }
2094 out_resp->count_modes = mode_count; 2204 out_resp->count_modes = mode_count;
2095 2205
2096 if ((out_resp->count_props >= props_count) && props_count) { 2206 ret = get_properties(&connector->base, file_priv->atomic,
2097 copied = 0; 2207 (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
2098 prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr); 2208 (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
2099 prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr); 2209 &out_resp->count_props);
2100 for (i = 0; i < connector->properties.count; i++) { 2210 if (ret)
2101 if (put_user(connector->properties.ids[i], 2211 goto out;
2102 prop_ptr + copied)) {
2103 ret = -EFAULT;
2104 goto out;
2105 }
2106
2107 if (put_user(connector->properties.values[i],
2108 prop_values + copied)) {
2109 ret = -EFAULT;
2110 goto out;
2111 }
2112 copied++;
2113 }
2114 }
2115 out_resp->count_props = props_count;
2116 2212
2117 if ((out_resp->count_encoders >= encoders_count) && encoders_count) { 2213 if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
2118 copied = 0; 2214 copied = 0;
@@ -2131,6 +2227,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
2131 out_resp->count_encoders = encoders_count; 2227 out_resp->count_encoders = encoders_count;
2132 2228
2133out: 2229out:
2230 drm_modeset_unlock(&dev->mode_config.connection_mutex);
2134 mutex_unlock(&dev->mode_config.mutex); 2231 mutex_unlock(&dev->mode_config.mutex);
2135 2232
2136 return ret; 2233 return ret;
@@ -3823,9 +3920,11 @@ void drm_object_attach_property(struct drm_mode_object *obj,
3823 return; 3920 return;
3824 } 3921 }
3825 3922
3826 obj->properties->ids[count] = property->base.id; 3923 obj->properties->properties[count] = property;
3827 obj->properties->values[count] = init_val; 3924 obj->properties->values[count] = init_val;
3828 obj->properties->count++; 3925 obj->properties->count++;
3926 if (property->flags & DRM_MODE_PROP_ATOMIC)
3927 obj->properties->atomic_count++;
3829} 3928}
3830EXPORT_SYMBOL(drm_object_attach_property); 3929EXPORT_SYMBOL(drm_object_attach_property);
3831 3930
@@ -3848,7 +3947,7 @@ int drm_object_property_set_value(struct drm_mode_object *obj,
3848 int i; 3947 int i;
3849 3948
3850 for (i = 0; i < obj->properties->count; i++) { 3949 for (i = 0; i < obj->properties->count; i++) {
3851 if (obj->properties->ids[i] == property->base.id) { 3950 if (obj->properties->properties[i] == property) {
3852 obj->properties->values[i] = val; 3951 obj->properties->values[i] = val;
3853 return 0; 3952 return 0;
3854 } 3953 }
@@ -3877,8 +3976,16 @@ int drm_object_property_get_value(struct drm_mode_object *obj,
3877{ 3976{
3878 int i; 3977 int i;
3879 3978
3979 /* read-only properties bypass atomic mechanism and still store
3980 * their value in obj->properties->values[].. mostly to avoid
3981 * having to deal w/ EDID and similar props in atomic paths:
3982 */
3983 if (drm_core_check_feature(property->dev, DRIVER_ATOMIC) &&
3984 !(property->flags & DRM_MODE_PROP_IMMUTABLE))
3985 return drm_atomic_get_property(obj, property, val);
3986
3880 for (i = 0; i < obj->properties->count; i++) { 3987 for (i = 0; i < obj->properties->count; i++) {
3881 if (obj->properties->ids[i] == property->base.id) { 3988 if (obj->properties->properties[i] == property) {
3882 *val = obj->properties->values[i]; 3989 *val = obj->properties->values[i];
3883 return 0; 3990 return 0;
3884 } 3991 }
@@ -4194,14 +4301,24 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
4194} 4301}
4195EXPORT_SYMBOL(drm_mode_connector_update_edid_property); 4302EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
4196 4303
4197static bool drm_property_change_is_valid(struct drm_property *property, 4304/* Some properties could refer to dynamic refcnt'd objects, or things that
4198 uint64_t value) 4305 * need special locking to handle lifetime issues (ie. to ensure the prop
4306 * value doesn't become invalid part way through the property update due to
4307 * race). The value returned by reference via 'obj' should be passed back
4308 * to drm_property_change_valid_put() after the property is set (and the
4309 * object to which the property is attached has a chance to take it's own
4310 * reference).
4311 */
4312bool drm_property_change_valid_get(struct drm_property *property,
4313 uint64_t value, struct drm_mode_object **ref)
4199{ 4314{
4200 int i; 4315 int i;
4201 4316
4202 if (property->flags & DRM_MODE_PROP_IMMUTABLE) 4317 if (property->flags & DRM_MODE_PROP_IMMUTABLE)
4203 return false; 4318 return false;
4204 4319
4320 *ref = NULL;
4321
4205 if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) { 4322 if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
4206 if (value < property->values[0] || value > property->values[1]) 4323 if (value < property->values[0] || value > property->values[1])
4207 return false; 4324 return false;
@@ -4223,20 +4340,29 @@ static bool drm_property_change_is_valid(struct drm_property *property,
4223 /* Only the driver knows */ 4340 /* Only the driver knows */
4224 return true; 4341 return true;
4225 } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { 4342 } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
4226 struct drm_mode_object *obj;
4227
4228 /* a zero value for an object property translates to null: */ 4343 /* a zero value for an object property translates to null: */
4229 if (value == 0) 4344 if (value == 0)
4230 return true; 4345 return true;
4231 /* 4346
4232 * NOTE: use _object_find() directly to bypass restriction on 4347 /* handle refcnt'd objects specially: */
4233 * looking up refcnt'd objects (ie. fb's). For a refcnt'd 4348 if (property->values[0] == DRM_MODE_OBJECT_FB) {
4234 * object this could race against object finalization, so it 4349 struct drm_framebuffer *fb;
4235 * simply tells us that the object *was* valid. Which is good 4350 fb = drm_framebuffer_lookup(property->dev, value);
4236 * enough. 4351 if (fb) {
4237 */ 4352 *ref = &fb->base;
4238 obj = _object_find(property->dev, value, property->values[0]); 4353 return true;
4239 return obj != NULL; 4354 } else {
4355 return false;
4356 }
4357 } else {
4358 return _object_find(property->dev, value, property->values[0]) != NULL;
4359 }
4360 } else {
4361 int i;
4362 for (i = 0; i < property->num_values; i++)
4363 if (property->values[i] == value)
4364 return true;
4365 return false;
4240 } 4366 }
4241 4367
4242 for (i = 0; i < property->num_values; i++) 4368 for (i = 0; i < property->num_values; i++)
@@ -4245,6 +4371,18 @@ static bool drm_property_change_is_valid(struct drm_property *property,
4245 return false; 4371 return false;
4246} 4372}
4247 4373
4374void drm_property_change_valid_put(struct drm_property *property,
4375 struct drm_mode_object *ref)
4376{
4377 if (!ref)
4378 return;
4379
4380 if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
4381 if (property->values[0] == DRM_MODE_OBJECT_FB)
4382 drm_framebuffer_unreference(obj_to_fb(ref));
4383 }
4384}
4385
4248/** 4386/**
4249 * drm_mode_connector_property_set_ioctl - set the current value of a connector property 4387 * drm_mode_connector_property_set_ioctl - set the current value of a connector property
4250 * @dev: DRM device 4388 * @dev: DRM device
@@ -4360,11 +4498,6 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
4360 struct drm_mode_obj_get_properties *arg = data; 4498 struct drm_mode_obj_get_properties *arg = data;
4361 struct drm_mode_object *obj; 4499 struct drm_mode_object *obj;
4362 int ret = 0; 4500 int ret = 0;
4363 int i;
4364 int copied = 0;
4365 int props_count = 0;
4366 uint32_t __user *props_ptr;
4367 uint64_t __user *prop_values_ptr;
4368 4501
4369 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 4502 if (!drm_core_check_feature(dev, DRIVER_MODESET))
4370 return -EINVAL; 4503 return -EINVAL;
@@ -4381,30 +4514,11 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
4381 goto out; 4514 goto out;
4382 } 4515 }
4383 4516
4384 props_count = obj->properties->count; 4517 ret = get_properties(obj, file_priv->atomic,
4518 (uint32_t __user *)(unsigned long)(arg->props_ptr),
4519 (uint64_t __user *)(unsigned long)(arg->prop_values_ptr),
4520 &arg->count_props);
4385 4521
4386 /* This ioctl is called twice, once to determine how much space is
4387 * needed, and the 2nd time to fill it. */
4388 if ((arg->count_props >= props_count) && props_count) {
4389 copied = 0;
4390 props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
4391 prop_values_ptr = (uint64_t __user *)(unsigned long)
4392 (arg->prop_values_ptr);
4393 for (i = 0; i < props_count; i++) {
4394 if (put_user(obj->properties->ids[i],
4395 props_ptr + copied)) {
4396 ret = -EFAULT;
4397 goto out;
4398 }
4399 if (put_user(obj->properties->values[i],
4400 prop_values_ptr + copied)) {
4401 ret = -EFAULT;
4402 goto out;
4403 }
4404 copied++;
4405 }
4406 }
4407 arg->count_props = props_count;
4408out: 4522out:
4409 drm_modeset_unlock_all(dev); 4523 drm_modeset_unlock_all(dev);
4410 return ret; 4524 return ret;
@@ -4433,8 +4547,8 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
4433 struct drm_mode_object *arg_obj; 4547 struct drm_mode_object *arg_obj;
4434 struct drm_mode_object *prop_obj; 4548 struct drm_mode_object *prop_obj;
4435 struct drm_property *property; 4549 struct drm_property *property;
4436 int ret = -EINVAL; 4550 int i, ret = -EINVAL;
4437 int i; 4551 struct drm_mode_object *ref;
4438 4552
4439 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 4553 if (!drm_core_check_feature(dev, DRIVER_MODESET))
4440 return -EINVAL; 4554 return -EINVAL;
@@ -4450,7 +4564,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
4450 goto out; 4564 goto out;
4451 4565
4452 for (i = 0; i < arg_obj->properties->count; i++) 4566 for (i = 0; i < arg_obj->properties->count; i++)
4453 if (arg_obj->properties->ids[i] == arg->prop_id) 4567 if (arg_obj->properties->properties[i]->base.id == arg->prop_id)
4454 break; 4568 break;
4455 4569
4456 if (i == arg_obj->properties->count) 4570 if (i == arg_obj->properties->count)
@@ -4464,7 +4578,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
4464 } 4578 }
4465 property = obj_to_property(prop_obj); 4579 property = obj_to_property(prop_obj);
4466 4580
4467 if (!drm_property_change_is_valid(property, arg->value)) 4581 if (!drm_property_change_valid_get(property, arg->value, &ref))
4468 goto out; 4582 goto out;
4469 4583
4470 switch (arg_obj->type) { 4584 switch (arg_obj->type) {
@@ -4481,6 +4595,8 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
4481 break; 4595 break;
4482 } 4596 }
4483 4597
4598 drm_property_change_valid_put(property, ref);
4599
4484out: 4600out:
4485 drm_modeset_unlock_all(dev); 4601 drm_modeset_unlock_all(dev);
4486 return ret; 4602 return ret;
@@ -5225,8 +5341,7 @@ void drm_mode_config_init(struct drm_device *dev)
5225 idr_init(&dev->mode_config.tile_idr); 5341 idr_init(&dev->mode_config.tile_idr);
5226 5342
5227 drm_modeset_lock_all(dev); 5343 drm_modeset_lock_all(dev);
5228 drm_mode_create_standard_connector_properties(dev); 5344 drm_mode_create_standard_properties(dev);
5229 drm_mode_create_standard_plane_properties(dev);
5230 drm_modeset_unlock_all(dev); 5345 drm_modeset_unlock_all(dev);
5231 5346
5232 /* Just to be sure */ 5347 /* Just to be sure */
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index d552708409de..b1979e7bdc88 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -946,6 +946,7 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mod
946 crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); 946 crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL);
947 if (!crtc_state) 947 if (!crtc_state)
948 return -ENOMEM; 948 return -ENOMEM;
949 crtc_state->crtc = crtc;
949 950
950 crtc_state->enable = true; 951 crtc_state->enable = true;
951 crtc_state->planes_changed = true; 952 crtc_state->planes_changed = true;
@@ -1005,6 +1006,7 @@ int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
1005 plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); 1006 plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
1006 if (!plane_state) 1007 if (!plane_state)
1007 return -ENOMEM; 1008 return -ENOMEM;
1009 plane_state->plane = plane;
1008 1010
1009 plane_state->crtc = crtc; 1011 plane_state->crtc = crtc;
1010 drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb); 1012 drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb);
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index a2945ee6d675..247dc8b62564 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -36,3 +36,9 @@ int drm_mode_object_get(struct drm_device *dev,
36void drm_mode_object_put(struct drm_device *dev, 36void drm_mode_object_put(struct drm_device *dev,
37 struct drm_mode_object *object); 37 struct drm_mode_object *object);
38 38
39/* drm_atomic.c */
40int drm_atomic_get_property(struct drm_mode_object *obj,
41 struct drm_property *property, uint64_t *val);
42int drm_mode_atomic_ioctl(struct drm_device *dev,
43 void *data, struct drm_file *file_priv);
44
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 4f41377b0b80..d51213464672 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -40,15 +40,19 @@
40unsigned int drm_debug = 0; /* 1 to enable debug output */ 40unsigned int drm_debug = 0; /* 1 to enable debug output */
41EXPORT_SYMBOL(drm_debug); 41EXPORT_SYMBOL(drm_debug);
42 42
43bool drm_atomic = 0;
44
43MODULE_AUTHOR(CORE_AUTHOR); 45MODULE_AUTHOR(CORE_AUTHOR);
44MODULE_DESCRIPTION(CORE_DESC); 46MODULE_DESCRIPTION(CORE_DESC);
45MODULE_LICENSE("GPL and additional rights"); 47MODULE_LICENSE("GPL and additional rights");
46MODULE_PARM_DESC(debug, "Enable debug output"); 48MODULE_PARM_DESC(debug, "Enable debug output");
49MODULE_PARM_DESC(atomic, "Enable experimental atomic KMS API");
47MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs] (0: never disable, <0: disable immediately)"); 50MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs] (0: never disable, <0: disable immediately)");
48MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); 51MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
49MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps"); 52MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
50 53
51module_param_named(debug, drm_debug, int, 0600); 54module_param_named(debug, drm_debug, int, 0600);
55module_param_named_unsafe(atomic, drm_atomic, bool, 0600);
52 56
53static DEFINE_SPINLOCK(drm_minor_lock); 57static DEFINE_SPINLOCK(drm_minor_lock);
54static struct idr drm_minors_idr; 58static struct idr drm_minors_idr;
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 00587a1e3c83..3785d66721f2 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -32,6 +32,7 @@
32#include <drm/drm_core.h> 32#include <drm/drm_core.h>
33#include "drm_legacy.h" 33#include "drm_legacy.h"
34#include "drm_internal.h" 34#include "drm_internal.h"
35#include "drm_crtc_internal.h"
35 36
36#include <linux/pci.h> 37#include <linux/pci.h>
37#include <linux/export.h> 38#include <linux/export.h>
@@ -345,6 +346,17 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
345 return -EINVAL; 346 return -EINVAL;
346 file_priv->universal_planes = req->value; 347 file_priv->universal_planes = req->value;
347 break; 348 break;
349 case DRM_CLIENT_CAP_ATOMIC:
350 /* for now, hide behind experimental drm.atomic moduleparam */
351 if (!drm_atomic)
352 return -EINVAL;
353 if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
354 return -EINVAL;
355 if (req->value > 1)
356 return -EINVAL;
357 file_priv->atomic = req->value;
358 file_priv->universal_planes = req->value;
359 break;
348 default: 360 default:
349 return -EINVAL; 361 return -EINVAL;
350 } 362 }
@@ -620,6 +632,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
620 DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 632 DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
621 DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 633 DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
622 DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 634 DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
635 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
623}; 636};
624 637
625#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) 638#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 391dfb7d1086..f24c4cfe674b 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -523,6 +523,7 @@ int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
523 plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); 523 plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
524 if (!plane_state) 524 if (!plane_state)
525 return -ENOMEM; 525 return -ENOMEM;
526 plane_state->plane = plane;
526 527
527 plane_state->crtc = crtc; 528 plane_state->crtc = crtc;
528 drm_atomic_set_fb_for_plane(plane_state, fb); 529 drm_atomic_set_fb_for_plane(plane_state, fb);
@@ -569,6 +570,7 @@ int drm_plane_helper_disable(struct drm_plane *plane)
569 plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); 570 plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
570 if (!plane_state) 571 if (!plane_state)
571 return -ENOMEM; 572 return -ENOMEM;
573 plane_state->plane = plane;
572 574
573 plane_state->crtc = NULL; 575 plane_state->crtc = NULL;
574 drm_atomic_set_fb_for_plane(plane_state, NULL); 576 drm_atomic_set_fb_for_plane(plane_state, NULL);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 26e5fdea6594..fc76f630e5b1 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -113,6 +113,7 @@ static void mdp5_plane_reset(struct drm_plane *plane)
113 } else { 113 } else {
114 mdp5_state->zpos = 1 + drm_plane_index(plane); 114 mdp5_state->zpos = 1 + drm_plane_index(plane);
115 } 115 }
116 mdp5_state->base.plane = plane;
116 117
117 plane->state = &mdp5_state->base; 118 plane->state = &mdp5_state->base;
118} 119}
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 191968256c58..2c396540e279 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -127,6 +127,26 @@ static void add_fb(struct msm_commit *c, struct drm_framebuffer *fb)
127} 127}
128 128
129 129
130int msm_atomic_check(struct drm_device *dev,
131 struct drm_atomic_state *state)
132{
133 int ret;
134
135 /*
136 * msm ->atomic_check can update ->mode_changed for pixel format
137 * changes, hence must be run before we check the modeset changes.
138 */
139 ret = drm_atomic_helper_check_planes(dev, state);
140 if (ret)
141 return ret;
142
143 ret = drm_atomic_helper_check_modeset(dev, state);
144 if (ret)
145 return ret;
146
147 return ret;
148}
149
130/** 150/**
131 * drm_atomic_helper_commit - commit validated state object 151 * drm_atomic_helper_commit - commit validated state object
132 * @dev: DRM device 152 * @dev: DRM device
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 9a61546a0b05..f1ebedde6346 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -29,7 +29,7 @@ static void msm_fb_output_poll_changed(struct drm_device *dev)
29static const struct drm_mode_config_funcs mode_config_funcs = { 29static const struct drm_mode_config_funcs mode_config_funcs = {
30 .fb_create = msm_framebuffer_create, 30 .fb_create = msm_framebuffer_create,
31 .output_poll_changed = msm_fb_output_poll_changed, 31 .output_poll_changed = msm_fb_output_poll_changed,
32 .atomic_check = drm_atomic_helper_check, 32 .atomic_check = msm_atomic_check,
33 .atomic_commit = msm_atomic_commit, 33 .atomic_commit = msm_atomic_commit,
34}; 34};
35 35
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index b69ef2d5a26c..22e5391a7ce8 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -148,6 +148,8 @@ void __msm_fence_worker(struct work_struct *work);
148 (_cb)->func = _func; \ 148 (_cb)->func = _func; \
149 } while (0) 149 } while (0)
150 150
151int msm_atomic_check(struct drm_device *dev,
152 struct drm_atomic_state *state);
151int msm_atomic_commit(struct drm_device *dev, 153int msm_atomic_commit(struct drm_device *dev,
152 struct drm_atomic_state *state, bool async); 154 struct drm_atomic_state *state, bool async);
153 155
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index a5f6a1f563c4..e928625a9da0 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -143,6 +143,7 @@ void drm_err(const char *format, ...);
143#define DRIVER_MODESET 0x2000 143#define DRIVER_MODESET 0x2000
144#define DRIVER_PRIME 0x4000 144#define DRIVER_PRIME 0x4000
145#define DRIVER_RENDER 0x8000 145#define DRIVER_RENDER 0x8000
146#define DRIVER_ATOMIC 0x10000
146 147
147/***********************************************************************/ 148/***********************************************************************/
148/** \name Macros to make printk easier */ 149/** \name Macros to make printk easier */
@@ -283,6 +284,8 @@ struct drm_file {
283 * in the plane list 284 * in the plane list
284 */ 285 */
285 unsigned universal_planes:1; 286 unsigned universal_planes:1;
287 /* true if client understands atomic properties */
288 unsigned atomic:1;
286 289
287 struct pid *pid; 290 struct pid *pid;
288 kuid_t uid; 291 kuid_t uid;
@@ -954,6 +957,7 @@ extern void drm_master_put(struct drm_master **master);
954extern void drm_put_dev(struct drm_device *dev); 957extern void drm_put_dev(struct drm_device *dev);
955extern void drm_unplug_dev(struct drm_device *dev); 958extern void drm_unplug_dev(struct drm_device *dev);
956extern unsigned int drm_debug; 959extern unsigned int drm_debug;
960extern bool drm_atomic;
957 961
958 /* Debugfs support */ 962 /* Debugfs support */
959#if defined(CONFIG_DEBUG_FS) 963#if defined(CONFIG_DEBUG_FS)
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index ad2229574dd9..51168a8b723a 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -38,16 +38,25 @@ void drm_atomic_state_free(struct drm_atomic_state *state);
38struct drm_crtc_state * __must_check 38struct drm_crtc_state * __must_check
39drm_atomic_get_crtc_state(struct drm_atomic_state *state, 39drm_atomic_get_crtc_state(struct drm_atomic_state *state,
40 struct drm_crtc *crtc); 40 struct drm_crtc *crtc);
41int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
42 struct drm_crtc_state *state, struct drm_property *property,
43 uint64_t val);
41struct drm_plane_state * __must_check 44struct drm_plane_state * __must_check
42drm_atomic_get_plane_state(struct drm_atomic_state *state, 45drm_atomic_get_plane_state(struct drm_atomic_state *state,
43 struct drm_plane *plane); 46 struct drm_plane *plane);
47int drm_atomic_plane_set_property(struct drm_plane *plane,
48 struct drm_plane_state *state, struct drm_property *property,
49 uint64_t val);
44struct drm_connector_state * __must_check 50struct drm_connector_state * __must_check
45drm_atomic_get_connector_state(struct drm_atomic_state *state, 51drm_atomic_get_connector_state(struct drm_atomic_state *state,
46 struct drm_connector *connector); 52 struct drm_connector *connector);
53int drm_atomic_connector_set_property(struct drm_connector *connector,
54 struct drm_connector_state *state, struct drm_property *property,
55 uint64_t val);
47 56
48int __must_check 57int __must_check
49drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state, 58drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
50 struct drm_plane *plane, struct drm_crtc *crtc); 59 struct drm_crtc *crtc);
51void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, 60void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
52 struct drm_framebuffer *fb); 61 struct drm_framebuffer *fb);
53int __must_check 62int __must_check
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index f956b413311e..2095917ff8c7 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -30,6 +30,10 @@
30 30
31#include <drm/drm_crtc.h> 31#include <drm/drm_crtc.h>
32 32
33int drm_atomic_helper_check_modeset(struct drm_device *dev,
34 struct drm_atomic_state *state);
35int drm_atomic_helper_check_planes(struct drm_device *dev,
36 struct drm_atomic_state *state);
33int drm_atomic_helper_check(struct drm_device *dev, 37int drm_atomic_helper_check(struct drm_device *dev,
34 struct drm_atomic_state *state); 38 struct drm_atomic_state *state);
35int drm_atomic_helper_commit(struct drm_device *dev, 39int drm_atomic_helper_commit(struct drm_device *dev,
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 291239f2fafc..6588bffb6518 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -63,8 +63,16 @@ struct drm_mode_object {
63 63
64#define DRM_OBJECT_MAX_PROPERTY 24 64#define DRM_OBJECT_MAX_PROPERTY 24
65struct drm_object_properties { 65struct drm_object_properties {
66 int count; 66 int count, atomic_count;
67 uint32_t ids[DRM_OBJECT_MAX_PROPERTY]; 67 /* NOTE: if we ever start dynamically destroying properties (ie.
68 * not at drm_mode_config_cleanup() time), then we'd have to do
69 * a better job of detaching property from mode objects to avoid
70 * dangling property pointers:
71 */
72 struct drm_property *properties[DRM_OBJECT_MAX_PROPERTY];
73 /* do not read/write values directly, but use drm_object_property_get_value()
74 * and drm_object_property_set_value():
75 */
68 uint64_t values[DRM_OBJECT_MAX_PROPERTY]; 76 uint64_t values[DRM_OBJECT_MAX_PROPERTY];
69}; 77};
70 78
@@ -237,7 +245,9 @@ struct drm_atomic_state;
237 245
238/** 246/**
239 * struct drm_crtc_state - mutable CRTC state 247 * struct drm_crtc_state - mutable CRTC state
248 * @crtc: backpointer to the CRTC
240 * @enable: whether the CRTC should be enabled, gates all other state 249 * @enable: whether the CRTC should be enabled, gates all other state
250 * @active: whether the CRTC is actively displaying (used for DPMS)
241 * @mode_changed: for use by helpers and drivers when computing state updates 251 * @mode_changed: for use by helpers and drivers when computing state updates
242 * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes 252 * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
243 * @last_vblank_count: for helpers and drivers to capture the vblank of the 253 * @last_vblank_count: for helpers and drivers to capture the vblank of the
@@ -248,9 +258,18 @@ struct drm_atomic_state;
248 * @event: optional pointer to a DRM event to signal upon completion of the 258 * @event: optional pointer to a DRM event to signal upon completion of the
249 * state update 259 * state update
250 * @state: backpointer to global drm_atomic_state 260 * @state: backpointer to global drm_atomic_state
261 *
262 * Note that the distinction between @enable and @active is rather subtile:
263 * Flipping @active while @enable is set without changing anything else may
264 * never return in a failure from the ->atomic_check callback. Userspace assumes
265 * that a DPMS On will always succeed. In other words: @enable controls resource
266 * assignment, @active controls the actual hardware state.
251 */ 267 */
252struct drm_crtc_state { 268struct drm_crtc_state {
269 struct drm_crtc *crtc;
270
253 bool enable; 271 bool enable;
272 bool active;
254 273
255 /* computed state bits used by helpers and drivers */ 274 /* computed state bits used by helpers and drivers */
256 bool planes_changed : 1; 275 bool planes_changed : 1;
@@ -292,6 +311,9 @@ struct drm_crtc_state {
292 * @atomic_duplicate_state: duplicate the atomic state for this CRTC 311 * @atomic_duplicate_state: duplicate the atomic state for this CRTC
293 * @atomic_destroy_state: destroy an atomic state for this CRTC 312 * @atomic_destroy_state: destroy an atomic state for this CRTC
294 * @atomic_set_property: set a property on an atomic state for this CRTC 313 * @atomic_set_property: set a property on an atomic state for this CRTC
314 * (do not call directly, use drm_atomic_crtc_set_property())
315 * @atomic_get_property: get a property on an atomic state for this CRTC
316 * (do not call directly, use drm_atomic_crtc_get_property())
295 * 317 *
296 * The drm_crtc_funcs structure is the central CRTC management structure 318 * The drm_crtc_funcs structure is the central CRTC management structure
297 * in the DRM. Each CRTC controls one or more connectors (note that the name 319 * in the DRM. Each CRTC controls one or more connectors (note that the name
@@ -351,6 +373,10 @@ struct drm_crtc_funcs {
351 struct drm_crtc_state *state, 373 struct drm_crtc_state *state,
352 struct drm_property *property, 374 struct drm_property *property,
353 uint64_t val); 375 uint64_t val);
376 int (*atomic_get_property)(struct drm_crtc *crtc,
377 const struct drm_crtc_state *state,
378 struct drm_property *property,
379 uint64_t *val);
354}; 380};
355 381
356/** 382/**
@@ -449,11 +475,14 @@ struct drm_crtc {
449 475
450/** 476/**
451 * struct drm_connector_state - mutable connector state 477 * struct drm_connector_state - mutable connector state
478 * @connector: backpointer to the connector
452 * @crtc: CRTC to connect connector to, NULL if disabled 479 * @crtc: CRTC to connect connector to, NULL if disabled
453 * @best_encoder: can be used by helpers and drivers to select the encoder 480 * @best_encoder: can be used by helpers and drivers to select the encoder
454 * @state: backpointer to global drm_atomic_state 481 * @state: backpointer to global drm_atomic_state
455 */ 482 */
456struct drm_connector_state { 483struct drm_connector_state {
484 struct drm_connector *connector;
485
457 struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_connector() */ 486 struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_connector() */
458 487
459 struct drm_encoder *best_encoder; 488 struct drm_encoder *best_encoder;
@@ -475,6 +504,9 @@ struct drm_connector_state {
475 * @atomic_duplicate_state: duplicate the atomic state for this connector 504 * @atomic_duplicate_state: duplicate the atomic state for this connector
476 * @atomic_destroy_state: destroy an atomic state for this connector 505 * @atomic_destroy_state: destroy an atomic state for this connector
477 * @atomic_set_property: set a property on an atomic state for this connector 506 * @atomic_set_property: set a property on an atomic state for this connector
507 * (do not call directly, use drm_atomic_connector_set_property())
508 * @atomic_get_property: get a property on an atomic state for this connector
509 * (do not call directly, use drm_atomic_connector_get_property())
478 * 510 *
479 * Each CRTC may have one or more connectors attached to it. The functions 511 * Each CRTC may have one or more connectors attached to it. The functions
480 * below allow the core DRM code to control connectors, enumerate available modes, 512 * below allow the core DRM code to control connectors, enumerate available modes,
@@ -508,6 +540,10 @@ struct drm_connector_funcs {
508 struct drm_connector_state *state, 540 struct drm_connector_state *state,
509 struct drm_property *property, 541 struct drm_property *property,
510 uint64_t val); 542 uint64_t val);
543 int (*atomic_get_property)(struct drm_connector *connector,
544 const struct drm_connector_state *state,
545 struct drm_property *property,
546 uint64_t *val);
511}; 547};
512 548
513/** 549/**
@@ -693,6 +729,7 @@ struct drm_connector {
693 729
694/** 730/**
695 * struct drm_plane_state - mutable plane state 731 * struct drm_plane_state - mutable plane state
732 * @plane: backpointer to the plane
696 * @crtc: currently bound CRTC, NULL if disabled 733 * @crtc: currently bound CRTC, NULL if disabled
697 * @fb: currently bound framebuffer 734 * @fb: currently bound framebuffer
698 * @fence: optional fence to wait for before scanning out @fb 735 * @fence: optional fence to wait for before scanning out @fb
@@ -709,6 +746,8 @@ struct drm_connector {
709 * @state: backpointer to global drm_atomic_state 746 * @state: backpointer to global drm_atomic_state
710 */ 747 */
711struct drm_plane_state { 748struct drm_plane_state {
749 struct drm_plane *plane;
750
712 struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */ 751 struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */
713 struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */ 752 struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */
714 struct fence *fence; 753 struct fence *fence;
@@ -735,6 +774,9 @@ struct drm_plane_state {
735 * @atomic_duplicate_state: duplicate the atomic state for this plane 774 * @atomic_duplicate_state: duplicate the atomic state for this plane
736 * @atomic_destroy_state: destroy an atomic state for this plane 775 * @atomic_destroy_state: destroy an atomic state for this plane
737 * @atomic_set_property: set a property on an atomic state for this plane 776 * @atomic_set_property: set a property on an atomic state for this plane
777 * (do not call directly, use drm_atomic_plane_set_property())
778 * @atomic_get_property: get a property on an atomic state for this plane
779 * (do not call directly, use drm_atomic_plane_get_property())
738 */ 780 */
739struct drm_plane_funcs { 781struct drm_plane_funcs {
740 int (*update_plane)(struct drm_plane *plane, 782 int (*update_plane)(struct drm_plane *plane,
@@ -758,6 +800,10 @@ struct drm_plane_funcs {
758 struct drm_plane_state *state, 800 struct drm_plane_state *state,
759 struct drm_property *property, 801 struct drm_property *property,
760 uint64_t val); 802 uint64_t val);
803 int (*atomic_get_property)(struct drm_plane *plane,
804 const struct drm_plane_state *state,
805 struct drm_property *property,
806 uint64_t *val);
761}; 807};
762 808
763enum drm_plane_type { 809enum drm_plane_type {
@@ -856,7 +902,7 @@ struct drm_bridge {
856/** 902/**
857 * struct struct drm_atomic_state - the global state object for atomic updates 903 * struct struct drm_atomic_state - the global state object for atomic updates
858 * @dev: parent DRM device 904 * @dev: parent DRM device
859 * @flags: state flags like async update 905 * @allow_modeset: allow full modeset
860 * @planes: pointer to array of plane pointers 906 * @planes: pointer to array of plane pointers
861 * @plane_states: pointer to array of plane states pointers 907 * @plane_states: pointer to array of plane states pointers
862 * @crtcs: pointer to array of CRTC pointers 908 * @crtcs: pointer to array of CRTC pointers
@@ -868,7 +914,7 @@ struct drm_bridge {
868 */ 914 */
869struct drm_atomic_state { 915struct drm_atomic_state {
870 struct drm_device *dev; 916 struct drm_device *dev;
871 uint32_t flags; 917 bool allow_modeset : 1;
872 struct drm_plane **planes; 918 struct drm_plane **planes;
873 struct drm_plane_state **plane_states; 919 struct drm_plane_state **plane_states;
874 struct drm_crtc **crtcs; 920 struct drm_crtc **crtcs;
@@ -1053,6 +1099,16 @@ struct drm_mode_config {
1053 struct drm_property *tile_property; 1099 struct drm_property *tile_property;
1054 struct drm_property *plane_type_property; 1100 struct drm_property *plane_type_property;
1055 struct drm_property *rotation_property; 1101 struct drm_property *rotation_property;
1102 struct drm_property *prop_src_x;
1103 struct drm_property *prop_src_y;
1104 struct drm_property *prop_src_w;
1105 struct drm_property *prop_src_h;
1106 struct drm_property *prop_crtc_x;
1107 struct drm_property *prop_crtc_y;
1108 struct drm_property *prop_crtc_w;
1109 struct drm_property *prop_crtc_h;
1110 struct drm_property *prop_fb_id;
1111 struct drm_property *prop_crtc_id;
1056 1112
1057 /* DVI-I properties */ 1113 /* DVI-I properties */
1058 struct drm_property *dvi_i_subconnector_property; 1114 struct drm_property *dvi_i_subconnector_property;
@@ -1290,6 +1346,10 @@ extern int drm_mode_create_scaling_mode_property(struct drm_device *dev);
1290extern int drm_mode_create_aspect_ratio_property(struct drm_device *dev); 1346extern int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
1291extern int drm_mode_create_dirty_info_property(struct drm_device *dev); 1347extern int drm_mode_create_dirty_info_property(struct drm_device *dev);
1292extern int drm_mode_create_suggested_offset_properties(struct drm_device *dev); 1348extern int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
1349extern bool drm_property_change_valid_get(struct drm_property *property,
1350 uint64_t value, struct drm_mode_object **ref);
1351extern void drm_property_change_valid_put(struct drm_property *property,
1352 struct drm_mode_object *ref);
1293 1353
1294extern int drm_mode_connector_attach_encoder(struct drm_connector *connector, 1354extern int drm_mode_connector_attach_encoder(struct drm_connector *connector,
1295 struct drm_encoder *encoder); 1355 struct drm_encoder *encoder);
@@ -1381,6 +1441,8 @@ extern int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
1381extern int drm_mode_plane_set_obj_prop(struct drm_plane *plane, 1441extern int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
1382 struct drm_property *property, 1442 struct drm_property *property,
1383 uint64_t value); 1443 uint64_t value);
1444extern int drm_mode_atomic_ioctl(struct drm_device *dev,
1445 void *data, struct drm_file *file_priv);
1384 1446
1385extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, 1447extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
1386 int *bpp); 1448 int *bpp);
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index b0b855613641..01b2d6d0e355 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -654,6 +654,13 @@ struct drm_get_cap {
654 */ 654 */
655#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2 655#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
656 656
657/**
658 * DRM_CLIENT_CAP_ATOMIC
659 *
660 * If set to 1, the DRM core will expose atomic properties to userspace
661 */
662#define DRM_CLIENT_CAP_ATOMIC 3
663
657/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ 664/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
658struct drm_set_client_cap { 665struct drm_set_client_cap {
659 __u64 capability; 666 __u64 capability;
@@ -777,6 +784,7 @@ struct drm_prime_handle {
777#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties) 784#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
778#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) 785#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property)
779#define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2) 786#define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2)
787#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic)
780 788
781/** 789/**
782 * Device specific ioctls should only be in their respective headers 790 * Device specific ioctls should only be in their respective headers
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index aae71cb32123..ca788e01dab2 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -272,6 +272,13 @@ struct drm_mode_get_connector {
272#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) 272#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1)
273#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2) 273#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2)
274 274
275/* the PROP_ATOMIC flag is used to hide properties from userspace that
276 * is not aware of atomic properties. This is mostly to work around
277 * older userspace (DDX drivers) that read/write each prop they find,
278 * witout being aware that this could be triggering a lengthy modeset.
279 */
280#define DRM_MODE_PROP_ATOMIC 0x80000000
281
275struct drm_mode_property_enum { 282struct drm_mode_property_enum {
276 __u64 value; 283 __u64 value;
277 char name[DRM_PROP_NAME_LEN]; 284 char name[DRM_PROP_NAME_LEN];
@@ -519,4 +526,27 @@ struct drm_mode_destroy_dumb {
519 uint32_t handle; 526 uint32_t handle;
520}; 527};
521 528
529/* page-flip flags are valid, plus: */
530#define DRM_MODE_ATOMIC_TEST_ONLY 0x0100
531#define DRM_MODE_ATOMIC_NONBLOCK 0x0200
532#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400
533
534#define DRM_MODE_ATOMIC_FLAGS (\
535 DRM_MODE_PAGE_FLIP_EVENT |\
536 DRM_MODE_PAGE_FLIP_ASYNC |\
537 DRM_MODE_ATOMIC_TEST_ONLY |\
538 DRM_MODE_ATOMIC_NONBLOCK |\
539 DRM_MODE_ATOMIC_ALLOW_MODESET)
540
541struct drm_mode_atomic {
542 __u32 flags;
543 __u32 count_objs;
544 __u64 objs_ptr;
545 __u64 count_props_ptr;
546 __u64 props_ptr;
547 __u64 prop_values_ptr;
548 __u64 reserved;
549 __u64 user_data;
550};
551
522#endif 552#endif