Эх сурвалжийг харах

disp: msm: add connector state along with crtc state to detect modeset

During modeset, private mode changed is detected from
msm_display_mode which is present in sde_connector_state.
In the current code, sde_connector_state is found from the
drm_connector variable which will not be valid
during atomic check phase and new connector state is
required here. To handle this, drm_connector_state is passed
along with the drm_crtc_state while detecting
msm_atomic_needs_modeset condition.

Change-Id: I62c162eff6e1c091cb05b3f049a40a0f25b710ba
Signed-off-by: Yashwanth <[email protected]>
Yashwanth 4 жил өмнө
parent
commit
ffc7cdbe08

+ 42 - 9
msm/msm_atomic.c

@@ -35,6 +35,31 @@ struct msm_commit {
 	struct kthread_work commit_work;
 };
 
+static struct drm_connector_state *_msm_get_conn_state(struct drm_crtc_state *crtc_state)
+{
+	struct drm_connector *conn;
+	struct drm_connector_state *conn_state = NULL;
+	struct drm_device *dev;
+	struct drm_connector_list_iter conn_iter;
+
+	if (!crtc_state || !crtc_state->crtc)
+		return NULL;
+
+	dev = crtc_state->crtc->dev;
+	drm_connector_list_iter_begin(dev, &conn_iter);
+
+	drm_for_each_connector_iter(conn, &conn_iter) {
+		if (drm_connector_mask(conn) & crtc_state->connector_mask) {
+			if (!(conn_state && conn->connector_type ==
+					DRM_MODE_CONNECTOR_VIRTUAL))
+				conn_state = conn->state;
+		}
+	}
+
+	drm_connector_list_iter_end(&conn_iter);
+	return conn_state;
+}
+
 static inline bool _msm_seamless_for_crtc(struct drm_atomic_state *state,
 			struct drm_crtc_state *crtc_state, bool enable)
 {
@@ -48,7 +73,7 @@ static inline bool _msm_seamless_for_crtc(struct drm_atomic_state *state,
 	if (!priv || !priv->kms || !priv->kms->funcs->get_msm_mode)
 		return false;
 
-	msm_mode = priv->kms->funcs->get_msm_mode(crtc_state);
+	msm_mode = priv->kms->funcs->get_msm_mode(_msm_get_conn_state(crtc_state));
 	if (!msm_mode)
 		return false;
 
@@ -103,7 +128,8 @@ static inline bool _msm_seamless_for_conn(struct drm_connector *connector,
 	if (!priv || !priv->kms || !priv->kms->funcs->get_msm_mode)
 		return false;
 
-	msm_mode = priv->kms->funcs->get_msm_mode(old_conn_state->crtc->state);
+	msm_mode = priv->kms->funcs->get_msm_mode(
+			_msm_get_conn_state(old_conn_state->crtc->state));
 	if (!msm_mode)
 		return false;
 
@@ -180,7 +206,8 @@ msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
 							old_conn_state->crtc);
 
 		if (!old_crtc_state->active ||
-		    !msm_atomic_needs_modeset(old_conn_state->crtc->state))
+		    !msm_atomic_needs_modeset(old_conn_state->crtc->state,
+				_msm_get_conn_state(old_conn_state->crtc->state)))
 			continue;
 
 		encoder = old_conn_state->best_encoder;
@@ -221,7 +248,8 @@ msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
 		const struct drm_crtc_helper_funcs *funcs;
 
 		/* Shut down everything that needs a full modeset. */
-		if (!msm_atomic_needs_modeset(crtc->state))
+		if (!msm_atomic_needs_modeset(crtc->state,
+				_msm_get_conn_state(crtc->state)))
 			continue;
 
 		if (!old_crtc_state->active)
@@ -294,7 +322,8 @@ msm_crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
 					old_conn_state, false))
 				continue;
 		} else if (!new_crtc_state->mode_changed) {
-			if (!msm_is_private_mode_changed(old_conn_state->crtc->state))
+			if (!msm_is_private_mode_changed(
+					_msm_get_conn_state(old_conn_state->crtc->state)))
 				continue;
 		}
 
@@ -373,7 +402,8 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 		struct msm_display_mode *msm_mode;
 
 		/* Need to filter out CRTCs where only planes change. */
-		if (!msm_atomic_needs_modeset(new_crtc_state))
+		if (!msm_atomic_needs_modeset(new_crtc_state,
+				_msm_get_conn_state(new_crtc_state)))
 			continue;
 
 		if (!new_crtc_state->active)
@@ -397,7 +427,8 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 		if (!kms->funcs || !kms->funcs->get_msm_mode)
 			continue;
 
-		msm_mode = kms->funcs->get_msm_mode(new_crtc_state);
+		msm_mode = kms->funcs->get_msm_mode(
+			_msm_get_conn_state(new_crtc_state));
 		if (!msm_mode)
 			continue;
 
@@ -417,7 +448,8 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 			continue;
 
 		if (!new_conn_state->crtc->state->active ||
-				!msm_atomic_needs_modeset(new_conn_state->crtc->state))
+				!msm_atomic_needs_modeset(new_conn_state->crtc->state,
+					_msm_get_conn_state(new_conn_state->crtc->state)))
 			continue;
 
 		old_conn_state = drm_atomic_get_old_connector_state(
@@ -466,7 +498,8 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 			continue;
 
 		if (!new_conn_state->crtc->state->active ||
-		    !msm_atomic_needs_modeset(new_conn_state->crtc->state))
+		    !msm_atomic_needs_modeset(new_conn_state->crtc->state,
+				_msm_get_conn_state(new_conn_state->crtc->state)))
 			continue;
 
 		old_conn_state = drm_atomic_get_old_connector_state(

+ 8 - 7
msm/msm_kms.h

@@ -70,7 +70,7 @@ struct msm_kms_funcs {
 	void (*complete_commit)(struct msm_kms *kms,
 			struct drm_atomic_state *state);
 	struct msm_display_mode *(*get_msm_mode)(
-				struct drm_crtc_state *c_state);
+				struct drm_connector_state *c_state);
 	/* functions to wait for atomic commit completed on each CRTC */
 	void (*wait_for_crtc_commit_done)(struct msm_kms *kms,
 					struct drm_crtc *crtc);
@@ -268,16 +268,16 @@ static inline bool msm_needs_vblank_pre_modeset(
 }
 
 static inline bool msm_is_private_mode_changed(
-		struct drm_crtc_state *state)
+		struct drm_connector_state *conn_state)
 {
 	struct msm_display_mode *msm_mode = NULL;
 	struct msm_drm_private *priv = NULL;
 	struct msm_kms *kms;
 
-	if (!state || !state->crtc)
+	if (!conn_state || !conn_state->connector || !conn_state->connector->dev)
 		return false;
 
-	priv = state->crtc->dev->dev_private;
+	priv = conn_state->connector->dev->dev_private;
 	if (!priv)
 		return false;
 
@@ -285,7 +285,7 @@ static inline bool msm_is_private_mode_changed(
 	if (!kms || !kms->funcs->get_msm_mode)
 		return false;
 
-	msm_mode = kms->funcs->get_msm_mode(state);
+	msm_mode = kms->funcs->get_msm_mode(conn_state);
 	if (!msm_mode)
 		return false;
 
@@ -298,12 +298,13 @@ static inline bool msm_is_private_mode_changed(
 	return false;
 }
 
-static inline bool msm_atomic_needs_modeset(struct drm_crtc_state *state)
+static inline bool msm_atomic_needs_modeset(struct drm_crtc_state *state,
+		struct drm_connector_state *conn_state)
 {
 	if (drm_atomic_crtc_needs_modeset(state))
 		return true;
 
-	if (msm_is_private_mode_changed(state))
+	if (msm_is_private_mode_changed(conn_state))
 		return true;
 	return false;
 }

+ 1 - 1
msm/sde/sde_encoder.c

@@ -934,7 +934,7 @@ static int _sde_encoder_atomic_check_reserve(struct drm_encoder *drm_enc,
 	int ret = 0;
 	struct drm_display_mode *adj_mode = &crtc_state->adjusted_mode;
 
-	if (sde_conn && msm_atomic_needs_modeset(crtc_state)) {
+	if (sde_conn && msm_atomic_needs_modeset(crtc_state, conn_state)) {
 		struct msm_display_topology *topology = NULL;
 
 		ret = sde_connector_get_mode_info(&sde_conn->base,

+ 8 - 2
msm/sde/sde_kms.c

@@ -3584,9 +3584,15 @@ static void _sde_kms_pm_suspend_idle_helper(struct sde_kms *sde_kms,
 	kthread_flush_worker(&priv->pp_event_worker);
 }
 
-struct msm_display_mode *sde_kms_get_msm_mode(struct drm_crtc_state *c_state)
+struct msm_display_mode *sde_kms_get_msm_mode(struct drm_connector_state *conn_state)
 {
-	return sde_crtc_get_msm_mode(c_state);
+	struct sde_connector_state *sde_conn_state;
+
+	if (!conn_state)
+		return NULL;
+
+	sde_conn_state = to_sde_connector_state(conn_state);
+	return &sde_conn_state->msm_mode;
 }
 
 static int sde_kms_pm_suspend(struct device *dev)

+ 1 - 1
msm/sde/sde_rm.c

@@ -2519,7 +2519,7 @@ int sde_rm_reserve(
 
 	/* Check if this is just a page-flip */
 	if (!_sde_rm_is_display_in_cont_splash(sde_kms, enc) &&
-			!msm_atomic_needs_modeset(crtc_state))
+			!msm_atomic_needs_modeset(crtc_state, conn_state))
 		return 0;
 
 	comp_info = kzalloc(sizeof(*comp_info), GFP_KERNEL);