History

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

Dave Airlie committed 11 years ago

Commit 9be23ae2 parents 5a0e9d7 e5b534116 files · +226 −75Browse files

Unified · Split

16 files
  1. Documentation/DocBook/drm.tmpl +1 −0
  2. drivers/gpu/drm/drm_atomic.c +21 −11
  3. drivers/gpu/drm/drm_atomic_helper.c +65 −12
  4. drivers/gpu/drm/drm_crtc.c +63 −12
  5. drivers/gpu/drm/drm_drv.c +2 −0
  6. drivers/gpu/drm/drm_plane_helper.c +1 −1
  7. drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +3 −3
  8. drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +2 −1
  9. drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +5 −4
  10. drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +2 −1
  11. drivers/gpu/drm/msm/msm_kms.h +0 −23
  12. include/drm/drmP.h +1 −1
  13. include/drm/drm_atomic.h +4 −2
  14. include/drm/drm_atomic_helper.h +26 −0
  15. include/drm/drm_crtc.h +24 −3
  16. include/drm/drm_plane_helper.h +6 −1
Documentation/DocBook/drm.tmpl+1−0
@@ -2343,6 +2343,7 @@ void intel_crt_init(struct drm_device *dev) · 2342 unmodified lines
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 initialization2344!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.c2347!Edrivers/gpu/drm/drm_atomic_helper.c
2347 </sect2>2348 </sect2>
2348 <sect2>2349 <sect2>
drivers/gpu/drm/drm_atomic.c+21−11
@@ -243,12 +243,6 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state, · 242 unmodified lines
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); · 95 unmodified lines
350 344
351/**345/**
352 * drm_atomic_set_crtc_for_plane - set crtc for plane346 * drm_atomic_set_crtc_for_plane - set crtc for plane
353 * @plane_state: atomic state object for the plane347 * @state: the incoming atomic state
348 * @plane: the plane whose incoming state to update
354 * @crtc: crtc to use for the plane349 * @crtc: crtc to use for the plane
355 *350 *
356 * Changing the assigned crtc for a plane requires us to grab the lock and state351 * 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); · 6 unmodified lines
363 * sequence must be restarted. All other errors are fatal.358 * sequence must be restarted. All other errors are fatal.
364 */359 */
365int360int
366drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,361drm_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);
drivers/gpu/drm/drm_atomic_helper.c+65−12
@@ -751,6 +751,33 @@ static void wait_for_fences(struct drm_device *dev, · 750 unmodified lines
751 }751 }
752}752}
753 753
754static 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 crtcs782 * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs
756 * @dev: DRM device783 * @dev: DRM device
@@ -758,7 +785,9 @@ static void wait_for_fences(struct drm_device *dev, · 1 unmodified line
758 *785 *
759 * Helper to, after atomic commit, wait for vblanks on all effected786 * Helper to, after atomic commit, wait for vblanks on all effected
760 * crtcs (ie. before cleaning up old framebuffers using787 * 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 */
763void792void
764drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,793drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
@@ -784,6 +813,9 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, · 19 unmodified lines
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, · 224 unmodified lines
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, · 3 unmodified lines
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: · 157 unmodified lines
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) · 49 unmodified lines
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: · 6 unmodified lines
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: · 144 unmodified lines
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: · 3 unmodified lines
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: · 265 unmodified lines
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);
drivers/gpu/drm/drm_crtc.c+63−12
@@ -721,6 +721,10 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) · 720 unmodified lines
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}
725EXPORT_SYMBOL(drm_crtc_cleanup);729EXPORT_SYMBOL(drm_crtc_cleanup);
726 730
@@ -918,6 +922,11 @@ void drm_connector_cleanup(struct drm_connector *connector) · 191 unmodified lines
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}
922EXPORT_SYMBOL(drm_connector_cleanup);931EXPORT_SYMBOL(drm_connector_cleanup);
923 932
@@ -1244,6 +1253,10 @@ void drm_plane_cleanup(struct drm_plane *plane) · 320 unmodified lines
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}
1248EXPORT_SYMBOL(drm_plane_cleanup);1261EXPORT_SYMBOL(drm_plane_cleanup);
1249 1262
@@ -1955,6 +1968,15 @@ static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode, · 705 unmodified lines
1955 return true;1968 return true;
1956}1969}
1957 1970
1971static 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 configuration1981 * drm_mode_getconnector - get connector configuration
1960 * @dev: drm device for the ioctl1982 * @dev: drm device for the ioctl
@@ -1973,6 +1995,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, · 12 unmodified lines
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, · 49 unmodified lines
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 else2058 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: · 63 unmodified lines
2099 return ret;2124 return ret;
2100}2125}
2101 2126
2127static 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 configuration2155 * drm_mode_getencoder - get encoder configuration
2104 * @dev: drm device for the ioctl2156 * @dev: drm device for the ioctl
@@ -2117,6 +2169,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, · 12 unmodified lines
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, · 3 unmodified lines
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 else2187 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, · 259 unmodified lines
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, · 16 unmodified lines
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, · 3 unmodified lines
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 /*
drivers/gpu/drm/drm_drv.c+2−0
@@ -535,6 +535,8 @@ static void drm_fs_inode_free(struct inode *inode) · 534 unmodified lines
535 * The initial ref-count of the object is 1. Use drm_dev_ref() and535 * 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 */
drivers/gpu/drm/drm_plane_helper.c+1−1
@@ -443,7 +443,7 @@ int drm_plane_helper_commit(struct drm_plane *plane, · 442 unmodified lines
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)
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c+3−3
@@ -84,7 +84,7 @@ static void crtc_flush(struct drm_crtc *crtc) · 83 unmodified lines
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) · 106 unmodified lines
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) · 17 unmodified lines
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) {
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c+2−1
@@ -107,7 +107,8 @@ static int mdp4_plane_atomic_check(struct drm_plane *plane, · 106 unmodified lines
107 return 0;107 return 0;
108}108}
109 109
110static void mdp4_plane_atomic_update(struct drm_plane *plane)110static 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;
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c+5−4
@@ -91,7 +91,7 @@ static void crtc_flush_all(struct drm_crtc *crtc) · 90 unmodified lines
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) · 26 unmodified lines
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
131static void mdp5_crtc_destroy(struct drm_crtc *crtc)132static void mdp5_crtc_destroy(struct drm_crtc *crtc)
@@ -195,7 +196,7 @@ static void blend_setup(struct drm_crtc *crtc) · 63 unmodified lines
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, · 115 unmodified lines
317 /* verify that there are not too many planes attached to crtc318 /* 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)) {
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c+2−1
@@ -213,7 +213,8 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane, · 212 unmodified lines
213 return 0;213 return 0;
214}214}
215 215
216static void mdp5_plane_atomic_update(struct drm_plane *plane)216static 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;
drivers/gpu/drm/msm/msm_kms.h+0−23
@@ -65,27 +65,4 @@ static inline void msm_kms_init(struct msm_kms *kms, · 64 unmodified lines
65struct msm_kms *mdp4_kms_init(struct drm_device *dev);65struct msm_kms *mdp4_kms_init(struct drm_device *dev);
66struct msm_kms *mdp5_kms_init(struct drm_device *dev);66struct 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
73static 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__ */
include/drm/drmP.h+1−1
@@ -809,7 +809,7 @@ struct drm_device { · 808 unmodified lines
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 /*@{ */
include/drm/drm_atomic.h+4−2
@@ -28,6 +28,8 @@ · 27 unmodified lines
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
31struct drm_atomic_state * __must_check33struct drm_atomic_state * __must_check
32drm_atomic_state_alloc(struct drm_device *dev);34drm_atomic_state_alloc(struct drm_device *dev);
33void drm_atomic_state_clear(struct drm_atomic_state *state);35void drm_atomic_state_clear(struct drm_atomic_state *state);
@@ -44,8 +46,8 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, · 10 unmodified lines
44 struct drm_connector *connector);46 struct drm_connector *connector);
45 47
46int __must_check48int __must_check
47drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,49drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state,
48 struct drm_crtc *crtc);50 struct drm_plane *plane, struct drm_crtc *crtc);
49void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,51void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
50 struct drm_framebuffer *fb);52 struct drm_framebuffer *fb);
51int __must_check53int __must_check
include/drm/drm_atomic_helper.h+26−0
@@ -28,6 +28,8 @@ · 27 unmodified lines
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
31int drm_atomic_helper_check(struct drm_device *dev,33int drm_atomic_helper_check(struct drm_device *dev,
32 struct drm_atomic_state *state);34 struct drm_atomic_state *state);
33int drm_atomic_helper_commit(struct drm_device *dev,35int drm_atomic_helper_commit(struct drm_device *dev,
@@ -96,5 +98,29 @@ drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); · 62 unmodified lines
96void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,98void 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_ */
include/drm/drm_crtc.h+24−3
@@ -231,6 +231,7 @@ struct drm_atomic_state; · 230 unmodified lines
231 * struct drm_crtc_state - mutable CRTC state231 * struct drm_crtc_state - mutable CRTC state
232 * @enable: whether the CRTC should be enabled, gates all other state232 * @enable: whether the CRTC should be enabled, gates all other state
233 * @mode_changed: for use by helpers and drivers when computing state updates233 * @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 the235 * @last_vblank_count: for helpers and drivers to capture the vblank of the
235 * update to ensure framebuffer cleanup isn't done too early236 * update to ensure framebuffer cleanup isn't done too early
236 * @planes_changed: for use by helpers and drivers when computing state updates237 * @planes_changed: for use by helpers and drivers when computing state updates
@@ -247,6 +248,13 @@ struct drm_crtc_state { · 10 unmodified lines
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 { · 185 unmodified lines
438 * @state: backpointer to global drm_atomic_state446 * @state: backpointer to global drm_atomic_state
439 */447 */
440struct drm_connector_state {448struct 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 { · 228 unmodified lines
673 * @state: backpointer to global drm_atomic_state681 * @state: backpointer to global drm_atomic_state
674 */682 */
675struct drm_plane_state {683struct 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 { · 373 unmodified lines
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)
include/drm/drm_plane_helper.h+6−1
@@ -49,6 +49,10 @@ extern int drm_crtc_init(struct drm_device *dev, · 48 unmodified lines
49 49
50/**50/**
51 * drm_plane_helper_funcs - helper operations for CRTCs51 * 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 { · 5 unmodified lines
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
66static inline void drm_plane_helper_add(struct drm_plane *plane,71static inline void drm_plane_helper_add(struct drm_plane *plane,