Przeglądaj źródła

disp: msm: sde: modify in_clone_mode after wb_reset is done

Add changes to modify the phys_enc->in_clone_mode variable
post wb_reset_state since this is a shared variable used
during atomic_check and atomic_commit. In current issue case,
wb_atomic_check has set in_clone_mode to true in commit N,
and in commit N-1 CWB is being disabled and re-sets the
in_clone_mode variable to false causing pp_done timeouts in
primary in commit N.

Change-Id: I8159bbdb5622a351d76bdc4dba75d48df20f4365
Signed-off-by: Jayaprakash Madisetty <[email protected]>
Signed-off-by: Samantha Tran <[email protected]>
Jayaprakash Madisetty 4 lat temu
rodzic
commit
436efb403c

+ 5 - 4
msm/sde/sde_crtc.c

@@ -549,7 +549,7 @@ static bool sde_crtc_mode_fixup(struct drm_crtc *crtc,
 
 	drm_for_each_encoder_mask(encoder, c_state->crtc->dev,
 		c_state->encoder_mask) {
-		if (!sde_encoder_in_clone_mode(encoder)) {
+		if (!sde_crtc_state_in_clone_mode(encoder, c_state)) {
 			encoder_valid = true;
 			break;
 		}
@@ -868,7 +868,7 @@ static int _sde_crtc_set_crtc_roi(struct drm_crtc *crtc,
 		 * This restriction should be relaxed when Connector ROI scaling is
 		 * supported and while in clone mode.
 		 */
-		if (!sde_encoder_in_clone_mode(sde_conn->encoder) &&
+		if (!sde_crtc_state_in_clone_mode(sde_conn->encoder, state) &&
 				is_conn_roi_dirty != is_crtc_roi_dirty) {
 			SDE_ERROR("connector/crtc rois not updated together\n");
 			return -EINVAL;
@@ -2549,7 +2549,7 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc,
 	dev = crtc->dev;
 	sde_crtc = to_sde_crtc(crtc);
 	cstate = to_sde_crtc_state(crtc->state);
-	SDE_EVT32_VERBOSE(DRMID(crtc));
+	SDE_EVT32_VERBOSE(DRMID(crtc), cstate->cwb_enc_mask);
 
 	SDE_ATRACE_BEGIN("sde_crtc_prepare_commit");
 
@@ -2569,6 +2569,7 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc,
 
 			cstate->connectors[cstate->num_connectors++] = conn;
 			sde_connector_prepare_fence(conn);
+			sde_encoder_set_clone_mode(encoder, crtc->state);
 		}
 	drm_connector_list_iter_end(&conn_iter);
 
@@ -2631,7 +2632,7 @@ enum sde_intf_mode sde_crtc_get_intf_mode(struct drm_crtc *crtc,
 	drm_for_each_encoder_mask(encoder, crtc->dev,
 			cstate->encoder_mask) {
 		/* continue if copy encoder is encountered */
-		if (sde_encoder_in_clone_mode(encoder))
+		if (sde_crtc_state_in_clone_mode(encoder, cstate))
 			continue;
 
 		return sde_encoder_get_intf_mode(encoder);

+ 18 - 0
msm/sde/sde_crtc.h

@@ -466,6 +466,7 @@ enum sde_crtc_dirty_flags {
  * @property_values: Current crtc property values
  * @input_fence_timeout_ns : Cached input fence timeout, in ns
  * @num_dim_layers: Number of dim layers
+ * @cwb_enc_mask  : encoder mask populated during atomic_check if CWB is enabled
  * @dim_layer: Dim layer configs
  * @num_ds: Number of destination scalers to be configured
  * @num_ds_enabled: Number of destination scalers enabled
@@ -501,6 +502,7 @@ struct sde_crtc_state {
 	DECLARE_BITMAP(dirty, SDE_CRTC_DIRTY_MAX);
 	uint64_t input_fence_timeout_ns;
 	uint32_t num_dim_layers;
+	uint32_t cwb_enc_mask;
 	struct sde_hw_dim_layer dim_layer[SDE_MAX_DIM_LAYERS];
 	uint32_t num_ds;
 	uint32_t num_ds_enabled;
@@ -880,6 +882,22 @@ static inline bool sde_crtc_atomic_check_has_modeset(
 	return (crtc_state && drm_atomic_crtc_needs_modeset(crtc_state));
 }
 
+static inline bool sde_crtc_state_in_clone_mode(struct drm_encoder *encoder,
+	struct drm_crtc_state *state)
+{
+	struct sde_crtc_state *cstate;
+
+	if (!state || !encoder)
+		return false;
+
+	cstate = to_sde_crtc_state(state);
+	if (sde_encoder_in_clone_mode(encoder) ||
+		(cstate->cwb_enc_mask & drm_encoder_mask(encoder)))
+		return true;
+
+	return false;
+}
+
 /**
  * sde_crtc_get_secure_transition - determines the operations to be
  * performed before transitioning to secure state

+ 30 - 0
msm/sde/sde_encoder.c

@@ -849,6 +849,36 @@ bool sde_encoder_is_cwb_disabling(struct drm_encoder *drm_enc,
 	return false;
 }
 
+void sde_encoder_set_clone_mode(struct drm_encoder *drm_enc,
+	 struct drm_crtc_state *crtc_state)
+{
+	struct sde_encoder_virt *sde_enc;
+	struct sde_crtc_state *sde_crtc_state;
+	int i = 0;
+
+	if (!drm_enc || !crtc_state) {
+		SDE_DEBUG("invalid params\n");
+		return;
+	}
+	sde_enc = to_sde_encoder_virt(drm_enc);
+	sde_crtc_state = to_sde_crtc_state(crtc_state);
+
+	if ((sde_enc->disp_info.intf_type != DRM_MODE_CONNECTOR_VIRTUAL) ||
+		(!(sde_crtc_state->cwb_enc_mask & drm_encoder_mask(drm_enc))))
+		return;
+
+	for (i = 0; i < sde_enc->num_phys_encs; i++) {
+		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
+
+		if (phys) {
+			phys->in_clone_mode = true;
+			SDE_DEBUG("enc:%d phys state:%d\n", DRMID(drm_enc), phys->enable_state);
+		}
+	}
+
+	sde_crtc_state->cwb_enc_mask = 0;
+}
+
 static int _sde_encoder_atomic_check_phys_enc(struct sde_encoder_virt *sde_enc,
 	struct drm_crtc_state *crtc_state,
 	struct drm_connector_state *conn_state)

+ 8 - 0
msm/sde/sde_encoder.h

@@ -491,6 +491,14 @@ void sde_encoder_enable_recovery_event(struct drm_encoder *encoder);
  */
 bool sde_encoder_in_clone_mode(struct drm_encoder *enc);
 
+/**
+ * sde_encoder_set_clone_mode - cwb in wb phys enc is enabled.
+ * drm_enc:	Pointer to drm encoder structure
+ * drm_crtc_state:	Pointer to drm_crtc_state
+ */
+void sde_encoder_set_clone_mode(struct drm_encoder *drm_enc,
+	 struct drm_crtc_state *crtc_state);
+
 /*
  * sde_encoder_is_cwb_disabling - check if cwb encoder disable is pending
  * @drm_enc:    Pointer to drm encoder structure

+ 8 - 4
msm/sde/sde_encoder_phys_wb.c

@@ -653,6 +653,7 @@ static void _sde_enc_phys_wb_detect_cwb(struct sde_encoder_phys *phys_enc,
 		struct drm_crtc_state *crtc_state)
 {
 	struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc);
+	struct sde_crtc_state *cstate = to_sde_crtc_state(crtc_state);
 	const struct sde_wb_cfg *wb_cfg = wb_enc->hw_wb->caps;
 	u32 encoder_mask = 0;
 
@@ -662,9 +663,11 @@ static void _sde_enc_phys_wb_detect_cwb(struct sde_encoder_phys *phys_enc,
 		encoder_mask = crtc_state->encoder_mask;
 		encoder_mask &= ~drm_encoder_mask(phys_enc->parent);
 	}
-	phys_enc->in_clone_mode = encoder_mask ? true : false;
 
-	SDE_DEBUG("detect CWB(OR)DCWB - status:%d\n", phys_enc->in_clone_mode);
+	cstate->cwb_enc_mask = encoder_mask ? drm_encoder_mask(phys_enc->parent) : 0;
+
+	SDE_DEBUG("detect CWB - status:%d, phys state:%d in_clone_mode:%d\n",
+		 cstate->cwb_enc_mask, phys_enc->enable_state, phys_enc->in_clone_mode);
 }
 
 static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc,
@@ -816,6 +819,7 @@ static int sde_encoder_phys_wb_atomic_check(
 		struct drm_connector_state *conn_state)
 {
 	struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc);
+	struct sde_crtc_state *cstate = to_sde_crtc_state(crtc_state);
 	struct sde_hw_wb *hw_wb = wb_enc->hw_wb;
 	const struct sde_wb_cfg *wb_cfg = hw_wb->caps;
 	struct drm_framebuffer *fb;
@@ -843,7 +847,7 @@ static int sde_encoder_phys_wb_atomic_check(
 
 	_sde_enc_phys_wb_detect_cwb(phys_enc, crtc_state);
 
-	if (clone_mode_curr && !phys_enc->in_clone_mode) {
+	if (clone_mode_curr && !cstate->cwb_enc_mask) {
 		SDE_ERROR("WB commit before CWB disable\n");
 		return -EINVAL;
 	}
@@ -902,7 +906,7 @@ static int sde_encoder_phys_wb_atomic_check(
 		crtc_state->mode_changed = true;
 
 	/* if in clone mode, return after cwb validation */
-	if (phys_enc->in_clone_mode) {
+	if (cstate->cwb_enc_mask) {
 		rc = _sde_enc_phys_wb_validate_cwb(phys_enc, crtc_state,
 				conn_state);
 		if (rc)

+ 1 - 1
msm/sde/sde_rm.c

@@ -2135,7 +2135,7 @@ static int _sde_rm_populate_requirements(
 	 * found enabled.
 	 */
 	if ((!RM_RQ_CWB(reqs) || !RM_RQ_DCWB(reqs))
-				&& sde_encoder_in_clone_mode(enc)) {
+				&& sde_crtc_state_in_clone_mode(enc, crtc_state)) {
 		if (cfg->has_dedicated_cwb_support)
 			reqs->top_ctrl |= BIT(SDE_RM_TOPCTL_DCWB);
 		else