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, |
