From: Thierry Reding <treding@xxxxxxxxxx> This function can be used to duplicate an atomic state object. This is useful for example to implement suspend/resume, where the state before suspend can be saved and restored upon resume. v2: move locking to caller, be more explicit about prerequisites Signed-off-by: Thierry Reding <treding@xxxxxxxxxx> --- drivers/gpu/drm/drm_atomic_helper.c | 80 +++++++++++++++++++++++++++++++++++++ include/drm/drm_atomic_helper.h | 2 + 2 files changed, 82 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index fd06595c2ee5..1f84df3b0a5d 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2358,6 +2358,86 @@ drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state); /** + * drm_atomic_helper_duplicate_state - duplicate an atomic state object + * @dev: DRM device + * + * Makes a copy of the current atomic state by looping over all objects and + * duplicating their respective states. This is used for example by suspend/ + * resume support code to save the state prior to suspend such that it can + * be restored upon resume. + * + * Note that this treats atomic state as persistent between save and restore. + * Drivers must make sure that this is guaranteed. + * + * Calls to this function must be guarded by drm_modeset_lock_all() and + * drm_modeset_unlock_all(). + * + * Returns: + * A pointer to the copy of the atomic state object on success or an + * ERR_PTR()-encoded error code on failure. + */ +struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev) +{ + struct drm_atomic_state *state; + struct drm_connector *conn; + struct drm_plane *plane; + struct drm_crtc *crtc; + int err = 0; + + if (WARN_ON(!dev->mode_config.acquire_ctx)) + return ERR_PTR(-EINVAL); + + state = drm_atomic_state_alloc(dev); + if (!state) + return ERR_PTR(-ENOMEM); + + state->acquire_ctx = dev->mode_config.acquire_ctx; + + drm_for_each_crtc(crtc, dev) { + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + err = PTR_ERR(crtc_state); + goto free; + } + } + + drm_for_each_plane(plane, dev) { + struct drm_plane_state *plane_state; + + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + err = PTR_ERR(plane_state); + goto free; + } + } + + drm_for_each_connector(conn, dev) { + struct drm_connector_state *conn_state; + + conn_state = drm_atomic_get_connector_state(state, conn); + if (IS_ERR(conn_state)) { + err = PTR_ERR(conn_state); + goto free; + } + } + + /* clear the acquire context so that it isn't accidentally reused */ + state->acquire_ctx = NULL; + +free: + if (err < 0) { + drm_atomic_state_free(state); + state = ERR_PTR(err); + } + + return state; +} +EXPORT_SYMBOL(drm_atomic_helper_duplicate_state); + +/** * __drm_atomic_helper_connector_destroy_state - release connector state * @connector: connector object * @state: connector state object to release diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 4ffe9dca07c4..5d27612997ce 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -118,6 +118,8 @@ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, struct drm_connector_state *state); struct drm_connector_state * drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); +struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev); void __drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state); -- 2.4.5 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel