Browse Source

Merge "disp: msm: sde: reset dsc mux config in encoder disable"

qctecmdr 3 years ago
parent
commit
fba8cf7c57
2 changed files with 52 additions and 1 deletions
  1. 12 0
      msm/sde/sde_encoder.c
  2. 40 1
      msm/sde/sde_rm.c

+ 12 - 0
msm/sde/sde_encoder.c

@@ -3188,6 +3188,7 @@ void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc,
 	struct sde_encoder_virt *sde_enc;
 	struct sde_hw_ctl *ctl = phys_enc->hw_ctl;
 	struct sde_ctl_flush_cfg cfg;
+	struct sde_hw_dsc *hw_dsc = NULL;
 	int i;
 
 	ctl->ops.reset(ctl);
@@ -3242,6 +3243,17 @@ void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc,
 				phys_enc->hw_pp->merge_3d ?
 				phys_enc->hw_pp->merge_3d->idx : 0);
 
+	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
+		hw_dsc = sde_enc->hw_dsc[i];
+
+		if (hw_dsc && hw_dsc->ops.bind_pingpong_blk) {
+			hw_dsc->ops.bind_pingpong_blk(hw_dsc, false, PINGPONG_MAX);
+
+			if (ctl->ops.update_bitmask)
+				ctl->ops.update_bitmask(ctl, SDE_HW_FLUSH_DSC, hw_dsc->idx, true);
+		}
+	}
+
 	sde_crtc_disable_cp_features(sde_enc->base.crtc);
 	ctl->ops.get_pending_flush(ctl, &cfg);
 	SDE_EVT32(DRMID(phys_enc->parent), cfg.pending_flush_mask);

+ 40 - 1
msm/sde/sde_rm.c

@@ -24,6 +24,9 @@
 	(((h)->rsvp && ((h)->rsvp->enc_id != (r)->enc_id)) ||\
 		((h)->rsvp_nxt && ((h)->rsvp_nxt->enc_id != (r)->enc_id)))
 
+#define RESERVED_BY_CURRENT(h, r) \
+	(((h)->rsvp && ((h)->rsvp->enc_id == (r)->enc_id)))
+
 #define RM_RQ_LOCK(r) ((r)->top_ctrl & BIT(SDE_RM_TOPCTL_RESERVE_LOCK))
 #define RM_RQ_CLEAR(r) ((r)->top_ctrl & BIT(SDE_RM_TOPCTL_RESERVE_CLEAR))
 #define RM_RQ_DSPP(r) ((r)->top_ctrl & BIT(SDE_RM_TOPCTL_DSPP))
@@ -1848,12 +1851,39 @@ static int _sde_rm_make_ctl_rsvp(struct sde_rm *rm, struct sde_rm_rsvp *rsvp,
 	return ret;
 }
 
+/*
+ * Returns number of dsc hw blocks previously  owned by this encoder.
+ * Returns 0 if not found  or error
+ */
+static int _sde_rm_find_prev_dsc(struct sde_rm *rm, struct sde_rm_rsvp *rsvp,
+		u8 *prev_dsc, u32 max_cnt)
+{
+	int i = 0;
+	struct sde_rm_hw_iter iter_dsc;
+
+	if ((!prev_dsc) || (max_cnt < MAX_DATA_PATH_PER_DSIPLAY))
+		return 0;
+
+	sde_rm_init_hw_iter(&iter_dsc, 0, SDE_HW_BLK_DSC);
+
+	while (_sde_rm_get_hw_locked(rm, &iter_dsc)) {
+		if (RESERVED_BY_CURRENT(iter_dsc.blk, rsvp))
+			prev_dsc[i++] =  iter_dsc.blk->id;
+
+		if (i >= MAX_DATA_PATH_PER_DSIPLAY)
+		       return 0;
+	}
+
+	return i;
+}
+
 static int _sde_rm_make_dsc_rsvp(struct sde_rm *rm, struct sde_rm_rsvp *rsvp,
 		struct sde_rm_requirements *reqs,
 		struct sde_splash_display *splash_display)
 {
 	int i;
 	u8 *hw_ids = NULL;
+	u8 prev_dsc[MAX_DATA_PATH_PER_DSIPLAY] = {0,};
 
 	/* Check if splash data provided dsc_ids */
 	if (splash_display) {
@@ -1866,7 +1896,16 @@ static int _sde_rm_make_dsc_rsvp(struct sde_rm *rm, struct sde_rm_rsvp *rsvp,
 				i, splash_display->dsc_ids[i]);
 	}
 
-	return  _sde_rm_reserve_dsc(rm, rsvp, reqs, hw_ids);
+	/*
+	 * find if this encoder has previously allocated dsc hw blocks, use same dsc blocks
+	 * if found to avoid switching dsc encoders during each modeset, as currently we
+	 * dont have feasible way of decoupling previously owned dsc blocks by resetting
+	 * respective dsc encoders mux control and flush them from commit path
+	 */
+	if (!hw_ids && _sde_rm_find_prev_dsc(rm, rsvp, prev_dsc, MAX_DATA_PATH_PER_DSIPLAY))
+		return  _sde_rm_reserve_dsc(rm, rsvp, reqs, prev_dsc);
+	else
+		return  _sde_rm_reserve_dsc(rm, rsvp, reqs, hw_ids);
 
 }