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. Signed-off-by: Thierry Reding <treding@xxxxxxxxxx> --- drivers/gpu/drm/drm_atomic_helper.c | 90 +++++++++++++++++++++++++++++++++++++ include/drm/drm_atomic_helper.h | 2 + 2 files changed, 92 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index fd06595c2ee5..f842499ca79e 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2358,6 +2358,96 @@ 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. + * + * 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_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; + struct drm_connector *conn; + struct drm_plane *plane; + struct drm_crtc *crtc; + int err; + + state = drm_atomic_state_alloc(dev); + if (!state) + return ERR_PTR(-ENOMEM); + + drm_modeset_acquire_init(&ctx, 0); + state->acquire_ctx = &ctx; + + err = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx); + if (err < 0) + goto free; + + drm_for_each_crtc(crtc, dev) { + unsigned int index = drm_crtc_index(crtc); + struct drm_crtc_state *crtc_state; + + crtc_state = crtc->funcs->atomic_duplicate_state(crtc); + if (!crtc_state) { + err = -ENOMEM; + goto unlock; + } + + state->crtc_states[index] = crtc_state; + state->crtcs[index] = crtc; + crtc_state->state = state; + } + + drm_for_each_plane(plane, dev) { + unsigned int index = drm_plane_index(plane); + struct drm_plane_state *plane_state; + + plane_state = plane->funcs->atomic_duplicate_state(plane); + if (!plane_state) { + err = -ENOMEM; + goto unlock; + } + + state->plane_states[index] = plane_state; + state->planes[index] = plane; + plane_state->state = state; + } + + drm_for_each_connector(conn, dev) { + unsigned int index = drm_connector_index(conn); + struct drm_connector_state *conn_state; + + conn_state = conn->funcs->atomic_duplicate_state(conn); + if (!conn_state) { + err = -ENOMEM; + goto unlock; + } + + state->connector_states[index] = conn_state; + state->connectors[index] = conn; + conn_state->state = state; + } + +unlock: + drm_modeset_drop_locks(&ctx); +free: + drm_modeset_acquire_fini(&ctx); + + 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