diff options
author | Dave Airlie <airlied@redhat.com> | 2014-12-01 17:59:34 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-12-01 17:59:34 -0500 |
commit | 9be23ae4350bfd71c0cc2ea3494671ee90e5603b (patch) | |
tree | 4233411cc12265c675125d99fb0ea03c9172423b | |
parent | 5a0e9d72136d90f5456bcc465d318f49d3f45838 (diff) | |
parent | e5b5341c28c66a122982d3d8822a4f9a0938f923 (diff) |
Merge tag 'topic/core-stuff-2014-11-28' of git://anongit.freedesktop.org/drm-intel into drm-next
So here's a pile of atomic fixes and improvements from various people.
There's still more patches in-flight, so I think I'll keep collecting them
in a separate branch.
* tag 'topic/core-stuff-2014-11-28' of git://anongit.freedesktop.org/drm-intel:
drm/atomic: clear plane's CRTC and FB when shutting down
drm: Handle atomic state properly in kms getfoo ioctl
drm: use mode_object_find helpers
drm: fix indentation
drm/msm: switch to atomic-helpers iterator macros
drm/atomic: add plane iterator macros
drm/atomic: track bitmask of planes attached to crtc
drm: Free atomic state during cleanup
drm: Make drm_atomic.h standalone includible
drm: Make drm_atomic_helper.h standalone includible
drm/plane: Add missing kerneldoc
drm/plane: Pass old state to ->atomic_update()
drm/atomic_helper: Cope with plane->crtc == NULL in disable helper
drm/atomic: Drop per-plane locking TODO
drm/atomic-helper: Skip vblank waits for unchanged fbs
drm: Document that drm_dev_alloc doesn't need a parent
-rw-r--r-- | Documentation/DocBook/drm.tmpl | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_atomic_helper.c | 77 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 75 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_drv.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_plane_helper.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_kms.h | 23 | ||||
-rw-r--r-- | include/drm/drmP.h | 2 | ||||
-rw-r--r-- | include/drm/drm_atomic.h | 6 | ||||
-rw-r--r-- | include/drm/drm_atomic_helper.h | 26 | ||||
-rw-r--r-- | include/drm/drm_crtc.h | 27 | ||||
-rw-r--r-- | include/drm/drm_plane_helper.h | 7 |
16 files changed, 226 insertions, 75 deletions
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 8c54f9a393cf..3789f2db3c21 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl | |||
@@ -2343,6 +2343,7 @@ void intel_crt_init(struct drm_device *dev) | |||
2343 | <title>Atomic State Reset and Initialization</title> | 2343 | <title>Atomic State Reset and Initialization</title> |
2344 | !Pdrivers/gpu/drm/drm_atomic_helper.c atomic state reset and initialization | 2344 | !Pdrivers/gpu/drm/drm_atomic_helper.c atomic state reset and initialization |
2345 | </sect3> | 2345 | </sect3> |
2346 | !Iinclude/drm/drm_atomic_helper.h | ||
2346 | !Edrivers/gpu/drm/drm_atomic_helper.c | 2347 | !Edrivers/gpu/drm/drm_atomic_helper.c |
2347 | </sect2> | 2348 | </sect2> |
2348 | <sect2> | 2349 | <sect2> |
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index d3b46746b611..ff5f034cc405 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c | |||
@@ -243,12 +243,6 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state, | |||
243 | if (state->plane_states[index]) | 243 | if (state->plane_states[index]) |
244 | return state->plane_states[index]; | 244 | return state->plane_states[index]; |
245 | 245 | ||
246 | /* | ||
247 | * TODO: We currently don't have per-plane mutexes. So instead of trying | ||
248 | * crazy tricks with deferring plane->crtc and hoping for the best just | ||
249 | * grab all crtc locks. Once we have per-plane locks we must update this | ||
250 | * to only take the plane mutex. | ||
251 | */ | ||
252 | ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx); | 246 | ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx); |
253 | if (ret) | 247 | if (ret) |
254 | return ERR_PTR(ret); | 248 | return ERR_PTR(ret); |
@@ -350,7 +344,8 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state); | |||
350 | 344 | ||
351 | /** | 345 | /** |
352 | * drm_atomic_set_crtc_for_plane - set crtc for plane | 346 | * drm_atomic_set_crtc_for_plane - set crtc for plane |
353 | * @plane_state: atomic state object for the plane | 347 | * @state: the incoming atomic state |
348 | * @plane: the plane whose incoming state to update | ||
354 | * @crtc: crtc to use for the plane | 349 | * @crtc: crtc to use for the plane |
355 | * | 350 | * |
356 | * Changing the assigned crtc for a plane requires us to grab the lock and state | 351 | * Changing the assigned crtc for a plane requires us to grab the lock and state |
@@ -363,20 +358,35 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state); | |||
363 | * sequence must be restarted. All other errors are fatal. | 358 | * sequence must be restarted. All other errors are fatal. |
364 | */ | 359 | */ |
365 | int | 360 | int |
366 | drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, | 361 | drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state, |
367 | struct drm_crtc *crtc) | 362 | struct drm_plane *plane, struct drm_crtc *crtc) |
368 | { | 363 | { |
364 | struct drm_plane_state *plane_state = | ||
365 | drm_atomic_get_plane_state(state, plane); | ||
369 | struct drm_crtc_state *crtc_state; | 366 | struct drm_crtc_state *crtc_state; |
370 | 367 | ||
368 | if (WARN_ON(IS_ERR(plane_state))) | ||
369 | return PTR_ERR(plane_state); | ||
370 | |||
371 | if (plane_state->crtc) { | ||
372 | crtc_state = drm_atomic_get_crtc_state(plane_state->state, | ||
373 | plane_state->crtc); | ||
374 | if (WARN_ON(IS_ERR(crtc_state))) | ||
375 | return PTR_ERR(crtc_state); | ||
376 | |||
377 | crtc_state->plane_mask &= ~(1 << drm_plane_index(plane)); | ||
378 | } | ||
379 | |||
380 | plane_state->crtc = crtc; | ||
381 | |||
371 | if (crtc) { | 382 | if (crtc) { |
372 | crtc_state = drm_atomic_get_crtc_state(plane_state->state, | 383 | crtc_state = drm_atomic_get_crtc_state(plane_state->state, |
373 | crtc); | 384 | crtc); |
374 | if (IS_ERR(crtc_state)) | 385 | if (IS_ERR(crtc_state)) |
375 | return PTR_ERR(crtc_state); | 386 | return PTR_ERR(crtc_state); |
387 | crtc_state->plane_mask |= (1 << drm_plane_index(plane)); | ||
376 | } | 388 | } |
377 | 389 | ||
378 | plane_state->crtc = crtc; | ||
379 | |||
380 | if (crtc) | 390 | if (crtc) |
381 | DRM_DEBUG_KMS("Link plane state %p to [CRTC:%d]\n", | 391 | DRM_DEBUG_KMS("Link plane state %p to [CRTC:%d]\n", |
382 | plane_state, crtc->base.id); | 392 | plane_state, crtc->base.id); |
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index a17b8e9c0a81..4a78a773151c 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
@@ -751,6 +751,33 @@ static void wait_for_fences(struct drm_device *dev, | |||
751 | } | 751 | } |
752 | } | 752 | } |
753 | 753 | ||
754 | static bool framebuffer_changed(struct drm_device *dev, | ||
755 | struct drm_atomic_state *old_state, | ||
756 | struct drm_crtc *crtc) | ||
757 | { | ||
758 | struct drm_plane *plane; | ||
759 | struct drm_plane_state *old_plane_state; | ||
760 | int nplanes = old_state->dev->mode_config.num_total_plane; | ||
761 | int i; | ||
762 | |||
763 | for (i = 0; i < nplanes; i++) { | ||
764 | plane = old_state->planes[i]; | ||
765 | old_plane_state = old_state->plane_states[i]; | ||
766 | |||
767 | if (!plane) | ||
768 | continue; | ||
769 | |||
770 | if (plane->state->crtc != crtc && | ||
771 | old_plane_state->crtc != crtc) | ||
772 | continue; | ||
773 | |||
774 | if (plane->state->fb != old_plane_state->fb) | ||
775 | return true; | ||
776 | } | ||
777 | |||
778 | return false; | ||
779 | } | ||
780 | |||
754 | /** | 781 | /** |
755 | * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs | 782 | * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs |
756 | * @dev: DRM device | 783 | * @dev: DRM device |
@@ -758,7 +785,9 @@ static void wait_for_fences(struct drm_device *dev, | |||
758 | * | 785 | * |
759 | * Helper to, after atomic commit, wait for vblanks on all effected | 786 | * Helper to, after atomic commit, wait for vblanks on all effected |
760 | * crtcs (ie. before cleaning up old framebuffers using | 787 | * crtcs (ie. before cleaning up old framebuffers using |
761 | * drm_atomic_helper_cleanup_planes()) | 788 | * drm_atomic_helper_cleanup_planes()). It will only wait on crtcs where the |
789 | * framebuffers have actually changed to optimize for the legacy cursor and | ||
790 | * plane update use-case. | ||
762 | */ | 791 | */ |
763 | void | 792 | void |
764 | drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, | 793 | drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, |
@@ -784,6 +813,9 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, | |||
784 | if (!crtc->state->enable) | 813 | if (!crtc->state->enable) |
785 | continue; | 814 | continue; |
786 | 815 | ||
816 | if (!framebuffer_changed(dev, old_state, crtc)) | ||
817 | continue; | ||
818 | |||
787 | ret = drm_crtc_vblank_get(crtc); | 819 | ret = drm_crtc_vblank_get(crtc); |
788 | if (ret != 0) | 820 | if (ret != 0) |
789 | continue; | 821 | continue; |
@@ -1014,6 +1046,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, | |||
1014 | for (i = 0; i < nplanes; i++) { | 1046 | for (i = 0; i < nplanes; i++) { |
1015 | struct drm_plane_helper_funcs *funcs; | 1047 | struct drm_plane_helper_funcs *funcs; |
1016 | struct drm_plane *plane = old_state->planes[i]; | 1048 | struct drm_plane *plane = old_state->planes[i]; |
1049 | struct drm_plane_state *old_plane_state; | ||
1017 | 1050 | ||
1018 | if (!plane) | 1051 | if (!plane) |
1019 | continue; | 1052 | continue; |
@@ -1023,7 +1056,9 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, | |||
1023 | if (!funcs || !funcs->atomic_update) | 1056 | if (!funcs || !funcs->atomic_update) |
1024 | continue; | 1057 | continue; |
1025 | 1058 | ||
1026 | funcs->atomic_update(plane); | 1059 | old_plane_state = old_state->plane_states[i]; |
1060 | |||
1061 | funcs->atomic_update(plane, old_plane_state); | ||
1027 | } | 1062 | } |
1028 | 1063 | ||
1029 | for (i = 0; i < ncrtcs; i++) { | 1064 | for (i = 0; i < ncrtcs; i++) { |
@@ -1187,7 +1222,7 @@ retry: | |||
1187 | goto fail; | 1222 | goto fail; |
1188 | } | 1223 | } |
1189 | 1224 | ||
1190 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); | 1225 | ret = drm_atomic_set_crtc_for_plane(state, plane, crtc); |
1191 | if (ret != 0) | 1226 | if (ret != 0) |
1192 | goto fail; | 1227 | goto fail; |
1193 | drm_atomic_set_fb_for_plane(plane_state, fb); | 1228 | drm_atomic_set_fb_for_plane(plane_state, fb); |
@@ -1243,6 +1278,17 @@ int drm_atomic_helper_disable_plane(struct drm_plane *plane) | |||
1243 | struct drm_plane_state *plane_state; | 1278 | struct drm_plane_state *plane_state; |
1244 | int ret = 0; | 1279 | int ret = 0; |
1245 | 1280 | ||
1281 | /* | ||
1282 | * FIXME: Without plane->crtc set we can't get at the implicit legacy | ||
1283 | * acquire context. The real fix will be to wire the acquire ctx through | ||
1284 | * everywhere we need it, but meanwhile prevent chaos by just skipping | ||
1285 | * this noop. The critical case is the cursor ioctls which a) only grab | ||
1286 | * crtc/cursor-plane locks (so we need the crtc to get at the right | ||
1287 | * acquire context) and b) can try to disable the plane multiple times. | ||
1288 | */ | ||
1289 | if (!plane->crtc) | ||
1290 | return 0; | ||
1291 | |||
1246 | state = drm_atomic_state_alloc(plane->dev); | 1292 | state = drm_atomic_state_alloc(plane->dev); |
1247 | if (!state) | 1293 | if (!state) |
1248 | return -ENOMEM; | 1294 | return -ENOMEM; |
@@ -1255,7 +1301,7 @@ retry: | |||
1255 | goto fail; | 1301 | goto fail; |
1256 | } | 1302 | } |
1257 | 1303 | ||
1258 | ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); | 1304 | ret = drm_atomic_set_crtc_for_plane(state, plane, NULL); |
1259 | if (ret != 0) | 1305 | if (ret != 0) |
1260 | goto fail; | 1306 | goto fail; |
1261 | drm_atomic_set_fb_for_plane(plane_state, NULL); | 1307 | drm_atomic_set_fb_for_plane(plane_state, NULL); |
@@ -1406,11 +1452,24 @@ retry: | |||
1406 | goto fail; | 1452 | goto fail; |
1407 | } | 1453 | } |
1408 | 1454 | ||
1455 | primary_state = drm_atomic_get_plane_state(state, crtc->primary); | ||
1456 | if (IS_ERR(primary_state)) { | ||
1457 | ret = PTR_ERR(primary_state); | ||
1458 | goto fail; | ||
1459 | } | ||
1460 | |||
1409 | if (!set->mode) { | 1461 | if (!set->mode) { |
1410 | WARN_ON(set->fb); | 1462 | WARN_ON(set->fb); |
1411 | WARN_ON(set->num_connectors); | 1463 | WARN_ON(set->num_connectors); |
1412 | 1464 | ||
1413 | crtc_state->enable = false; | 1465 | crtc_state->enable = false; |
1466 | |||
1467 | ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, NULL); | ||
1468 | if (ret != 0) | ||
1469 | goto fail; | ||
1470 | |||
1471 | drm_atomic_set_fb_for_plane(primary_state, NULL); | ||
1472 | |||
1414 | goto commit; | 1473 | goto commit; |
1415 | } | 1474 | } |
1416 | 1475 | ||
@@ -1420,13 +1479,7 @@ retry: | |||
1420 | crtc_state->enable = true; | 1479 | crtc_state->enable = true; |
1421 | drm_mode_copy(&crtc_state->mode, set->mode); | 1480 | drm_mode_copy(&crtc_state->mode, set->mode); |
1422 | 1481 | ||
1423 | primary_state = drm_atomic_get_plane_state(state, crtc->primary); | 1482 | ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, crtc); |
1424 | if (IS_ERR(primary_state)) { | ||
1425 | ret = PTR_ERR(primary_state); | ||
1426 | goto fail; | ||
1427 | } | ||
1428 | |||
1429 | ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); | ||
1430 | if (ret != 0) | 1483 | if (ret != 0) |
1431 | goto fail; | 1484 | goto fail; |
1432 | drm_atomic_set_fb_for_plane(primary_state, set->fb); | 1485 | drm_atomic_set_fb_for_plane(primary_state, set->fb); |
@@ -1698,7 +1751,7 @@ retry: | |||
1698 | goto fail; | 1751 | goto fail; |
1699 | } | 1752 | } |
1700 | 1753 | ||
1701 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); | 1754 | ret = drm_atomic_set_crtc_for_plane(state, plane, crtc); |
1702 | if (ret != 0) | 1755 | if (ret != 0) |
1703 | goto fail; | 1756 | goto fail; |
1704 | drm_atomic_set_fb_for_plane(plane_state, fb); | 1757 | drm_atomic_set_fb_for_plane(plane_state, fb); |
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 589a921d4313..de79283eaea7 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -721,6 +721,10 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) | |||
721 | drm_mode_object_put(dev, &crtc->base); | 721 | drm_mode_object_put(dev, &crtc->base); |
722 | list_del(&crtc->head); | 722 | list_del(&crtc->head); |
723 | dev->mode_config.num_crtc--; | 723 | dev->mode_config.num_crtc--; |
724 | |||
725 | WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state); | ||
726 | if (crtc->state && crtc->funcs->atomic_destroy_state) | ||
727 | crtc->funcs->atomic_destroy_state(crtc, crtc->state); | ||
724 | } | 728 | } |
725 | EXPORT_SYMBOL(drm_crtc_cleanup); | 729 | EXPORT_SYMBOL(drm_crtc_cleanup); |
726 | 730 | ||
@@ -918,6 +922,11 @@ void drm_connector_cleanup(struct drm_connector *connector) | |||
918 | connector->name = NULL; | 922 | connector->name = NULL; |
919 | list_del(&connector->head); | 923 | list_del(&connector->head); |
920 | dev->mode_config.num_connector--; | 924 | dev->mode_config.num_connector--; |
925 | |||
926 | WARN_ON(connector->state && !connector->funcs->atomic_destroy_state); | ||
927 | if (connector->state && connector->funcs->atomic_destroy_state) | ||
928 | connector->funcs->atomic_destroy_state(connector, | ||
929 | connector->state); | ||
921 | } | 930 | } |
922 | EXPORT_SYMBOL(drm_connector_cleanup); | 931 | EXPORT_SYMBOL(drm_connector_cleanup); |
923 | 932 | ||
@@ -1244,6 +1253,10 @@ void drm_plane_cleanup(struct drm_plane *plane) | |||
1244 | if (plane->type == DRM_PLANE_TYPE_OVERLAY) | 1253 | if (plane->type == DRM_PLANE_TYPE_OVERLAY) |
1245 | dev->mode_config.num_overlay_plane--; | 1254 | dev->mode_config.num_overlay_plane--; |
1246 | drm_modeset_unlock_all(dev); | 1255 | drm_modeset_unlock_all(dev); |
1256 | |||
1257 | WARN_ON(plane->state && !plane->funcs->atomic_destroy_state); | ||
1258 | if (plane->state && plane->funcs->atomic_destroy_state) | ||
1259 | plane->funcs->atomic_destroy_state(plane, plane->state); | ||
1247 | } | 1260 | } |
1248 | EXPORT_SYMBOL(drm_plane_cleanup); | 1261 | EXPORT_SYMBOL(drm_plane_cleanup); |
1249 | 1262 | ||
@@ -1955,6 +1968,15 @@ static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode, | |||
1955 | return true; | 1968 | return true; |
1956 | } | 1969 | } |
1957 | 1970 | ||
1971 | static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector) | ||
1972 | { | ||
1973 | /* For atomic drivers only state objects are synchronously updated and | ||
1974 | * protected by modeset locks, so check those first. */ | ||
1975 | if (connector->state) | ||
1976 | return connector->state->best_encoder; | ||
1977 | return connector->encoder; | ||
1978 | } | ||
1979 | |||
1958 | /** | 1980 | /** |
1959 | * drm_mode_getconnector - get connector configuration | 1981 | * drm_mode_getconnector - get connector configuration |
1960 | * @dev: drm device for the ioctl | 1982 | * @dev: drm device for the ioctl |
@@ -1973,6 +1995,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
1973 | { | 1995 | { |
1974 | struct drm_mode_get_connector *out_resp = data; | 1996 | struct drm_mode_get_connector *out_resp = data; |
1975 | struct drm_connector *connector; | 1997 | struct drm_connector *connector; |
1998 | struct drm_encoder *encoder; | ||
1976 | struct drm_display_mode *mode; | 1999 | struct drm_display_mode *mode; |
1977 | int mode_count = 0; | 2000 | int mode_count = 0; |
1978 | int props_count = 0; | 2001 | int props_count = 0; |
@@ -2028,8 +2051,10 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
2028 | out_resp->subpixel = connector->display_info.subpixel_order; | 2051 | out_resp->subpixel = connector->display_info.subpixel_order; |
2029 | out_resp->connection = connector->status; | 2052 | out_resp->connection = connector->status; |
2030 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); | 2053 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
2031 | if (connector->encoder) | 2054 | |
2032 | out_resp->encoder_id = connector->encoder->base.id; | 2055 | encoder = drm_connector_get_encoder(connector); |
2056 | if (encoder) | ||
2057 | out_resp->encoder_id = encoder->base.id; | ||
2033 | else | 2058 | else |
2034 | out_resp->encoder_id = 0; | 2059 | out_resp->encoder_id = 0; |
2035 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | 2060 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
@@ -2099,6 +2124,33 @@ out: | |||
2099 | return ret; | 2124 | return ret; |
2100 | } | 2125 | } |
2101 | 2126 | ||
2127 | static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder) | ||
2128 | { | ||
2129 | struct drm_connector *connector; | ||
2130 | struct drm_device *dev = encoder->dev; | ||
2131 | bool uses_atomic = false; | ||
2132 | |||
2133 | /* For atomic drivers only state objects are synchronously updated and | ||
2134 | * protected by modeset locks, so check those first. */ | ||
2135 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
2136 | if (!connector->state) | ||
2137 | continue; | ||
2138 | |||
2139 | uses_atomic = true; | ||
2140 | |||
2141 | if (connector->state->best_encoder != encoder) | ||
2142 | continue; | ||
2143 | |||
2144 | return connector->state->crtc; | ||
2145 | } | ||
2146 | |||
2147 | /* Don't return stale data (e.g. pending async disable). */ | ||
2148 | if (uses_atomic) | ||
2149 | return NULL; | ||
2150 | |||
2151 | return encoder->crtc; | ||
2152 | } | ||
2153 | |||
2102 | /** | 2154 | /** |
2103 | * drm_mode_getencoder - get encoder configuration | 2155 | * drm_mode_getencoder - get encoder configuration |
2104 | * @dev: drm device for the ioctl | 2156 | * @dev: drm device for the ioctl |
@@ -2117,6 +2169,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, | |||
2117 | { | 2169 | { |
2118 | struct drm_mode_get_encoder *enc_resp = data; | 2170 | struct drm_mode_get_encoder *enc_resp = data; |
2119 | struct drm_encoder *encoder; | 2171 | struct drm_encoder *encoder; |
2172 | struct drm_crtc *crtc; | ||
2120 | 2173 | ||
2121 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 2174 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2122 | return -EINVAL; | 2175 | return -EINVAL; |
@@ -2126,7 +2179,10 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, | |||
2126 | return -ENOENT; | 2179 | return -ENOENT; |
2127 | 2180 | ||
2128 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); | 2181 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
2129 | if (encoder->crtc) | 2182 | crtc = drm_encoder_get_crtc(encoder); |
2183 | if (crtc) | ||
2184 | enc_resp->crtc_id = crtc->base.id; | ||
2185 | else if (encoder->crtc) | ||
2130 | enc_resp->crtc_id = encoder->crtc->base.id; | 2186 | enc_resp->crtc_id = encoder->crtc->base.id; |
2131 | else | 2187 | else |
2132 | enc_resp->crtc_id = 0; | 2188 | enc_resp->crtc_id = 0; |
@@ -2392,7 +2448,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
2392 | struct drm_file *file_priv) | 2448 | struct drm_file *file_priv) |
2393 | { | 2449 | { |
2394 | struct drm_mode_set_plane *plane_req = data; | 2450 | struct drm_mode_set_plane *plane_req = data; |
2395 | struct drm_mode_object *obj; | ||
2396 | struct drm_plane *plane; | 2451 | struct drm_plane *plane; |
2397 | struct drm_crtc *crtc = NULL; | 2452 | struct drm_crtc *crtc = NULL; |
2398 | struct drm_framebuffer *fb = NULL; | 2453 | struct drm_framebuffer *fb = NULL; |
@@ -2415,14 +2470,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
2415 | * First, find the plane, crtc, and fb objects. If not available, | 2470 | * First, find the plane, crtc, and fb objects. If not available, |
2416 | * we don't bother to call the driver. | 2471 | * we don't bother to call the driver. |
2417 | */ | 2472 | */ |
2418 | obj = drm_mode_object_find(dev, plane_req->plane_id, | 2473 | plane = drm_plane_find(dev, plane_req->plane_id); |
2419 | DRM_MODE_OBJECT_PLANE); | 2474 | if (!plane) { |
2420 | if (!obj) { | ||
2421 | DRM_DEBUG_KMS("Unknown plane ID %d\n", | 2475 | DRM_DEBUG_KMS("Unknown plane ID %d\n", |
2422 | plane_req->plane_id); | 2476 | plane_req->plane_id); |
2423 | return -ENOENT; | 2477 | return -ENOENT; |
2424 | } | 2478 | } |
2425 | plane = obj_to_plane(obj); | ||
2426 | 2479 | ||
2427 | if (plane_req->fb_id) { | 2480 | if (plane_req->fb_id) { |
2428 | fb = drm_framebuffer_lookup(dev, plane_req->fb_id); | 2481 | fb = drm_framebuffer_lookup(dev, plane_req->fb_id); |
@@ -2432,14 +2485,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
2432 | return -ENOENT; | 2485 | return -ENOENT; |
2433 | } | 2486 | } |
2434 | 2487 | ||
2435 | obj = drm_mode_object_find(dev, plane_req->crtc_id, | 2488 | crtc = drm_crtc_find(dev, plane_req->crtc_id); |
2436 | DRM_MODE_OBJECT_CRTC); | 2489 | if (!crtc) { |
2437 | if (!obj) { | ||
2438 | DRM_DEBUG_KMS("Unknown crtc ID %d\n", | 2490 | DRM_DEBUG_KMS("Unknown crtc ID %d\n", |
2439 | plane_req->crtc_id); | 2491 | plane_req->crtc_id); |
2440 | return -ENOENT; | 2492 | return -ENOENT; |
2441 | } | 2493 | } |
2442 | crtc = obj_to_crtc(obj); | ||
2443 | } | 2494 | } |
2444 | 2495 | ||
2445 | /* | 2496 | /* |
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 2e5c7d941313..4f41377b0b80 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
@@ -535,6 +535,8 @@ static void drm_fs_inode_free(struct inode *inode) | |||
535 | * The initial ref-count of the object is 1. Use drm_dev_ref() and | 535 | * The initial ref-count of the object is 1. Use drm_dev_ref() and |
536 | * drm_dev_unref() to take and drop further ref-counts. | 536 | * drm_dev_unref() to take and drop further ref-counts. |
537 | * | 537 | * |
538 | * Note that for purely virtual devices @parent can be NULL. | ||
539 | * | ||
538 | * RETURNS: | 540 | * RETURNS: |
539 | * Pointer to new DRM device, or NULL if out of memory. | 541 | * Pointer to new DRM device, or NULL if out of memory. |
540 | */ | 542 | */ |
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 93c6533c25da..18a1ac6ac22f 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c | |||
@@ -443,7 +443,7 @@ int drm_plane_helper_commit(struct drm_plane *plane, | |||
443 | crtc_funcs[i]->atomic_begin(crtc[i]); | 443 | crtc_funcs[i]->atomic_begin(crtc[i]); |
444 | } | 444 | } |
445 | 445 | ||
446 | plane_funcs->atomic_update(plane); | 446 | plane_funcs->atomic_update(plane, plane_state); |
447 | 447 | ||
448 | for (i = 0; i < 2; i++) { | 448 | for (i = 0; i < 2; i++) { |
449 | if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush) | 449 | if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush) |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 6781aa994613..a7672e100d8b 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | |||
@@ -84,7 +84,7 @@ static void crtc_flush(struct drm_crtc *crtc) | |||
84 | struct drm_plane *plane; | 84 | struct drm_plane *plane; |
85 | uint32_t flush = 0; | 85 | uint32_t flush = 0; |
86 | 86 | ||
87 | for_each_plane_on_crtc(crtc, plane) { | 87 | drm_atomic_crtc_for_each_plane(plane, crtc) { |
88 | enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); | 88 | enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); |
89 | flush |= pipe2flush(pipe_id); | 89 | flush |= pipe2flush(pipe_id); |
90 | } | 90 | } |
@@ -197,7 +197,7 @@ static void setup_mixer(struct mdp4_kms *mdp4_kms) | |||
197 | struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); | 197 | struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); |
198 | struct drm_plane *plane; | 198 | struct drm_plane *plane; |
199 | 199 | ||
200 | for_each_plane_on_crtc(crtc, plane) { | 200 | drm_atomic_crtc_for_each_plane(plane, crtc) { |
201 | enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); | 201 | enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); |
202 | int idx = idxs[pipe_id]; | 202 | int idx = idxs[pipe_id]; |
203 | mixer_cfg = mixercfg(mixer_cfg, mdp4_crtc->mixer, | 203 | mixer_cfg = mixercfg(mixer_cfg, mdp4_crtc->mixer, |
@@ -221,7 +221,7 @@ static void blend_setup(struct drm_crtc *crtc) | |||
221 | mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0); | 221 | mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0); |
222 | mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0); | 222 | mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0); |
223 | 223 | ||
224 | for_each_plane_on_crtc(crtc, plane) { | 224 | drm_atomic_crtc_for_each_plane(plane, crtc) { |
225 | enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); | 225 | enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); |
226 | int idx = idxs[pipe_id]; | 226 | int idx = idxs[pipe_id]; |
227 | if (idx > 0) { | 227 | if (idx > 0) { |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index 76d0a40c7138..1e5ebe83647d 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | |||
@@ -107,7 +107,8 @@ static int mdp4_plane_atomic_check(struct drm_plane *plane, | |||
107 | return 0; | 107 | return 0; |
108 | } | 108 | } |
109 | 109 | ||
110 | static void mdp4_plane_atomic_update(struct drm_plane *plane) | 110 | static void mdp4_plane_atomic_update(struct drm_plane *plane, |
111 | struct drm_plane_state *old_state) | ||
111 | { | 112 | { |
112 | struct drm_plane_state *state = plane->state; | 113 | struct drm_plane_state *state = plane->state; |
113 | int ret; | 114 | int ret; |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 0598bdea4ff4..0e9a2e3a82d7 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | |||
@@ -91,7 +91,7 @@ static void crtc_flush_all(struct drm_crtc *crtc) | |||
91 | if (!mdp5_crtc->ctl) | 91 | if (!mdp5_crtc->ctl) |
92 | return; | 92 | return; |
93 | 93 | ||
94 | for_each_plane_on_crtc(crtc, plane) { | 94 | drm_atomic_crtc_for_each_plane(plane, crtc) { |
95 | flush_mask |= mdp5_plane_get_flush(plane); | 95 | flush_mask |= mdp5_plane_get_flush(plane); |
96 | } | 96 | } |
97 | flush_mask |= mdp5_ctl_get_flush(mdp5_crtc->ctl); | 97 | flush_mask |= mdp5_ctl_get_flush(mdp5_crtc->ctl); |
@@ -124,8 +124,9 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file) | |||
124 | } | 124 | } |
125 | spin_unlock_irqrestore(&dev->event_lock, flags); | 125 | spin_unlock_irqrestore(&dev->event_lock, flags); |
126 | 126 | ||
127 | for_each_plane_on_crtc(crtc, plane) | 127 | drm_atomic_crtc_for_each_plane(plane, crtc) { |
128 | mdp5_plane_complete_flip(plane); | 128 | mdp5_plane_complete_flip(plane); |
129 | } | ||
129 | } | 130 | } |
130 | 131 | ||
131 | static void mdp5_crtc_destroy(struct drm_crtc *crtc) | 132 | static void mdp5_crtc_destroy(struct drm_crtc *crtc) |
@@ -195,7 +196,7 @@ static void blend_setup(struct drm_crtc *crtc) | |||
195 | if (!mdp5_crtc->ctl) | 196 | if (!mdp5_crtc->ctl) |
196 | goto out; | 197 | goto out; |
197 | 198 | ||
198 | for_each_plane_on_crtc(crtc, plane) { | 199 | drm_atomic_crtc_for_each_plane(plane, crtc) { |
199 | enum mdp_mixer_stage_id stage = | 200 | enum mdp_mixer_stage_id stage = |
200 | to_mdp5_plane_state(plane->state)->stage; | 201 | to_mdp5_plane_state(plane->state)->stage; |
201 | 202 | ||
@@ -317,7 +318,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, | |||
317 | /* verify that there are not too many planes attached to crtc | 318 | /* verify that there are not too many planes attached to crtc |
318 | * and that we don't have conflicting mixer stages: | 319 | * and that we don't have conflicting mixer stages: |
319 | */ | 320 | */ |
320 | for_each_pending_plane_on_crtc(state->state, crtc, plane) { | 321 | drm_atomic_crtc_state_for_each_plane(plane, state) { |
321 | struct drm_plane_state *pstate; | 322 | struct drm_plane_state *pstate; |
322 | 323 | ||
323 | if (cnt >= ARRAY_SIZE(pstates)) { | 324 | if (cnt >= ARRAY_SIZE(pstates)) { |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 533df7caa310..26e5fdea6594 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | |||
@@ -213,7 +213,8 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane, | |||
213 | return 0; | 213 | return 0; |
214 | } | 214 | } |
215 | 215 | ||
216 | static void mdp5_plane_atomic_update(struct drm_plane *plane) | 216 | static void mdp5_plane_atomic_update(struct drm_plane *plane, |
217 | struct drm_plane_state *old_state) | ||
217 | { | 218 | { |
218 | struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); | 219 | struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); |
219 | struct drm_plane_state *state = plane->state; | 220 | struct drm_plane_state *state = plane->state; |
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 7fb4876388e7..06437745bc2c 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h | |||
@@ -65,27 +65,4 @@ static inline void msm_kms_init(struct msm_kms *kms, | |||
65 | struct msm_kms *mdp4_kms_init(struct drm_device *dev); | 65 | struct msm_kms *mdp4_kms_init(struct drm_device *dev); |
66 | struct msm_kms *mdp5_kms_init(struct drm_device *dev); | 66 | struct msm_kms *mdp5_kms_init(struct drm_device *dev); |
67 | 67 | ||
68 | /* TODO move these helper iterator macro somewhere common: */ | ||
69 | #define for_each_plane_on_crtc(_crtc, _plane) \ | ||
70 | list_for_each_entry((_plane), &(_crtc)->dev->mode_config.plane_list, head) \ | ||
71 | if ((_plane)->state->crtc == (_crtc)) | ||
72 | |||
73 | static inline bool | ||
74 | __plane_will_be_attached_to_crtc(struct drm_atomic_state *state, | ||
75 | struct drm_plane *plane, struct drm_crtc *crtc) | ||
76 | { | ||
77 | int idx = drm_plane_index(plane); | ||
78 | |||
79 | /* if plane is modified in incoming state, use the new state: */ | ||
80 | if (state->plane_states[idx]) | ||
81 | return state->plane_states[idx]->crtc == crtc; | ||
82 | |||
83 | /* otherwise, current state: */ | ||
84 | return plane->state->crtc == crtc; | ||
85 | } | ||
86 | |||
87 | #define for_each_pending_plane_on_crtc(_state, _crtc, _plane) \ | ||
88 | list_for_each_entry((_plane), &(_crtc)->dev->mode_config.plane_list, head) \ | ||
89 | if (__plane_will_be_attached_to_crtc((_state), (_plane), (_crtc))) | ||
90 | |||
91 | #endif /* __MSM_KMS_H__ */ | 68 | #endif /* __MSM_KMS_H__ */ |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index be776fb2db18..8ba35c622e22 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -809,7 +809,7 @@ struct drm_device { | |||
809 | struct drm_local_map *agp_buffer_map; | 809 | struct drm_local_map *agp_buffer_map; |
810 | unsigned int agp_buffer_token; | 810 | unsigned int agp_buffer_token; |
811 | 811 | ||
812 | struct drm_mode_config mode_config; /**< Current mode config */ | 812 | struct drm_mode_config mode_config; /**< Current mode config */ |
813 | 813 | ||
814 | /** \name GEM information */ | 814 | /** \name GEM information */ |
815 | /*@{ */ | 815 | /*@{ */ |
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 9d919168bc11..ad2229574dd9 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h | |||
@@ -28,6 +28,8 @@ | |||
28 | #ifndef DRM_ATOMIC_H_ | 28 | #ifndef DRM_ATOMIC_H_ |
29 | #define DRM_ATOMIC_H_ | 29 | #define DRM_ATOMIC_H_ |
30 | 30 | ||
31 | #include <drm/drm_crtc.h> | ||
32 | |||
31 | struct drm_atomic_state * __must_check | 33 | struct drm_atomic_state * __must_check |
32 | drm_atomic_state_alloc(struct drm_device *dev); | 34 | drm_atomic_state_alloc(struct drm_device *dev); |
33 | void drm_atomic_state_clear(struct drm_atomic_state *state); | 35 | void drm_atomic_state_clear(struct drm_atomic_state *state); |
@@ -44,8 +46,8 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, | |||
44 | struct drm_connector *connector); | 46 | struct drm_connector *connector); |
45 | 47 | ||
46 | int __must_check | 48 | int __must_check |
47 | drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, | 49 | drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state, |
48 | struct drm_crtc *crtc); | 50 | struct drm_plane *plane, struct drm_crtc *crtc); |
49 | void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, | 51 | void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, |
50 | struct drm_framebuffer *fb); | 52 | struct drm_framebuffer *fb); |
51 | int __must_check | 53 | int __must_check |
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 64b4e91b93bc..f956b413311e 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h | |||
@@ -28,6 +28,8 @@ | |||
28 | #ifndef DRM_ATOMIC_HELPER_H_ | 28 | #ifndef DRM_ATOMIC_HELPER_H_ |
29 | #define DRM_ATOMIC_HELPER_H_ | 29 | #define DRM_ATOMIC_HELPER_H_ |
30 | 30 | ||
31 | #include <drm/drm_crtc.h> | ||
32 | |||
31 | int drm_atomic_helper_check(struct drm_device *dev, | 33 | int drm_atomic_helper_check(struct drm_device *dev, |
32 | struct drm_atomic_state *state); | 34 | struct drm_atomic_state *state); |
33 | int drm_atomic_helper_commit(struct drm_device *dev, | 35 | int drm_atomic_helper_commit(struct drm_device *dev, |
@@ -96,5 +98,29 @@ drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); | |||
96 | void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, | 98 | void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, |
97 | struct drm_connector_state *state); | 99 | struct drm_connector_state *state); |
98 | 100 | ||
101 | /** | ||
102 | * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC | ||
103 | * @plane: the loop cursor | ||
104 | * @crtc: the crtc whose planes are iterated | ||
105 | * | ||
106 | * This iterates over the current state, useful (for example) when applying | ||
107 | * atomic state after it has been checked and swapped. To iterate over the | ||
108 | * planes which *will* be attached (for ->atomic_check()) see | ||
109 | * drm_crtc_for_each_pending_plane() | ||
110 | */ | ||
111 | #define drm_atomic_crtc_for_each_plane(plane, crtc) \ | ||
112 | drm_for_each_plane_mask(plane, (crtc)->dev, (crtc)->state->plane_mask) | ||
113 | |||
114 | /** | ||
115 | * drm_crtc_atomic_state_for_each_plane - iterate over attached planes in new state | ||
116 | * @plane: the loop cursor | ||
117 | * @crtc_state: the incoming crtc-state | ||
118 | * | ||
119 | * Similar to drm_crtc_for_each_plane(), but iterates the planes that will be | ||
120 | * attached if the specified state is applied. Useful during (for example) | ||
121 | * ->atomic_check() operations, to validate the incoming state | ||
122 | */ | ||
123 | #define drm_atomic_crtc_state_for_each_plane(plane, crtc_state) \ | ||
124 | drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask) | ||
99 | 125 | ||
100 | #endif /* DRM_ATOMIC_HELPER_H_ */ | 126 | #endif /* DRM_ATOMIC_HELPER_H_ */ |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index b459e8fbbc25..dd2c16e43333 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -231,6 +231,7 @@ struct drm_atomic_state; | |||
231 | * struct drm_crtc_state - mutable CRTC state | 231 | * struct drm_crtc_state - mutable CRTC state |
232 | * @enable: whether the CRTC should be enabled, gates all other state | 232 | * @enable: whether the CRTC should be enabled, gates all other state |
233 | * @mode_changed: for use by helpers and drivers when computing state updates | 233 | * @mode_changed: for use by helpers and drivers when computing state updates |
234 | * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes | ||
234 | * @last_vblank_count: for helpers and drivers to capture the vblank of the | 235 | * @last_vblank_count: for helpers and drivers to capture the vblank of the |
235 | * update to ensure framebuffer cleanup isn't done too early | 236 | * update to ensure framebuffer cleanup isn't done too early |
236 | * @planes_changed: for use by helpers and drivers when computing state updates | 237 | * @planes_changed: for use by helpers and drivers when computing state updates |
@@ -247,6 +248,13 @@ struct drm_crtc_state { | |||
247 | bool planes_changed : 1; | 248 | bool planes_changed : 1; |
248 | bool mode_changed : 1; | 249 | bool mode_changed : 1; |
249 | 250 | ||
251 | /* attached planes bitmask: | ||
252 | * WARNING: transitional helpers do not maintain plane_mask so | ||
253 | * drivers not converted over to atomic helpers should not rely | ||
254 | * on plane_mask being accurate! | ||
255 | */ | ||
256 | u32 plane_mask; | ||
257 | |||
250 | /* last_vblank_count: for vblank waits before cleanup */ | 258 | /* last_vblank_count: for vblank waits before cleanup */ |
251 | u32 last_vblank_count; | 259 | u32 last_vblank_count; |
252 | 260 | ||
@@ -438,7 +446,7 @@ struct drm_crtc { | |||
438 | * @state: backpointer to global drm_atomic_state | 446 | * @state: backpointer to global drm_atomic_state |
439 | */ | 447 | */ |
440 | struct drm_connector_state { | 448 | struct drm_connector_state { |
441 | struct drm_crtc *crtc; | 449 | struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_connector() */ |
442 | 450 | ||
443 | struct drm_encoder *best_encoder; | 451 | struct drm_encoder *best_encoder; |
444 | 452 | ||
@@ -673,8 +681,8 @@ struct drm_connector { | |||
673 | * @state: backpointer to global drm_atomic_state | 681 | * @state: backpointer to global drm_atomic_state |
674 | */ | 682 | */ |
675 | struct drm_plane_state { | 683 | struct drm_plane_state { |
676 | struct drm_crtc *crtc; | 684 | struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */ |
677 | struct drm_framebuffer *fb; | 685 | struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */ |
678 | struct fence *fence; | 686 | struct fence *fence; |
679 | 687 | ||
680 | /* Signed dest location allows it to be partially off screen */ | 688 | /* Signed dest location allows it to be partially off screen */ |
@@ -1054,6 +1062,19 @@ struct drm_mode_config { | |||
1054 | uint32_t cursor_width, cursor_height; | 1062 | uint32_t cursor_width, cursor_height; |
1055 | }; | 1063 | }; |
1056 | 1064 | ||
1065 | /** | ||
1066 | * drm_for_each_plane_mask - iterate over planes specified by bitmask | ||
1067 | * @plane: the loop cursor | ||
1068 | * @dev: the DRM device | ||
1069 | * @plane_mask: bitmask of plane indices | ||
1070 | * | ||
1071 | * Iterate over all planes specified by bitmask. | ||
1072 | */ | ||
1073 | #define drm_for_each_plane_mask(plane, dev, plane_mask) \ | ||
1074 | list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \ | ||
1075 | if ((plane_mask) & (1 << drm_plane_index(plane))) | ||
1076 | |||
1077 | |||
1057 | #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) | 1078 | #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) |
1058 | #define obj_to_connector(x) container_of(x, struct drm_connector, base) | 1079 | #define obj_to_connector(x) container_of(x, struct drm_connector, base) |
1059 | #define obj_to_encoder(x) container_of(x, struct drm_encoder, base) | 1080 | #define obj_to_encoder(x) container_of(x, struct drm_encoder, base) |
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index c48f14d88690..a185392cafeb 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h | |||
@@ -49,6 +49,10 @@ extern int drm_crtc_init(struct drm_device *dev, | |||
49 | 49 | ||
50 | /** | 50 | /** |
51 | * drm_plane_helper_funcs - helper operations for CRTCs | 51 | * drm_plane_helper_funcs - helper operations for CRTCs |
52 | * @prepare_fb: prepare a framebuffer for use by the plane | ||
53 | * @cleanup_fb: cleanup a framebuffer when it's no longer used by the plane | ||
54 | * @atomic_check: check that a given atomic state is valid and can be applied | ||
55 | * @atomic_update: apply an atomic state to the plane | ||
52 | * | 56 | * |
53 | * The helper operations are called by the mid-layer CRTC helper. | 57 | * The helper operations are called by the mid-layer CRTC helper. |
54 | */ | 58 | */ |
@@ -60,7 +64,8 @@ struct drm_plane_helper_funcs { | |||
60 | 64 | ||
61 | int (*atomic_check)(struct drm_plane *plane, | 65 | int (*atomic_check)(struct drm_plane *plane, |
62 | struct drm_plane_state *state); | 66 | struct drm_plane_state *state); |
63 | void (*atomic_update)(struct drm_plane *plane); | 67 | void (*atomic_update)(struct drm_plane *plane, |
68 | struct drm_plane_state *old_state); | ||
64 | }; | 69 | }; |
65 | 70 | ||
66 | static inline void drm_plane_helper_add(struct drm_plane *plane, | 71 | static inline void drm_plane_helper_add(struct drm_plane *plane, |