drm/msm/sde: move rot flush config to crtc kickoff

Move the rotator flush bit determination from the blend setup
to the kickoff function. This consolidates all sbuf related
programming between sync/async/offline modes to the kickoff
function instead of splitting the configuration between blend
and kickoff functions.

Change-Id: I9b696a4f3f47a5ed699961d3b56e236a027982ff
Signed-off-by: Clarence Ip <cip@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index e033647..efbbd24 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -1263,7 +1263,7 @@
 	struct sde_hw_stage_cfg *stage_cfg;
 	struct sde_rect plane_crtc_roi;
 
-	u32 flush_mask, flush_sbuf, flush_tmp;
+	u32 flush_mask, flush_sbuf;
 	uint32_t stage_idx, lm_idx;
 	int zpos_cnt[SDE_STAGE_MAX + 1] = { 0 };
 	int i;
@@ -1279,10 +1279,9 @@
 	lm = mixer->hw_lm;
 	stage_cfg = &sde_crtc->stage_cfg;
 	cstate = to_sde_crtc_state(crtc->state);
-	flush_sbuf = 0x0;
 
 	cstate->sbuf_prefill_line = 0;
-	cstate->is_sbuf = false;
+	sde_crtc->sbuf_flush_mask = 0x0;
 
 	drm_atomic_crtc_for_each_plane(plane, crtc) {
 		state = plane->state;
@@ -1297,16 +1296,14 @@
 		pstate = to_sde_plane_state(state);
 		fb = state->fb;
 
-		if (sde_plane_is_sbuf_mode(plane, &prefill))
-			cstate->is_sbuf = true;
+		prefill = sde_plane_rot_calc_prefill(plane);
 		if (prefill > cstate->sbuf_prefill_line)
 			cstate->sbuf_prefill_line = prefill;
 
-		sde_plane_get_ctl_flush(plane, ctl, &flush_mask, &flush_tmp);
+		sde_plane_get_ctl_flush(plane, ctl, &flush_mask, &flush_sbuf);
 
-		/* persist rotator flush bit(s) for one more commit */
-		flush_mask |= cstate->sbuf_flush_mask | flush_tmp;
-		flush_sbuf |= flush_tmp;
+		/* save sbuf flush value for later */
+		sde_crtc->sbuf_flush_mask |= flush_sbuf;
 
 		SDE_DEBUG("crtc %d stage:%d - plane %d sspp %d fb %d\n",
 				crtc->base.id,
@@ -1330,7 +1327,7 @@
 				state->src_w >> 16, state->src_h >> 16,
 				state->crtc_x, state->crtc_y,
 				state->crtc_w, state->crtc_h,
-				flush_tmp ? cstate->is_sbuf : 0);
+				flush_sbuf != 0);
 
 		stage_idx = zpos_cnt[pstate->stage]++;
 		stage_cfg->stage[pstate->stage][stage_idx] =
@@ -1357,8 +1354,6 @@
 		}
 	}
 
-	cstate->sbuf_flush_mask = flush_sbuf;
-
 	if (lm && lm->ops.setup_dim_layer) {
 		cstate = to_sde_crtc_state(crtc->state);
 		for (i = 0; i < cstate->num_dim_layers; i++)
@@ -2735,6 +2730,7 @@
 	struct drm_plane *plane;
 	struct sde_crtc *sde_crtc;
 	struct sde_hw_ctl *ctl, *master_ctl;
+	u32 flush_mask;
 	int i;
 
 	if (!crtc || !cstate)
@@ -2742,21 +2738,41 @@
 
 	sde_crtc = to_sde_crtc(crtc);
 
+	/*
+	 * Update sbuf configuration and flush bits if a flush
+	 * mask has been defined for either the current or
+	 * previous commit.
+	 *
+	 * Updates are also required for the first commit after
+	 * sbuf_flush_mask becomes 0x0, to properly transition
+	 * the hardware out of sbuf mode.
+	 */
+	if (!sde_crtc->sbuf_flush_mask_old && !sde_crtc->sbuf_flush_mask)
+		return;
+
+	flush_mask = sde_crtc->sbuf_flush_mask_old | sde_crtc->sbuf_flush_mask;
+	sde_crtc->sbuf_flush_mask_old = sde_crtc->sbuf_flush_mask;
+
 	SDE_ATRACE_BEGIN("crtc_kickoff_rot");
 
-	drm_atomic_crtc_for_each_plane(plane, crtc)
-		sde_plane_kickoff(plane);
+	if (cstate->sbuf_cfg.rot_op_mode != SDE_CTL_ROT_OP_MODE_OFFLINE) {
+		drm_atomic_crtc_for_each_plane(plane, crtc) {
+			sde_plane_kickoff(plane);
+		}
+	}
 
 	master_ctl = NULL;
 	for (i = 0; i < sde_crtc->num_mixers; i++) {
 		ctl = sde_crtc->mixers[i].hw_ctl;
-		if (!ctl || !ctl->ops.setup_sbuf_cfg)
+		if (!ctl || !ctl->ops.setup_sbuf_cfg ||
+				!ctl->ops.update_pending_flush)
 			continue;
 
 		if (!master_ctl || master_ctl->idx > ctl->idx)
 			master_ctl = ctl;
 
 		ctl->ops.setup_sbuf_cfg(ctl, &cstate->sbuf_cfg);
+		ctl->ops.update_pending_flush(ctl, flush_mask);
 	}
 
 	if (cstate->sbuf_cfg.rot_op_mode == SDE_CTL_ROT_OP_MODE_INLINE_ASYNC &&
@@ -2803,7 +2819,7 @@
 	SDE_ATRACE_BEGIN("crtc_commit");
 
 	/* default to ASYNC mode for inline rotation */
-	cstate->sbuf_cfg.rot_op_mode = cstate->is_sbuf ?
+	cstate->sbuf_cfg.rot_op_mode = sde_crtc->sbuf_flush_mask ?
 		SDE_CTL_ROT_OP_MODE_INLINE_ASYNC : SDE_CTL_ROT_OP_MODE_OFFLINE;
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
@@ -2867,8 +2883,11 @@
 	/*
 	 * For SYNC inline modes, delay the kick off until after the
 	 * wait for frame done in case the wait times out.
+	 *
+	 * Also perform a final kickoff when transitioning back to
+	 * offline mode.
 	 */
-	if (cstate->sbuf_cfg.rot_op_mode == SDE_CTL_ROT_OP_MODE_INLINE_SYNC)
+	if (cstate->sbuf_cfg.rot_op_mode != SDE_CTL_ROT_OP_MODE_INLINE_ASYNC)
 		_sde_crtc_commit_kickoff_rot(crtc, cstate);
 
 	sde_vbif_clear_errors(sde_kms);
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 5d66719..0783f11 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -204,6 +204,8 @@
  * @misr_enable   : boolean entry indicates misr enable/disable status.
  * @misr_frame_count  : misr frame count provided by client
  * @misr_data     : store misr data before turning off the clocks.
+ * @sbuf_flush_mask: flush mask for inline rotator
+ * @sbuf_flush_mask_old: inline rotator flush mask for previous commit
  * @power_event   : registered power event handle
  * @cur_perf      : current performance committed to clock/bandwidth driver
  * @rp_lock       : serialization lock for resource pool
@@ -264,6 +266,9 @@
 	u32 misr_frame_count;
 	u32 misr_data[CRTC_DUAL_MIXERS];
 
+	u32 sbuf_flush_mask;
+	u32 sbuf_flush_mask_old;
+
 	struct sde_power_event *power_event;
 
 	struct sde_core_perf_params cur_perf;
@@ -357,8 +362,6 @@
  * @new_perf: new performance state being requested
  * @sbuf_cfg: stream buffer configuration
  * @sbuf_prefill_line: number of line for inline rotator prefetch
- * @sbuf_flush_mask: flush mask for inline rotator
- * @is_sbuf: whether or not the CRTC is using inline rotation
  */
 struct sde_crtc_state {
 	struct drm_crtc_state base;
@@ -386,8 +389,6 @@
 	struct sde_core_perf_params new_perf;
 	struct sde_ctl_sbuf_cfg sbuf_cfg;
 	u32 sbuf_prefill_line;
-	u32 sbuf_flush_mask;
-	bool is_sbuf;
 
 	struct sde_crtc_respool rp;
 };
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 10f796f..15b4cd2 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -1518,7 +1518,7 @@
  * @plane: Pointer to drm plane
  * return: prefill time in line
  */
-static u32 sde_plane_rot_calc_prefill(struct drm_plane *plane)
+u32 sde_plane_rot_calc_prefill(struct drm_plane *plane)
 {
 	struct drm_plane_state *state;
 	struct sde_plane_state *pstate;
@@ -1554,26 +1554,6 @@
 }
 
 /**
- * sde_plane_is_sbuf_mode - check if sspp of given plane is in streaming
- *	buffer mode
- * @plane: Pointer to drm plane
- * @prefill: Pointer to prefill line count
- * return: true if sspp is in stream buffer mode
- */
-bool sde_plane_is_sbuf_mode(struct drm_plane *plane, u32 *prefill)
-{
-	struct sde_plane_state *pstate = plane && plane->state ?
-			to_sde_plane_state(plane->state) : NULL;
-	struct sde_plane_rot_state *rstate = pstate ? &pstate->rot : NULL;
-	bool sbuf_mode = rstate ? rstate->out_sbuf : false;
-
-	if (prefill)
-		*prefill = sde_plane_rot_calc_prefill(plane);
-
-	return sbuf_mode;
-}
-
-/**
  * sde_plane_rot_calc_cfg - calculate rotator/sspp configuration by
  *	enumerating over all planes attached to the same rotator
  * @plane: Pointer to drm plane
@@ -2752,7 +2732,7 @@
 		return;
 
 	*flush_rot = 0x0;
-	if (sde_plane_is_sbuf_mode(plane, NULL) && rstate->rot_hw &&
+	if (rstate && rstate->out_sbuf && rstate->rot_hw &&
 			ctl->ops.get_bitmask_rot)
 		ctl->ops.get_bitmask_rot(ctl, flush_rot, rstate->rot_hw->idx);
 }
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h
index 913647f..c956345 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.h
+++ b/drivers/gpu/drm/msm/sde/sde_plane.h
@@ -207,12 +207,11 @@
 		u32 *flush_sspp, u32 *flush_rot);
 
 /**
- * sde_plane_is_sbuf_mode - return status of stream buffer mode
- * @plane:   Pointer to DRM plane object
- * @prefill: Pointer to updated prefill in stream buffer mode (optional)
- * Returns: true if plane is in stream buffer mode
+ * sde_plane_rot_calc_prefill - calculate rotator start prefill
+ * @plane: Pointer to drm plane
+ * return: prefill time in line
  */
-bool sde_plane_is_sbuf_mode(struct drm_plane *plane, u32 *prefill);
+u32 sde_plane_rot_calc_prefill(struct drm_plane *plane);
 
 /**
  * sde_plane_restore - restore hw state if previously power collapsed