aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_atomic_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_atomic_helper.c')
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c316
1 files changed, 235 insertions, 81 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index aecb5d69bc2d..87a2a446d2b7 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -42,14 +42,14 @@
42 * add their own additional internal state. 42 * add their own additional internal state.
43 * 43 *
44 * This library also provides default implementations for the check callback in 44 * This library also provides default implementations for the check callback in
45 * drm_atomic_helper_check and for the commit callback with 45 * drm_atomic_helper_check() and for the commit callback with
46 * drm_atomic_helper_commit. But the individual stages and callbacks are expose 46 * drm_atomic_helper_commit(). But the individual stages and callbacks are
47 * to allow drivers to mix and match and e.g. use the plane helpers only 47 * exposed to allow drivers to mix and match and e.g. use the plane helpers only
48 * together with a driver private modeset implementation. 48 * together with a driver private modeset implementation.
49 * 49 *
50 * This library also provides implementations for all the legacy driver 50 * This library also provides implementations for all the legacy driver
51 * interfaces on top of the atomic interface. See drm_atomic_helper_set_config, 51 * interfaces on top of the atomic interface. See drm_atomic_helper_set_config(),
52 * drm_atomic_helper_disable_plane, drm_atomic_helper_disable_plane and the 52 * drm_atomic_helper_disable_plane(), drm_atomic_helper_disable_plane() and the
53 * various functions to implement set_property callbacks. New drivers must not 53 * various functions to implement set_property callbacks. New drivers must not
54 * implement these functions themselves but must use the provided helpers. 54 * implement these functions themselves but must use the provided helpers.
55 */ 55 */
@@ -993,6 +993,22 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
993 * object. This can still fail when e.g. the framebuffer reservation fails. For 993 * object. This can still fail when e.g. the framebuffer reservation fails. For
994 * now this doesn't implement asynchronous commits. 994 * now this doesn't implement asynchronous commits.
995 * 995 *
996 * Note that right now this function does not support async commits, and hence
997 * driver writers must implement their own version for now. Also note that the
998 * default ordering of how the various stages are called is to match the legacy
999 * modeset helper library closest. One peculiarity of that is that it doesn't
1000 * mesh well with runtime PM at all.
1001 *
1002 * For drivers supporting runtime PM the recommended sequence is
1003 *
1004 * drm_atomic_helper_commit_modeset_disables(dev, state);
1005 *
1006 * drm_atomic_helper_commit_modeset_enables(dev, state);
1007 *
1008 * drm_atomic_helper_commit_planes(dev, state, true);
1009 *
1010 * See the kerneldoc entries for these three functions for more details.
1011 *
996 * RETURNS 1012 * RETURNS
997 * Zero for success or -errno. 1013 * Zero for success or -errno.
998 */ 1014 */
@@ -1037,7 +1053,7 @@ int drm_atomic_helper_commit(struct drm_device *dev,
1037 1053
1038 drm_atomic_helper_commit_modeset_disables(dev, state); 1054 drm_atomic_helper_commit_modeset_disables(dev, state);
1039 1055
1040 drm_atomic_helper_commit_planes(dev, state); 1056 drm_atomic_helper_commit_planes(dev, state, false);
1041 1057
1042 drm_atomic_helper_commit_modeset_enables(dev, state); 1058 drm_atomic_helper_commit_modeset_enables(dev, state);
1043 1059
@@ -1077,7 +1093,7 @@ EXPORT_SYMBOL(drm_atomic_helper_commit);
1077 * work item, which allows nice concurrent updates on disjoint sets of crtcs. 1093 * work item, which allows nice concurrent updates on disjoint sets of crtcs.
1078 * 1094 *
1079 * 3. The software state is updated synchronously with 1095 * 3. The software state is updated synchronously with
1080 * drm_atomic_helper_swap_state. Doing this under the protection of all modeset 1096 * drm_atomic_helper_swap_state(). Doing this under the protection of all modeset
1081 * locks means concurrent callers never see inconsistent state. And doing this 1097 * locks means concurrent callers never see inconsistent state. And doing this
1082 * while it's guaranteed that no relevant async worker runs means that async 1098 * while it's guaranteed that no relevant async worker runs means that async
1083 * workers do not need grab any locks. Actually they must not grab locks, for 1099 * workers do not need grab any locks. Actually they must not grab locks, for
@@ -1111,17 +1127,14 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
1111 const struct drm_plane_helper_funcs *funcs; 1127 const struct drm_plane_helper_funcs *funcs;
1112 struct drm_plane *plane = state->planes[i]; 1128 struct drm_plane *plane = state->planes[i];
1113 struct drm_plane_state *plane_state = state->plane_states[i]; 1129 struct drm_plane_state *plane_state = state->plane_states[i];
1114 struct drm_framebuffer *fb;
1115 1130
1116 if (!plane) 1131 if (!plane)
1117 continue; 1132 continue;
1118 1133
1119 funcs = plane->helper_private; 1134 funcs = plane->helper_private;
1120 1135
1121 fb = plane_state->fb; 1136 if (funcs->prepare_fb) {
1122 1137 ret = funcs->prepare_fb(plane, plane_state);
1123 if (fb && funcs->prepare_fb) {
1124 ret = funcs->prepare_fb(plane, fb, plane_state);
1125 if (ret) 1138 if (ret)
1126 goto fail; 1139 goto fail;
1127 } 1140 }
@@ -1134,17 +1147,14 @@ fail:
1134 const struct drm_plane_helper_funcs *funcs; 1147 const struct drm_plane_helper_funcs *funcs;
1135 struct drm_plane *plane = state->planes[i]; 1148 struct drm_plane *plane = state->planes[i];
1136 struct drm_plane_state *plane_state = state->plane_states[i]; 1149 struct drm_plane_state *plane_state = state->plane_states[i];
1137 struct drm_framebuffer *fb;
1138 1150
1139 if (!plane) 1151 if (!plane)
1140 continue; 1152 continue;
1141 1153
1142 funcs = plane->helper_private; 1154 funcs = plane->helper_private;
1143 1155
1144 fb = state->plane_states[i]->fb; 1156 if (funcs->cleanup_fb)
1145 1157 funcs->cleanup_fb(plane, plane_state);
1146 if (fb && funcs->cleanup_fb)
1147 funcs->cleanup_fb(plane, fb, plane_state);
1148 1158
1149 } 1159 }
1150 1160
@@ -1152,10 +1162,16 @@ fail:
1152} 1162}
1153EXPORT_SYMBOL(drm_atomic_helper_prepare_planes); 1163EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
1154 1164
1165bool plane_crtc_active(struct drm_plane_state *state)
1166{
1167 return state->crtc && state->crtc->state->active;
1168}
1169
1155/** 1170/**
1156 * drm_atomic_helper_commit_planes - commit plane state 1171 * drm_atomic_helper_commit_planes - commit plane state
1157 * @dev: DRM device 1172 * @dev: DRM device
1158 * @old_state: atomic state object with old state structures 1173 * @old_state: atomic state object with old state structures
1174 * @active_only: Only commit on active CRTC if set
1159 * 1175 *
1160 * This function commits the new plane state using the plane and atomic helper 1176 * This function commits the new plane state using the plane and atomic helper
1161 * functions for planes and crtcs. It assumes that the atomic state has already 1177 * functions for planes and crtcs. It assumes that the atomic state has already
@@ -1168,9 +1184,26 @@ EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
1168 * Note that this function does all plane updates across all CRTCs in one step. 1184 * Note that this function does all plane updates across all CRTCs in one step.
1169 * If the hardware can't support this approach look at 1185 * If the hardware can't support this approach look at
1170 * drm_atomic_helper_commit_planes_on_crtc() instead. 1186 * drm_atomic_helper_commit_planes_on_crtc() instead.
1187 *
1188 * Plane parameters can be updated by applications while the associated CRTC is
1189 * disabled. The DRM/KMS core will store the parameters in the plane state,
1190 * which will be available to the driver when the CRTC is turned on. As a result
1191 * most drivers don't need to be immediately notified of plane updates for a
1192 * disabled CRTC.
1193 *
1194 * Unless otherwise needed, drivers are advised to set the @active_only
1195 * parameters to true in order not to receive plane update notifications related
1196 * to a disabled CRTC. This avoids the need to manually ignore plane updates in
1197 * driver code when the driver and/or hardware can't or just don't need to deal
1198 * with updates on disabled CRTCs, for example when supporting runtime PM.
1199 *
1200 * The drm_atomic_helper_commit() default implementation only sets @active_only
1201 * to false to most closely match the behaviour of the legacy helpers. This should
1202 * not be copied blindly by drivers.
1171 */ 1203 */
1172void drm_atomic_helper_commit_planes(struct drm_device *dev, 1204void drm_atomic_helper_commit_planes(struct drm_device *dev,
1173 struct drm_atomic_state *old_state) 1205 struct drm_atomic_state *old_state,
1206 bool active_only)
1174{ 1207{
1175 struct drm_crtc *crtc; 1208 struct drm_crtc *crtc;
1176 struct drm_crtc_state *old_crtc_state; 1209 struct drm_crtc_state *old_crtc_state;
@@ -1186,25 +1219,43 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
1186 if (!funcs || !funcs->atomic_begin) 1219 if (!funcs || !funcs->atomic_begin)
1187 continue; 1220 continue;
1188 1221
1222 if (active_only && !crtc->state->active)
1223 continue;
1224
1189 funcs->atomic_begin(crtc, old_crtc_state); 1225 funcs->atomic_begin(crtc, old_crtc_state);
1190 } 1226 }
1191 1227
1192 for_each_plane_in_state(old_state, plane, old_plane_state, i) { 1228 for_each_plane_in_state(old_state, plane, old_plane_state, i) {
1193 const struct drm_plane_helper_funcs *funcs; 1229 const struct drm_plane_helper_funcs *funcs;
1230 bool disabling;
1194 1231
1195 funcs = plane->helper_private; 1232 funcs = plane->helper_private;
1196 1233
1197 if (!funcs) 1234 if (!funcs)
1198 continue; 1235 continue;
1199 1236
1237 disabling = drm_atomic_plane_disabling(plane, old_plane_state);
1238
1239 if (active_only) {
1240 /*
1241 * Skip planes related to inactive CRTCs. If the plane
1242 * is enabled use the state of the current CRTC. If the
1243 * plane is being disabled use the state of the old
1244 * CRTC to avoid skipping planes being disabled on an
1245 * active CRTC.
1246 */
1247 if (!disabling && !plane_crtc_active(plane->state))
1248 continue;
1249 if (disabling && !plane_crtc_active(old_plane_state))
1250 continue;
1251 }
1252
1200 /* 1253 /*
1201 * Special-case disabling the plane if drivers support it. 1254 * Special-case disabling the plane if drivers support it.
1202 */ 1255 */
1203 if (drm_atomic_plane_disabling(plane, old_plane_state) && 1256 if (disabling && funcs->atomic_disable)
1204 funcs->atomic_disable)
1205 funcs->atomic_disable(plane, old_plane_state); 1257 funcs->atomic_disable(plane, old_plane_state);
1206 else if (plane->state->crtc || 1258 else if (plane->state->crtc || disabling)
1207 drm_atomic_plane_disabling(plane, old_plane_state))
1208 funcs->atomic_update(plane, old_plane_state); 1259 funcs->atomic_update(plane, old_plane_state);
1209 } 1260 }
1210 1261
@@ -1216,6 +1267,9 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
1216 if (!funcs || !funcs->atomic_flush) 1267 if (!funcs || !funcs->atomic_flush)
1217 continue; 1268 continue;
1218 1269
1270 if (active_only && !crtc->state->active)
1271 continue;
1272
1219 funcs->atomic_flush(crtc, old_crtc_state); 1273 funcs->atomic_flush(crtc, old_crtc_state);
1220 } 1274 }
1221} 1275}
@@ -1300,14 +1354,11 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
1300 1354
1301 for_each_plane_in_state(old_state, plane, plane_state, i) { 1355 for_each_plane_in_state(old_state, plane, plane_state, i) {
1302 const struct drm_plane_helper_funcs *funcs; 1356 const struct drm_plane_helper_funcs *funcs;
1303 struct drm_framebuffer *old_fb;
1304 1357
1305 funcs = plane->helper_private; 1358 funcs = plane->helper_private;
1306 1359
1307 old_fb = plane_state->fb; 1360 if (funcs->cleanup_fb)
1308 1361 funcs->cleanup_fb(plane, plane_state);
1309 if (old_fb && funcs->cleanup_fb)
1310 funcs->cleanup_fb(plane, old_fb, plane_state);
1311 } 1362 }
1312} 1363}
1313EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes); 1364EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
@@ -1334,7 +1385,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
1334 * 1385 *
1335 * 4. Actually commit the hardware state. 1386 * 4. Actually commit the hardware state.
1336 * 1387 *
1337 * 5. Call drm_atomic_helper_cleanup_planes with @state, which since step 3 1388 * 5. Call drm_atomic_helper_cleanup_planes() with @state, which since step 3
1338 * contains the old state. Also do any other cleanup required with that state. 1389 * contains the old state. Also do any other cleanup required with that state.
1339 */ 1390 */
1340void drm_atomic_helper_swap_state(struct drm_device *dev, 1391void drm_atomic_helper_swap_state(struct drm_device *dev,
@@ -1502,21 +1553,9 @@ retry:
1502 goto fail; 1553 goto fail;
1503 } 1554 }
1504 1555
1505 ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); 1556 ret = __drm_atomic_helper_disable_plane(plane, plane_state);
1506 if (ret != 0) 1557 if (ret != 0)
1507 goto fail; 1558 goto fail;
1508 drm_atomic_set_fb_for_plane(plane_state, NULL);
1509 plane_state->crtc_x = 0;
1510 plane_state->crtc_y = 0;
1511 plane_state->crtc_h = 0;
1512 plane_state->crtc_w = 0;
1513 plane_state->src_x = 0;
1514 plane_state->src_y = 0;
1515 plane_state->src_h = 0;
1516 plane_state->src_w = 0;
1517
1518 if (plane == plane->crtc->cursor)
1519 state->legacy_cursor_update = true;
1520 1559
1521 ret = drm_atomic_commit(state); 1560 ret = drm_atomic_commit(state);
1522 if (ret != 0) 1561 if (ret != 0)
@@ -1546,6 +1585,32 @@ backoff:
1546} 1585}
1547EXPORT_SYMBOL(drm_atomic_helper_disable_plane); 1586EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
1548 1587
1588/* just used from fb-helper and atomic-helper: */
1589int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
1590 struct drm_plane_state *plane_state)
1591{
1592 int ret;
1593
1594 ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
1595 if (ret != 0)
1596 return ret;
1597
1598 drm_atomic_set_fb_for_plane(plane_state, NULL);
1599 plane_state->crtc_x = 0;
1600 plane_state->crtc_y = 0;
1601 plane_state->crtc_h = 0;
1602 plane_state->crtc_w = 0;
1603 plane_state->src_x = 0;
1604 plane_state->src_y = 0;
1605 plane_state->src_h = 0;
1606 plane_state->src_w = 0;
1607
1608 if (plane->crtc && (plane == plane->crtc->cursor))
1609 plane_state->state->legacy_cursor_update = true;
1610
1611 return 0;
1612}
1613
1549static int update_output_state(struct drm_atomic_state *state, 1614static int update_output_state(struct drm_atomic_state *state,
1550 struct drm_mode_set *set) 1615 struct drm_mode_set *set)
1551{ 1616{
@@ -1629,8 +1694,6 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set)
1629{ 1694{
1630 struct drm_atomic_state *state; 1695 struct drm_atomic_state *state;
1631 struct drm_crtc *crtc = set->crtc; 1696 struct drm_crtc *crtc = set->crtc;
1632 struct drm_crtc_state *crtc_state;
1633 struct drm_plane_state *primary_state;
1634 int ret = 0; 1697 int ret = 0;
1635 1698
1636 state = drm_atomic_state_alloc(crtc->dev); 1699 state = drm_atomic_state_alloc(crtc->dev);
@@ -1639,17 +1702,54 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set)
1639 1702
1640 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); 1703 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
1641retry: 1704retry:
1642 crtc_state = drm_atomic_get_crtc_state(state, crtc); 1705 ret = __drm_atomic_helper_set_config(set, state);
1643 if (IS_ERR(crtc_state)) { 1706 if (ret != 0)
1644 ret = PTR_ERR(crtc_state);
1645 goto fail; 1707 goto fail;
1646 }
1647 1708
1648 primary_state = drm_atomic_get_plane_state(state, crtc->primary); 1709 ret = drm_atomic_commit(state);
1649 if (IS_ERR(primary_state)) { 1710 if (ret != 0)
1650 ret = PTR_ERR(primary_state);
1651 goto fail; 1711 goto fail;
1652 } 1712
1713 /* Driver takes ownership of state on successful commit. */
1714 return 0;
1715fail:
1716 if (ret == -EDEADLK)
1717 goto backoff;
1718
1719 drm_atomic_state_free(state);
1720
1721 return ret;
1722backoff:
1723 drm_atomic_state_clear(state);
1724 drm_atomic_legacy_backoff(state);
1725
1726 /*
1727 * Someone might have exchanged the framebuffer while we dropped locks
1728 * in the backoff code. We need to fix up the fb refcount tracking the
1729 * core does for us.
1730 */
1731 crtc->primary->old_fb = crtc->primary->fb;
1732
1733 goto retry;
1734}
1735EXPORT_SYMBOL(drm_atomic_helper_set_config);
1736
1737/* just used from fb-helper and atomic-helper: */
1738int __drm_atomic_helper_set_config(struct drm_mode_set *set,
1739 struct drm_atomic_state *state)
1740{
1741 struct drm_crtc_state *crtc_state;
1742 struct drm_plane_state *primary_state;
1743 struct drm_crtc *crtc = set->crtc;
1744 int ret;
1745
1746 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1747 if (IS_ERR(crtc_state))
1748 return PTR_ERR(crtc_state);
1749
1750 primary_state = drm_atomic_get_plane_state(state, crtc->primary);
1751 if (IS_ERR(primary_state))
1752 return PTR_ERR(primary_state);
1653 1753
1654 if (!set->mode) { 1754 if (!set->mode) {
1655 WARN_ON(set->fb); 1755 WARN_ON(set->fb);
@@ -1657,13 +1757,13 @@ retry:
1657 1757
1658 ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL); 1758 ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
1659 if (ret != 0) 1759 if (ret != 0)
1660 goto fail; 1760 return ret;
1661 1761
1662 crtc_state->active = false; 1762 crtc_state->active = false;
1663 1763
1664 ret = drm_atomic_set_crtc_for_plane(primary_state, NULL); 1764 ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
1665 if (ret != 0) 1765 if (ret != 0)
1666 goto fail; 1766 return ret;
1667 1767
1668 drm_atomic_set_fb_for_plane(primary_state, NULL); 1768 drm_atomic_set_fb_for_plane(primary_state, NULL);
1669 1769
@@ -1675,13 +1775,14 @@ retry:
1675 1775
1676 ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode); 1776 ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode);
1677 if (ret != 0) 1777 if (ret != 0)
1678 goto fail; 1778 return ret;
1679 1779
1680 crtc_state->active = true; 1780 crtc_state->active = true;
1681 1781
1682 ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); 1782 ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
1683 if (ret != 0) 1783 if (ret != 0)
1684 goto fail; 1784 return ret;
1785
1685 drm_atomic_set_fb_for_plane(primary_state, set->fb); 1786 drm_atomic_set_fb_for_plane(primary_state, set->fb);
1686 primary_state->crtc_x = 0; 1787 primary_state->crtc_x = 0;
1687 primary_state->crtc_y = 0; 1788 primary_state->crtc_y = 0;
@@ -1695,35 +1796,10 @@ retry:
1695commit: 1796commit:
1696 ret = update_output_state(state, set); 1797 ret = update_output_state(state, set);
1697 if (ret) 1798 if (ret)
1698 goto fail; 1799 return ret;
1699
1700 ret = drm_atomic_commit(state);
1701 if (ret != 0)
1702 goto fail;
1703 1800
1704 /* Driver takes ownership of state on successful commit. */
1705 return 0; 1801 return 0;
1706fail:
1707 if (ret == -EDEADLK)
1708 goto backoff;
1709
1710 drm_atomic_state_free(state);
1711
1712 return ret;
1713backoff:
1714 drm_atomic_state_clear(state);
1715 drm_atomic_legacy_backoff(state);
1716
1717 /*
1718 * Someone might have exchanged the framebuffer while we dropped locks
1719 * in the backoff code. We need to fix up the fb refcount tracking the
1720 * core does for us.
1721 */
1722 crtc->primary->old_fb = crtc->primary->fb;
1723
1724 goto retry;
1725} 1802}
1726EXPORT_SYMBOL(drm_atomic_helper_set_config);
1727 1803
1728/** 1804/**
1729 * drm_atomic_helper_crtc_set_property - helper for crtc properties 1805 * drm_atomic_helper_crtc_set_property - helper for crtc properties
@@ -2333,6 +2409,84 @@ drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
2333EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state); 2409EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
2334 2410
2335/** 2411/**
2412 * drm_atomic_helper_duplicate_state - duplicate an atomic state object
2413 * @dev: DRM device
2414 * @ctx: lock acquisition context
2415 *
2416 * Makes a copy of the current atomic state by looping over all objects and
2417 * duplicating their respective states.
2418 *
2419 * Note that this treats atomic state as persistent between save and restore.
2420 * Drivers must make sure that this is possible and won't result in confusion
2421 * or erroneous behaviour.
2422 *
2423 * Note that if callers haven't already acquired all modeset locks this might
2424 * return -EDEADLK, which must be handled by calling drm_modeset_backoff().
2425 *
2426 * Returns:
2427 * A pointer to the copy of the atomic state object on success or an
2428 * ERR_PTR()-encoded error code on failure.
2429 */
2430struct drm_atomic_state *
2431drm_atomic_helper_duplicate_state(struct drm_device *dev,
2432 struct drm_modeset_acquire_ctx *ctx)
2433{
2434 struct drm_atomic_state *state;
2435 struct drm_connector *conn;
2436 struct drm_plane *plane;
2437 struct drm_crtc *crtc;
2438 int err = 0;
2439
2440 state = drm_atomic_state_alloc(dev);
2441 if (!state)
2442 return ERR_PTR(-ENOMEM);
2443
2444 state->acquire_ctx = ctx;
2445
2446 drm_for_each_crtc(crtc, dev) {
2447 struct drm_crtc_state *crtc_state;
2448
2449 crtc_state = drm_atomic_get_crtc_state(state, crtc);
2450 if (IS_ERR(crtc_state)) {
2451 err = PTR_ERR(crtc_state);
2452 goto free;
2453 }
2454 }
2455
2456 drm_for_each_plane(plane, dev) {
2457 struct drm_plane_state *plane_state;
2458
2459 plane_state = drm_atomic_get_plane_state(state, plane);
2460 if (IS_ERR(plane_state)) {
2461 err = PTR_ERR(plane_state);
2462 goto free;
2463 }
2464 }
2465
2466 drm_for_each_connector(conn, dev) {
2467 struct drm_connector_state *conn_state;
2468
2469 conn_state = drm_atomic_get_connector_state(state, conn);
2470 if (IS_ERR(conn_state)) {
2471 err = PTR_ERR(conn_state);
2472 goto free;
2473 }
2474 }
2475
2476 /* clear the acquire context so that it isn't accidentally reused */
2477 state->acquire_ctx = NULL;
2478
2479free:
2480 if (err < 0) {
2481 drm_atomic_state_free(state);
2482 state = ERR_PTR(err);
2483 }
2484
2485 return state;
2486}
2487EXPORT_SYMBOL(drm_atomic_helper_duplicate_state);
2488
2489/**
2336 * __drm_atomic_helper_connector_destroy_state - release connector state 2490 * __drm_atomic_helper_connector_destroy_state - release connector state
2337 * @connector: connector object 2491 * @connector: connector object
2338 * @state: connector state object to release 2492 * @state: connector state object to release