@@ -3140,6 +3140,7 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev,
struct drm_atomic_state *state;
struct drm_connector *conn;
struct drm_connector_list_iter conn_iter;
+ struct drm_private_obj *priv_obj;
struct drm_plane *plane;
struct drm_crtc *crtc;
int err = 0;
@@ -3184,6 +3185,19 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev,
}
drm_connector_list_iter_end(&conn_iter);
+ drm_for_each_privobj(priv_obj, dev) {
+ struct drm_private_state *priv_state;
+
+ if (!priv_obj->needs_duplicate_state)
+ continue;
+
+ priv_state = drm_atomic_get_private_obj_state(state, priv_obj);
+ if (IS_ERR(priv_state)) {
+ err = PTR_ERR(priv_state);
+ goto free;
+ }
+ }
+
/* clear the acquire context so that it isn't accidentally reused */
state->acquire_ctx = NULL;
@@ -3278,6 +3292,8 @@ int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
struct drm_connector_state *new_conn_state;
struct drm_crtc *crtc;
struct drm_crtc_state *new_crtc_state;
+ struct drm_private_state *new_priv_state;
+ struct drm_private_obj *priv_obj;
state->acquire_ctx = ctx;
@@ -3290,6 +3306,12 @@ int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
for_each_new_connector_in_state(state, connector, new_conn_state, i)
state->connectors[i].old_state = connector->state;
+ for_each_new_private_obj_in_state(state, priv_obj, new_priv_state, i) {
+ if (!priv_obj->needs_duplicate_state)
+ continue;
+ state->private_objs[i].old_state = priv_obj->state;
+ }
+
ret = drm_atomic_commit(state);
state->acquire_ctx = NULL;
@@ -139,6 +139,13 @@ static int mdp5_global_obj_init(struct mdp5_kms *mdp5_kms)
drm_atomic_private_obj_init(mdp5_kms->dev, &mdp5_kms->glob_state,
&state->base,
&mdp5_global_state_funcs);
+
+ /*
+ * Set needs_duplicate_state flag, as we have assignment of hwpipe in
+ * global atomic state that needs to be duplicated for suspend state.
+ */
+ mdp5_kms->glob_state.needs_duplicate_state = true;
+
return 0;
}
@@ -273,6 +273,17 @@ struct drm_private_obj {
* &drm_private_state_funcs.
*/
const struct drm_private_state_funcs *funcs;
+
+ /**
+ * @needs_duplicate_state:
+ *
+ * A flag that's set by driver in order to duplicate the state of this
+ * private object in drm_atomic_helper_duplicate_state(). It's required
+ * by drivers like msm/mdp5 where the state is used as the driver global
+ * atomic state, and needs to be duplicated in context of suspend helper
+ * drm_atomic_helper_suspend(), restored on drm_atomic_helper_resume().
+ */
+ bool needs_duplicate_state;
};
/**