[PATCH 1/3] drm: atomic-helper: Implement drm_atomic_helper_duplicate_state()

Thierry Reding thierry.reding at gmail.com
Tue Aug 11 04:37:43 PDT 2015


From: Thierry Reding <treding at nvidia.com>

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 at nvidia.com>
---
 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



More information about the dri-devel mailing list