Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+226 -75
+1
Documentation/DocBook/drm.tmpl
··· 2343 2343 <title>Atomic State Reset and Initialization</title> 2344 2344 !Pdrivers/gpu/drm/drm_atomic_helper.c atomic state reset and initialization 2345 2345 </sect3> 2346 + !Iinclude/drm/drm_atomic_helper.h 2346 2347 !Edrivers/gpu/drm/drm_atomic_helper.c 2347 2348 </sect2> 2348 2349 <sect2>
+21 -11
drivers/gpu/drm/drm_atomic.c
··· 243 243 if (state->plane_states[index]) 244 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 246 ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx); 253 247 if (ret) 254 248 return ERR_PTR(ret); ··· 344 350 345 351 /** 346 352 * drm_atomic_set_crtc_for_plane - set crtc for plane 347 - * @plane_state: atomic state object for the plane 353 + * @state: the incoming atomic state 354 + * @plane: the plane whose incoming state to update 348 355 * @crtc: crtc to use for the plane 349 356 * 350 357 * Changing the assigned crtc for a plane requires us to grab the lock and state ··· 358 363 * sequence must be restarted. All other errors are fatal. 359 364 */ 360 365 int 361 - drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, 362 - struct drm_crtc *crtc) 366 + drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state, 367 + struct drm_plane *plane, struct drm_crtc *crtc) 363 368 { 369 + struct drm_plane_state *plane_state = 370 + drm_atomic_get_plane_state(state, plane); 364 371 struct drm_crtc_state *crtc_state; 372 + 373 + if (WARN_ON(IS_ERR(plane_state))) 374 + return PTR_ERR(plane_state); 375 + 376 + if (plane_state->crtc) { 377 + crtc_state = drm_atomic_get_crtc_state(plane_state->state, 378 + plane_state->crtc); 379 + if (WARN_ON(IS_ERR(crtc_state))) 380 + return PTR_ERR(crtc_state); 381 + 382 + crtc_state->plane_mask &= ~(1 << drm_plane_index(plane)); 383 + } 384 + 385 + plane_state->crtc = crtc; 365 386 366 387 if (crtc) { 367 388 crtc_state = drm_atomic_get_crtc_state(plane_state->state, 368 389 crtc); 369 390 if (IS_ERR(crtc_state)) 370 391 return PTR_ERR(crtc_state); 392 + crtc_state->plane_mask |= (1 << drm_plane_index(plane)); 371 393 } 372 - 373 - plane_state->crtc = crtc; 374 394 375 395 if (crtc) 376 396 DRM_DEBUG_KMS("Link plane state %p to [CRTC:%d]\n",
+65 -12
drivers/gpu/drm/drm_atomic_helper.c
··· 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 782 * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs 756 783 * @dev: DRM device ··· 785 758 * 786 759 * Helper to, after atomic commit, wait for vblanks on all effected 787 760 * crtcs (ie. before cleaning up old framebuffers using 788 - * drm_atomic_helper_cleanup_planes()) 761 + * drm_atomic_helper_cleanup_planes()). It will only wait on crtcs where the 762 + * framebuffers have actually changed to optimize for the legacy cursor and 763 + * plane update use-case. 789 764 */ 790 765 void 791 766 drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, ··· 811 782 old_crtc_state->enable = false; 812 783 813 784 if (!crtc->state->enable) 785 + continue; 786 + 787 + if (!framebuffer_changed(dev, old_state, crtc)) 814 788 continue; 815 789 816 790 ret = drm_crtc_vblank_get(crtc); ··· 1046 1014 for (i = 0; i < nplanes; i++) { 1047 1015 struct drm_plane_helper_funcs *funcs; 1048 1016 struct drm_plane *plane = old_state->planes[i]; 1017 + struct drm_plane_state *old_plane_state; 1049 1018 1050 1019 if (!plane) 1051 1020 continue; ··· 1056 1023 if (!funcs || !funcs->atomic_update) 1057 1024 continue; 1058 1025 1059 - funcs->atomic_update(plane); 1026 + old_plane_state = old_state->plane_states[i]; 1027 + 1028 + funcs->atomic_update(plane, old_plane_state); 1060 1029 } 1061 1030 1062 1031 for (i = 0; i < ncrtcs; i++) { ··· 1222 1187 goto fail; 1223 1188 } 1224 1189 1225 - ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); 1190 + ret = drm_atomic_set_crtc_for_plane(state, plane, crtc); 1226 1191 if (ret != 0) 1227 1192 goto fail; 1228 1193 drm_atomic_set_fb_for_plane(plane_state, fb); ··· 1278 1243 struct drm_plane_state *plane_state; 1279 1244 int ret = 0; 1280 1245 1246 + /* 1247 + * FIXME: Without plane->crtc set we can't get at the implicit legacy 1248 + * acquire context. The real fix will be to wire the acquire ctx through 1249 + * everywhere we need it, but meanwhile prevent chaos by just skipping 1250 + * this noop. The critical case is the cursor ioctls which a) only grab 1251 + * crtc/cursor-plane locks (so we need the crtc to get at the right 1252 + * acquire context) and b) can try to disable the plane multiple times. 1253 + */ 1254 + if (!plane->crtc) 1255 + return 0; 1256 + 1281 1257 state = drm_atomic_state_alloc(plane->dev); 1282 1258 if (!state) 1283 1259 return -ENOMEM; ··· 1301 1255 goto fail; 1302 1256 } 1303 1257 1304 - ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); 1258 + ret = drm_atomic_set_crtc_for_plane(state, plane, NULL); 1305 1259 if (ret != 0) 1306 1260 goto fail; 1307 1261 drm_atomic_set_fb_for_plane(plane_state, NULL); ··· 1452 1406 goto fail; 1453 1407 } 1454 1408 1409 + primary_state = drm_atomic_get_plane_state(state, crtc->primary); 1410 + if (IS_ERR(primary_state)) { 1411 + ret = PTR_ERR(primary_state); 1412 + goto fail; 1413 + } 1414 + 1455 1415 if (!set->mode) { 1456 1416 WARN_ON(set->fb); 1457 1417 WARN_ON(set->num_connectors); 1458 1418 1459 1419 crtc_state->enable = false; 1420 + 1421 + ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, NULL); 1422 + if (ret != 0) 1423 + goto fail; 1424 + 1425 + drm_atomic_set_fb_for_plane(primary_state, NULL); 1426 + 1460 1427 goto commit; 1461 1428 } 1462 1429 ··· 1479 1420 crtc_state->enable = true; 1480 1421 drm_mode_copy(&crtc_state->mode, set->mode); 1481 1422 1482 - primary_state = drm_atomic_get_plane_state(state, crtc->primary); 1483 - if (IS_ERR(primary_state)) { 1484 - ret = PTR_ERR(primary_state); 1485 - goto fail; 1486 - } 1487 - 1488 - ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); 1423 + ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, crtc); 1489 1424 if (ret != 0) 1490 1425 goto fail; 1491 1426 drm_atomic_set_fb_for_plane(primary_state, set->fb); ··· 1751 1698 goto fail; 1752 1699 } 1753 1700 1754 - ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); 1701 + ret = drm_atomic_set_crtc_for_plane(state, plane, crtc); 1755 1702 if (ret != 0) 1756 1703 goto fail; 1757 1704 drm_atomic_set_fb_for_plane(plane_state, fb);
+63 -12
drivers/gpu/drm/drm_crtc.c
··· 721 721 drm_mode_object_put(dev, &crtc->base); 722 722 list_del(&crtc->head); 723 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 729 EXPORT_SYMBOL(drm_crtc_cleanup); 726 730 ··· 922 918 connector->name = NULL; 923 919 list_del(&connector->head); 924 920 dev->mode_config.num_connector--; 921 + 922 + WARN_ON(connector->state && !connector->funcs->atomic_destroy_state); 923 + if (connector->state && connector->funcs->atomic_destroy_state) 924 + connector->funcs->atomic_destroy_state(connector, 925 + connector->state); 925 926 } 926 927 EXPORT_SYMBOL(drm_connector_cleanup); 927 928 ··· 1253 1244 if (plane->type == DRM_PLANE_TYPE_OVERLAY) 1254 1245 dev->mode_config.num_overlay_plane--; 1255 1246 drm_modeset_unlock_all(dev); 1247 + 1248 + WARN_ON(plane->state && !plane->funcs->atomic_destroy_state); 1249 + if (plane->state && plane->funcs->atomic_destroy_state) 1250 + plane->funcs->atomic_destroy_state(plane, plane->state); 1256 1251 } 1257 1252 EXPORT_SYMBOL(drm_plane_cleanup); 1258 1253 ··· 1968 1955 return true; 1969 1956 } 1970 1957 1958 + static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector) 1959 + { 1960 + /* For atomic drivers only state objects are synchronously updated and 1961 + * protected by modeset locks, so check those first. */ 1962 + if (connector->state) 1963 + return connector->state->best_encoder; 1964 + return connector->encoder; 1965 + } 1966 + 1971 1967 /** 1972 1968 * drm_mode_getconnector - get connector configuration 1973 1969 * @dev: drm device for the ioctl ··· 1995 1973 { 1996 1974 struct drm_mode_get_connector *out_resp = data; 1997 1975 struct drm_connector *connector; 1976 + struct drm_encoder *encoder; 1998 1977 struct drm_display_mode *mode; 1999 1978 int mode_count = 0; 2000 1979 int props_count = 0; ··· 2051 2028 out_resp->subpixel = connector->display_info.subpixel_order; 2052 2029 out_resp->connection = connector->status; 2053 2030 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); 2054 - if (connector->encoder) 2055 - out_resp->encoder_id = connector->encoder->base.id; 2031 + 2032 + encoder = drm_connector_get_encoder(connector); 2033 + if (encoder) 2034 + out_resp->encoder_id = encoder->base.id; 2056 2035 else 2057 2036 out_resp->encoder_id = 0; 2058 2037 drm_modeset_unlock(&dev->mode_config.connection_mutex); ··· 2124 2099 return ret; 2125 2100 } 2126 2101 2102 + static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder) 2103 + { 2104 + struct drm_connector *connector; 2105 + struct drm_device *dev = encoder->dev; 2106 + bool uses_atomic = false; 2107 + 2108 + /* For atomic drivers only state objects are synchronously updated and 2109 + * protected by modeset locks, so check those first. */ 2110 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 2111 + if (!connector->state) 2112 + continue; 2113 + 2114 + uses_atomic = true; 2115 + 2116 + if (connector->state->best_encoder != encoder) 2117 + continue; 2118 + 2119 + return connector->state->crtc; 2120 + } 2121 + 2122 + /* Don't return stale data (e.g. pending async disable). */ 2123 + if (uses_atomic) 2124 + return NULL; 2125 + 2126 + return encoder->crtc; 2127 + } 2128 + 2127 2129 /** 2128 2130 * drm_mode_getencoder - get encoder configuration 2129 2131 * @dev: drm device for the ioctl ··· 2169 2117 { 2170 2118 struct drm_mode_get_encoder *enc_resp = data; 2171 2119 struct drm_encoder *encoder; 2120 + struct drm_crtc *crtc; 2172 2121 2173 2122 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2174 2123 return -EINVAL; ··· 2179 2126 return -ENOENT; 2180 2127 2181 2128 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); 2182 - if (encoder->crtc) 2129 + crtc = drm_encoder_get_crtc(encoder); 2130 + if (crtc) 2131 + enc_resp->crtc_id = crtc->base.id; 2132 + else if (encoder->crtc) 2183 2133 enc_resp->crtc_id = encoder->crtc->base.id; 2184 2134 else 2185 2135 enc_resp->crtc_id = 0; ··· 2448 2392 struct drm_file *file_priv) 2449 2393 { 2450 2394 struct drm_mode_set_plane *plane_req = data; 2451 - struct drm_mode_object *obj; 2452 2395 struct drm_plane *plane; 2453 2396 struct drm_crtc *crtc = NULL; 2454 2397 struct drm_framebuffer *fb = NULL; ··· 2470 2415 * First, find the plane, crtc, and fb objects. If not available, 2471 2416 * we don't bother to call the driver. 2472 2417 */ 2473 - obj = drm_mode_object_find(dev, plane_req->plane_id, 2474 - DRM_MODE_OBJECT_PLANE); 2475 - if (!obj) { 2418 + plane = drm_plane_find(dev, plane_req->plane_id); 2419 + if (!plane) { 2476 2420 DRM_DEBUG_KMS("Unknown plane ID %d\n", 2477 2421 plane_req->plane_id); 2478 2422 return -ENOENT; 2479 2423 } 2480 - plane = obj_to_plane(obj); 2481 2424 2482 2425 if (plane_req->fb_id) { 2483 2426 fb = drm_framebuffer_lookup(dev, plane_req->fb_id); ··· 2485 2432 return -ENOENT; 2486 2433 } 2487 2434 2488 - obj = drm_mode_object_find(dev, plane_req->crtc_id, 2489 - DRM_MODE_OBJECT_CRTC); 2490 - if (!obj) { 2435 + crtc = drm_crtc_find(dev, plane_req->crtc_id); 2436 + if (!crtc) { 2491 2437 DRM_DEBUG_KMS("Unknown crtc ID %d\n", 2492 2438 plane_req->crtc_id); 2493 2439 return -ENOENT; 2494 2440 } 2495 - crtc = obj_to_crtc(obj); 2496 2441 } 2497 2442 2498 2443 /*
+2
drivers/gpu/drm/drm_drv.c
··· 535 535 * The initial ref-count of the object is 1. Use drm_dev_ref() and 536 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 540 * RETURNS: 539 541 * Pointer to new DRM device, or NULL if out of memory. 540 542 */
+1 -1
drivers/gpu/drm/drm_plane_helper.c
··· 443 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 448 for (i = 0; i < 2; i++) { 449 449 if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush)
+3 -3
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
··· 84 84 struct drm_plane *plane; 85 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 88 enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); 89 89 flush |= pipe2flush(pipe_id); 90 90 } ··· 197 197 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); 198 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 201 enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); 202 202 int idx = idxs[pipe_id]; 203 203 mixer_cfg = mixercfg(mixer_cfg, mdp4_crtc->mixer, ··· 221 221 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0); 222 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 225 enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); 226 226 int idx = idxs[pipe_id]; 227 227 if (idx > 0) {
+2 -1
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
··· 107 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 113 struct drm_plane_state *state = plane->state; 113 114 int ret;
+5 -4
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
··· 91 91 if (!mdp5_crtc->ctl) 92 92 return; 93 93 94 - for_each_plane_on_crtc(crtc, plane) { 94 + drm_atomic_crtc_for_each_plane(plane, crtc) { 95 95 flush_mask |= mdp5_plane_get_flush(plane); 96 96 } 97 97 flush_mask |= mdp5_ctl_get_flush(mdp5_crtc->ctl); ··· 124 124 } 125 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 128 mdp5_plane_complete_flip(plane); 129 + } 129 130 } 130 131 131 132 static void mdp5_crtc_destroy(struct drm_crtc *crtc) ··· 196 195 if (!mdp5_crtc->ctl) 197 196 goto out; 198 197 199 - for_each_plane_on_crtc(crtc, plane) { 198 + drm_atomic_crtc_for_each_plane(plane, crtc) { 200 199 enum mdp_mixer_stage_id stage = 201 200 to_mdp5_plane_state(plane->state)->stage; 202 201 ··· 318 317 /* verify that there are not too many planes attached to crtc 319 318 * and that we don't have conflicting mixer stages: 320 319 */ 321 - for_each_pending_plane_on_crtc(state->state, crtc, plane) { 320 + drm_atomic_crtc_state_for_each_plane(plane, state) { 322 321 struct drm_plane_state *pstate; 323 322 324 323 if (cnt >= ARRAY_SIZE(pstates)) {
+2 -1
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
··· 213 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 219 struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); 219 220 struct drm_plane_state *state = plane->state;
-23
drivers/gpu/drm/msm/msm_kms.h
··· 65 65 struct msm_kms *mdp4_kms_init(struct drm_device *dev); 66 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 68 #endif /* __MSM_KMS_H__ */
+1 -1
include/drm/drmP.h
··· 809 809 struct drm_local_map *agp_buffer_map; 810 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 814 /** \name GEM information */ 815 815 /*@{ */
+4 -2
include/drm/drm_atomic.h
··· 28 28 #ifndef DRM_ATOMIC_H_ 29 29 #define DRM_ATOMIC_H_ 30 30 31 + #include <drm/drm_crtc.h> 32 + 31 33 struct drm_atomic_state * __must_check 32 34 drm_atomic_state_alloc(struct drm_device *dev); 33 35 void drm_atomic_state_clear(struct drm_atomic_state *state); ··· 46 44 struct drm_connector *connector); 47 45 48 46 int __must_check 49 - drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, 50 - struct drm_crtc *crtc); 47 + drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state, 48 + struct drm_plane *plane, struct drm_crtc *crtc); 51 49 void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, 52 50 struct drm_framebuffer *fb); 53 51 int __must_check
+26
include/drm/drm_atomic_helper.h
··· 28 28 #ifndef DRM_ATOMIC_HELPER_H_ 29 29 #define DRM_ATOMIC_HELPER_H_ 30 30 31 + #include <drm/drm_crtc.h> 32 + 31 33 int drm_atomic_helper_check(struct drm_device *dev, 32 34 struct drm_atomic_state *state); 33 35 int drm_atomic_helper_commit(struct drm_device *dev, ··· 98 96 void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, 99 97 struct drm_connector_state *state); 100 98 99 + /** 100 + * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC 101 + * @plane: the loop cursor 102 + * @crtc: the crtc whose planes are iterated 103 + * 104 + * This iterates over the current state, useful (for example) when applying 105 + * atomic state after it has been checked and swapped. To iterate over the 106 + * planes which *will* be attached (for ->atomic_check()) see 107 + * drm_crtc_for_each_pending_plane() 108 + */ 109 + #define drm_atomic_crtc_for_each_plane(plane, crtc) \ 110 + drm_for_each_plane_mask(plane, (crtc)->dev, (crtc)->state->plane_mask) 111 + 112 + /** 113 + * drm_crtc_atomic_state_for_each_plane - iterate over attached planes in new state 114 + * @plane: the loop cursor 115 + * @crtc_state: the incoming crtc-state 116 + * 117 + * Similar to drm_crtc_for_each_plane(), but iterates the planes that will be 118 + * attached if the specified state is applied. Useful during (for example) 119 + * ->atomic_check() operations, to validate the incoming state 120 + */ 121 + #define drm_atomic_crtc_state_for_each_plane(plane, crtc_state) \ 122 + drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask) 101 123 102 124 #endif /* DRM_ATOMIC_HELPER_H_ */
+24 -3
include/drm/drm_crtc.h
··· 231 231 * struct drm_crtc_state - mutable CRTC state 232 232 * @enable: whether the CRTC should be enabled, gates all other state 233 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 235 * @last_vblank_count: for helpers and drivers to capture the vblank of the 235 236 * update to ensure framebuffer cleanup isn't done too early 236 237 * @planes_changed: for use by helpers and drivers when computing state updates ··· 247 246 /* computed state bits used by helpers and drivers */ 248 247 bool planes_changed : 1; 249 248 bool mode_changed : 1; 249 + 250 + /* attached planes bitmask: 251 + * WARNING: transitional helpers do not maintain plane_mask so 252 + * drivers not converted over to atomic helpers should not rely 253 + * on plane_mask being accurate! 254 + */ 255 + u32 plane_mask; 250 256 251 257 /* last_vblank_count: for vblank waits before cleanup */ 252 258 u32 last_vblank_count; ··· 446 438 * @state: backpointer to global drm_atomic_state 447 439 */ 448 440 struct drm_connector_state { 449 - struct drm_crtc *crtc; 441 + struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_connector() */ 450 442 451 443 struct drm_encoder *best_encoder; 452 444 ··· 681 673 * @state: backpointer to global drm_atomic_state 682 674 */ 683 675 struct drm_plane_state { 684 - struct drm_crtc *crtc; 685 - struct drm_framebuffer *fb; 676 + struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */ 677 + struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */ 686 678 struct fence *fence; 687 679 688 680 /* Signed dest location allows it to be partially off screen */ ··· 1061 1053 /* cursor size */ 1062 1054 uint32_t cursor_width, cursor_height; 1063 1055 }; 1056 + 1057 + /** 1058 + * drm_for_each_plane_mask - iterate over planes specified by bitmask 1059 + * @plane: the loop cursor 1060 + * @dev: the DRM device 1061 + * @plane_mask: bitmask of plane indices 1062 + * 1063 + * Iterate over all planes specified by bitmask. 1064 + */ 1065 + #define drm_for_each_plane_mask(plane, dev, plane_mask) \ 1066 + list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \ 1067 + if ((plane_mask) & (1 << drm_plane_index(plane))) 1068 + 1064 1069 1065 1070 #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) 1066 1071 #define obj_to_connector(x) container_of(x, struct drm_connector, base)
+6 -1
include/drm/drm_plane_helper.h
··· 49 49 50 50 /** 51 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 57 * The helper operations are called by the mid-layer CRTC helper. 54 58 */ ··· 64 60 65 61 int (*atomic_check)(struct drm_plane *plane, 66 62 struct drm_plane_state *state); 67 - void (*atomic_update)(struct drm_plane *plane); 63 + void (*atomic_update)(struct drm_plane *plane, 64 + struct drm_plane_state *old_state); 68 65 }; 69 66 70 67 static inline void drm_plane_helper_add(struct drm_plane *plane,