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
23432343 <title>Atomic State Reset and Initialization</title>
23442344 !Pdrivers/gpu/drm/drm_atomic_helper.c atomic state reset and initialization
23452345 </sect3>
2346+!Iinclude/drm/drm_atomic_helper.h
23462347 !Edrivers/gpu/drm/drm_atomic_helper.c
23472348 </sect2>
23482349 <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
243243 if (state->plane_states[index])
244244 return state->plane_states[index];
245245
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− */
252246 ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx);
253247 if (ret)
254248 return ERR_PTR(ret);
@@ -350,7 +344,8 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state); · 95 unmodified lines
350344
351345 /**
352346 * 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
354349 * @crtc: crtc to use for the plane
355350 *
356351 * 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
363358 * sequence must be restarted. All other errors are fatal.
364359 */
365360 int
366−drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
367− struct drm_crtc *crtc)
361+drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state,
362+ struct drm_plane *plane, struct drm_crtc *crtc)
368363 {
364+ struct drm_plane_state *plane_state =
365+ drm_atomic_get_plane_state(state, plane);
369366 struct drm_crtc_state *crtc_state;
370367
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+
371382 if (crtc) {
372383 crtc_state = drm_atomic_get_crtc_state(plane_state->state,
373384 crtc);
374385 if (IS_ERR(crtc_state))
375386 return PTR_ERR(crtc_state);
387+ crtc_state->plane_mask |= (1 << drm_plane_index(plane));
376388 }
377389
378− plane_state->crtc = crtc;
379−
380390 if (crtc)
381391 DRM_DEBUG_KMS("Link plane state %p to [CRTC:%d]\n",
382392 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
751751 }
752752 }
753753
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+
754781 /**
755782 * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs
756783 * @dev: DRM device
@@ -758,7 +785,9 @@ static void wait_for_fences(struct drm_device *dev, · 1 unmodified line
758785 *
759786 * Helper to, after atomic commit, wait for vblanks on all effected
760787 * 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.
762791 */
763792 void
764793 drm_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
784813 if (!crtc->state->enable)
785814 continue;
786815
816+ if (!framebuffer_changed(dev, old_state, crtc))
817+ continue;
818+
787819 ret = drm_crtc_vblank_get(crtc);
788820 if (ret != 0)
789821 continue;
@@ -1014,6 +1046,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, · 224 unmodified lines
10141046 for (i = 0; i < nplanes; i++) {
10151047 struct drm_plane_helper_funcs *funcs;
10161048 struct drm_plane *plane = old_state->planes[i];
1049+ struct drm_plane_state *old_plane_state;
10171050
10181051 if (!plane)
10191052 continue;
@@ -1023,7 +1056,9 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, · 3 unmodified lines
10231056 if (!funcs || !funcs->atomic_update)
10241057 continue;
10251058
1026− funcs->atomic_update(plane);
1059+ old_plane_state = old_state->plane_states[i];
1060+
1061+ funcs->atomic_update(plane, old_plane_state);
10271062 }
10281063
10291064 for (i = 0; i < ncrtcs; i++) {
@@ -1187,7 +1222,7 @@ retry: · 157 unmodified lines
11871222 goto fail;
11881223 }
11891224
1190− ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
1225+ ret = drm_atomic_set_crtc_for_plane(state, plane, crtc);
11911226 if (ret != 0)
11921227 goto fail;
11931228 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
12431278 struct drm_plane_state *plane_state;
12441279 int ret = 0;
12451280
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+
12461292 state = drm_atomic_state_alloc(plane->dev);
12471293 if (!state)
12481294 return -ENOMEM;
@@ -1255,7 +1301,7 @@ retry: · 6 unmodified lines
12551301 goto fail;
12561302 }
12571303
1258− ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
1304+ ret = drm_atomic_set_crtc_for_plane(state, plane, NULL);
12591305 if (ret != 0)
12601306 goto fail;
12611307 drm_atomic_set_fb_for_plane(plane_state, NULL);
@@ -1406,11 +1452,24 @@ retry: · 144 unmodified lines
14061452 goto fail;
14071453 }
14081454
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+
14091461 if (!set->mode) {
14101462 WARN_ON(set->fb);
14111463 WARN_ON(set->num_connectors);
14121464
14131465 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+
14141473 goto commit;
14151474 }
14161475
@@ -1420,13 +1479,7 @@ retry: · 3 unmodified lines
14201479 crtc_state->enable = true;
14211480 drm_mode_copy(&crtc_state->mode, set->mode);
14221481
1423− primary_state = drm_atomic_get_plane_state(state, crtc->primary);
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);
1482+ ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, crtc);
14301483 if (ret != 0)
14311484 goto fail;
14321485 drm_atomic_set_fb_for_plane(primary_state, set->fb);
@@ -1698,7 +1751,7 @@ retry: · 265 unmodified lines
16981751 goto fail;
16991752 }
17001753
1701− ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
1754+ ret = drm_atomic_set_crtc_for_plane(state, plane, crtc);
17021755 if (ret != 0)
17031756 goto fail;
17041757 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
721721 drm_mode_object_put(dev, &crtc->base);
722722 list_del(&crtc->head);
723723 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);
724728 }
725729 EXPORT_SYMBOL(drm_crtc_cleanup);
726730
@@ -918,6 +922,11 @@ void drm_connector_cleanup(struct drm_connector *connector) · 191 unmodified lines
918922 connector->name = NULL;
919923 list_del(&connector->head);
920924 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);
921930 }
922931 EXPORT_SYMBOL(drm_connector_cleanup);
923932
@@ -1244,6 +1253,10 @@ void drm_plane_cleanup(struct drm_plane *plane) · 320 unmodified lines
12441253 if (plane->type == DRM_PLANE_TYPE_OVERLAY)
12451254 dev->mode_config.num_overlay_plane--;
12461255 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);
12471260 }
12481261 EXPORT_SYMBOL(drm_plane_cleanup);
12491262
@@ -1955,6 +1968,15 @@ static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode, · 705 unmodified lines
19551968 return true;
19561969 }
19571970
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+
19581980 /**
19591981 * drm_mode_getconnector - get connector configuration
19601982 * @dev: drm device for the ioctl
@@ -1973,6 +1995,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, · 12 unmodified lines
19731995 {
19741996 struct drm_mode_get_connector *out_resp = data;
19751997 struct drm_connector *connector;
1998+ struct drm_encoder *encoder;
19761999 struct drm_display_mode *mode;
19772000 int mode_count = 0;
19782001 int props_count = 0;
@@ -2028,8 +2051,10 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, · 49 unmodified lines
20282051 out_resp->subpixel = connector->display_info.subpixel_order;
20292052 out_resp->connection = connector->status;
20302053 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
2031− if (connector->encoder)
2032− out_resp->encoder_id = connector->encoder->base.id;
2054+
2055+ encoder = drm_connector_get_encoder(connector);
2056+ if (encoder)
2057+ out_resp->encoder_id = encoder->base.id;
20332058 else
20342059 out_resp->encoder_id = 0;
20352060 drm_modeset_unlock(&dev->mode_config.connection_mutex);
@@ -2099,6 +2124,33 @@ out: · 63 unmodified lines
20992124 return ret;
21002125 }
21012126
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+
21022154 /**
21032155 * drm_mode_getencoder - get encoder configuration
21042156 * @dev: drm device for the ioctl
@@ -2117,6 +2169,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, · 12 unmodified lines
21172169 {
21182170 struct drm_mode_get_encoder *enc_resp = data;
21192171 struct drm_encoder *encoder;
2172+ struct drm_crtc *crtc;
21202173
21212174 if (!drm_core_check_feature(dev, DRIVER_MODESET))
21222175 return -EINVAL;
@@ -2126,7 +2179,10 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, · 3 unmodified lines
21262179 return -ENOENT;
21272180
21282181 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)
21302186 enc_resp->crtc_id = encoder->crtc->base.id;
21312187 else
21322188 enc_resp->crtc_id = 0;
@@ -2392,7 +2448,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data, · 259 unmodified lines
23922448 struct drm_file *file_priv)
23932449 {
23942450 struct drm_mode_set_plane *plane_req = data;
2395− struct drm_mode_object *obj;
23962451 struct drm_plane *plane;
23972452 struct drm_crtc *crtc = NULL;
23982453 struct drm_framebuffer *fb = NULL;
@@ -2415,14 +2470,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data, · 16 unmodified lines
24152470 * First, find the plane, crtc, and fb objects. If not available,
24162471 * we don't bother to call the driver.
24172472 */
2418− obj = drm_mode_object_find(dev, plane_req->plane_id,
2419− DRM_MODE_OBJECT_PLANE);
2420− if (!obj) {
2473+ plane = drm_plane_find(dev, plane_req->plane_id);
2474+ if (!plane) {
24212475 DRM_DEBUG_KMS("Unknown plane ID %d\n",
24222476 plane_req->plane_id);
24232477 return -ENOENT;
24242478 }
2425− plane = obj_to_plane(obj);
24262479
24272480 if (plane_req->fb_id) {
24282481 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
24322485 return -ENOENT;
24332486 }
24342487
2435− obj = drm_mode_object_find(dev, plane_req->crtc_id,
2436− DRM_MODE_OBJECT_CRTC);
2437− if (!obj) {
2488+ crtc = drm_crtc_find(dev, plane_req->crtc_id);
2489+ if (!crtc) {
24382490 DRM_DEBUG_KMS("Unknown crtc ID %d\n",
24392491 plane_req->crtc_id);
24402492 return -ENOENT;
24412493 }
2442− crtc = obj_to_crtc(obj);
24432494 }
24442495
24452496 /*
drivers/gpu/drm/drm_drv.c+2−0
@@ -535,6 +535,8 @@ static void drm_fs_inode_free(struct inode *inode) · 534 unmodified lines
535535 * The initial ref-count of the object is 1. Use drm_dev_ref() and
536536 * drm_dev_unref() to take and drop further ref-counts.
537537 *
538+ * Note that for purely virtual devices @parent can be NULL.
539+ *
538540 * RETURNS:
539541 * Pointer to new DRM device, or NULL if out of memory.
540542 */
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
443443 crtc_funcs[i]->atomic_begin(crtc[i]);
444444 }
445445
446− plane_funcs->atomic_update(plane);
446+ plane_funcs->atomic_update(plane, plane_state);
447447
448448 for (i = 0; i < 2; i++) {
449449 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
8484 struct drm_plane *plane;
8585 uint32_t flush = 0;
8686
87− for_each_plane_on_crtc(crtc, plane) {
87+ drm_atomic_crtc_for_each_plane(plane, crtc) {
8888 enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
8989 flush |= pipe2flush(pipe_id);
9090 }
@@ -197,7 +197,7 @@ static void setup_mixer(struct mdp4_kms *mdp4_kms) · 106 unmodified lines
197197 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
198198 struct drm_plane *plane;
199199
200− for_each_plane_on_crtc(crtc, plane) {
200+ drm_atomic_crtc_for_each_plane(plane, crtc) {
201201 enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
202202 int idx = idxs[pipe_id];
203203 mixer_cfg = mixercfg(mixer_cfg, mdp4_crtc->mixer,
@@ -221,7 +221,7 @@ static void blend_setup(struct drm_crtc *crtc) · 17 unmodified lines
221221 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0);
222222 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0);
223223
224− for_each_plane_on_crtc(crtc, plane) {
224+ drm_atomic_crtc_for_each_plane(plane, crtc) {
225225 enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
226226 int idx = idxs[pipe_id];
227227 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
107107 return 0;
108108 }
109109
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)
111112 {
112113 struct drm_plane_state *state = plane->state;
113114 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
9191 if (!mdp5_crtc->ctl)
9292 return;
9393
94− for_each_plane_on_crtc(crtc, plane) {
94+ drm_atomic_crtc_for_each_plane(plane, crtc) {
9595 flush_mask |= mdp5_plane_get_flush(plane);
9696 }
9797 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
124124 }
125125 spin_unlock_irqrestore(&dev->event_lock, flags);
126126
127− for_each_plane_on_crtc(crtc, plane)
127+ drm_atomic_crtc_for_each_plane(plane, crtc) {
128128 mdp5_plane_complete_flip(plane);
129+ }
129130 }
130131
131132 static void mdp5_crtc_destroy(struct drm_crtc *crtc)
@@ -195,7 +196,7 @@ static void blend_setup(struct drm_crtc *crtc) · 63 unmodified lines
195196 if (!mdp5_crtc->ctl)
196197 goto out;
197198
198− for_each_plane_on_crtc(crtc, plane) {
199+ drm_atomic_crtc_for_each_plane(plane, crtc) {
199200 enum mdp_mixer_stage_id stage =
200201 to_mdp5_plane_state(plane->state)->stage;
201202
@@ -317,7 +318,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, · 115 unmodified lines
317318 /* verify that there are not too many planes attached to crtc
318319 * and that we don't have conflicting mixer stages:
319320 */
320− for_each_pending_plane_on_crtc(state->state, crtc, plane) {
321+ drm_atomic_crtc_state_for_each_plane(plane, state) {
321322 struct drm_plane_state *pstate;
322323
323324 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
213213 return 0;
214214 }
215215
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)
217218 {
218219 struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
219220 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
6565 struct msm_kms *mdp4_kms_init(struct drm_device *dev);
6666 struct msm_kms *mdp5_kms_init(struct drm_device *dev);
6767
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−
9168 #endif /* __MSM_KMS_H__ */
include/drm/drmP.h+1−1
@@ -809,7 +809,7 @@ struct drm_device { · 808 unmodified lines
809809 struct drm_local_map *agp_buffer_map;
810810 unsigned int agp_buffer_token;
811811
812− struct drm_mode_config mode_config; /**< Current mode config */
812+ struct drm_mode_config mode_config; /**< Current mode config */
813813
814814 /** \name GEM information */
815815 /*@{ */
include/drm/drm_atomic.h+4−2
@@ -28,6 +28,8 @@ · 27 unmodified lines
2828 #ifndef DRM_ATOMIC_H_
2929 #define DRM_ATOMIC_H_
3030
31+#include <drm/drm_crtc.h>
32+
3133 struct drm_atomic_state * __must_check
3234 drm_atomic_state_alloc(struct drm_device *dev);
3335 void 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
4446 struct drm_connector *connector);
4547
4648 int __must_check
47−drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
48− struct drm_crtc *crtc);
49+drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state,
50+ struct drm_plane *plane, struct drm_crtc *crtc);
4951 void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
5052 struct drm_framebuffer *fb);
5153 int __must_check
include/drm/drm_atomic_helper.h+26−0
@@ -28,6 +28,8 @@ · 27 unmodified lines
2828 #ifndef DRM_ATOMIC_HELPER_H_
2929 #define DRM_ATOMIC_HELPER_H_
3030
31+#include <drm/drm_crtc.h>
32+
3133 int drm_atomic_helper_check(struct drm_device *dev,
3234 struct drm_atomic_state *state);
3335 int 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
9698 void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
9799 struct drm_connector_state *state);
98100
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)
99125
100126 #endif /* DRM_ATOMIC_HELPER_H_ */
include/drm/drm_crtc.h+24−3
@@ -231,6 +231,7 @@ struct drm_atomic_state; · 230 unmodified lines
231231 * struct drm_crtc_state - mutable CRTC state
232232 * @enable: whether the CRTC should be enabled, gates all other state
233233 * @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
234235 * @last_vblank_count: for helpers and drivers to capture the vblank of the
235236 * update to ensure framebuffer cleanup isn't done too early
236237 * @planes_changed: for use by helpers and drivers when computing state updates
@@ -247,6 +248,13 @@ struct drm_crtc_state { · 10 unmodified lines
247248 bool planes_changed : 1;
248249 bool mode_changed : 1;
249250
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+
250258 /* last_vblank_count: for vblank waits before cleanup */
251259 u32 last_vblank_count;
252260
@@ -438,7 +446,7 @@ struct drm_crtc { · 185 unmodified lines
438446 * @state: backpointer to global drm_atomic_state
439447 */
440448 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() */
442450
443451 struct drm_encoder *best_encoder;
444452
@@ -673,8 +681,8 @@ struct drm_connector { · 228 unmodified lines
673681 * @state: backpointer to global drm_atomic_state
674682 */
675683 struct drm_plane_state {
676− struct drm_crtc *crtc;
677− struct drm_framebuffer *fb;
684+ struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */
685+ struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */
678686 struct fence *fence;
679687
680688 /* Signed dest location allows it to be partially off screen */
@@ -1054,6 +1062,19 @@ struct drm_mode_config { · 373 unmodified lines
10541062 uint32_t cursor_width, cursor_height;
10551063 };
10561064
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+
10571078 #define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
10581079 #define obj_to_connector(x) container_of(x, struct drm_connector, base)
10591080 #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
4949
5050 /**
5151 * 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
5256 *
5357 * The helper operations are called by the mid-layer CRTC helper.
5458 */
@@ -60,7 +64,8 @@ struct drm_plane_helper_funcs { · 5 unmodified lines
6064
6165 int (*atomic_check)(struct drm_plane *plane,
6266 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);
6469 };
6570
6671 static inline void drm_plane_helper_add(struct drm_plane *plane,