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