Explorar o código

disp: msm: sde: decouple FETCH_PIPE_ACTIVE logic from setup_blendstages

Setup blendstages is done per LM but FETCH_PIPE_ACTIVE is per CTL.
Overloading mixer blendstage setup with fetch pipe logic can lead
to HW programming errors. Refactor the logic for setting
FETCH_PIPE_ACTIVE by adding a new op that allows caller to provide
a bitmask of all pipes required to be active on this CTL. This new
logic includes support for:
 - 4LM use-cases, staging pipes for all LMs within a CRTC
 - Demura fetch-pipe without need for tracking via active_cfg (removed)

Also, lower the cyclomatic complexity in setup_blendstages by moving
the logic for obtaining the mixer config settings in to a helper
function.

Change-Id: I2907b359ffad5734be5b06f44919b5ddb1ef3f7c
Signed-off-by: Steve Cohen <[email protected]>
Steve Cohen %!s(int64=5) %!d(string=hai) anos
pai
achega
b9e3d4aebb
Modificáronse 5 ficheiros con 107 adicións e 111 borrados
  1. 10 28
      msm/sde/sde_crtc.c
  2. 0 2
      msm/sde/sde_crtc.h
  3. 1 1
      msm/sde/sde_encoder.c
  4. 87 77
      msm/sde/sde_hw_ctl.c
  5. 9 3
      msm/sde/sde_hw_ctl.h

+ 10 - 28
msm/sde/sde_crtc.c

@@ -496,10 +496,6 @@ static void _sde_crtc_setup_blend_cfg(struct sde_crtc_mixer *mixer,
 		}
 		break;
 
-	case SDE_DRM_BLEND_OP_SKIP:
-		SDE_ERROR("skip the blending for plane\n");
-		return;
-
 	default:
 		/* do nothing */
 		break;
@@ -1336,25 +1332,6 @@ static void _sde_crtc_set_src_split_order(struct drm_crtc *crtc,
 	}
 }
 
-static void __sde_crtc_assign_active_cfg(struct sde_crtc *sdecrtc,
-				struct drm_plane *plane)
-{
-	u8 found = 0;
-	int i;
-
-	for (i = 0; i < SDE_STAGE_MAX; i++) {
-		if (sdecrtc->active_cfg.stage[i][0] == SSPP_NONE) {
-			found = 1;
-			break;
-		}
-	}
-	if (!found) {
-		SDE_ERROR("All active configs are allocated\n");
-		return;
-	}
-	sdecrtc->active_cfg.stage[i][0] = sde_plane_pipe(plane);
-}
-
 static void _sde_crtc_setup_blend_cfg_by_stage(struct sde_crtc_mixer *mixer,
 		int num_mixers, struct plane_state *pstates, int cnt)
 {
@@ -1406,6 +1383,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
 	int i, mode, cnt = 0;
 	bool bg_alpha_enable = false, is_secure = false;
 	u32 blend_type;
+	DECLARE_BITMAP(fetch_active, SSPP_MAX);
 
 	if (!sde_crtc || !crtc->state || !mixer) {
 		SDE_ERROR("invalid sde_crtc or mixer\n");
@@ -1421,6 +1399,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
 	if (!pstates)
 		return;
 
+	memset(fetch_active, 0, sizeof(fetch_active));
 	drm_atomic_crtc_for_each_plane(plane, crtc) {
 		state = plane->state;
 		if (!state)
@@ -1440,6 +1419,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
 				(mode == SDE_DRM_FB_SEC_DIR_TRANS)) ?
 				true : false;
 
+		set_bit(sde_plane_pipe(plane), fetch_active);
 		sde_plane_ctl_flush(plane, ctl, true);
 
 		SDE_DEBUG("crtc %d stage:%d - plane %d sspp %d fb %d\n",
@@ -1458,9 +1438,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
 		blend_type = sde_plane_get_property(pstate,
 					PLANE_PROP_BLEND_OP);
 
-		if (blend_type == SDE_DRM_BLEND_OP_SKIP) {
-			__sde_crtc_assign_active_cfg(sde_crtc, plane);
-		} else {
+		if (blend_type != SDE_DRM_BLEND_OP_SKIP) {
 			if (pstate->stage == SDE_STAGE_BASE &&
 					format->alpha_enable)
 				bg_alpha_enable = true;
@@ -1517,6 +1495,9 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
 	_sde_crtc_setup_blend_cfg_by_stage(mixer, sde_crtc->num_mixers,
 			pstates, cnt);
 
+	if (ctl->ops.set_active_pipes)
+		ctl->ops.set_active_pipes(ctl, fetch_active);
+
 	sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL);
 	_sde_crtc_set_src_split_order(crtc, pstates, cnt);
 
@@ -1651,7 +1632,6 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc,
 
 	/* initialize stage cfg */
 	memset(&sde_crtc->stage_cfg, 0, sizeof(struct sde_hw_stage_cfg));
-	memset(&sde_crtc->active_cfg, 0, sizeof(sde_crtc->active_cfg));
 
 	if (add_planes)
 		_sde_crtc_blend_setup_mixer(crtc, old_state, sde_crtc, mixer);
@@ -1683,7 +1663,7 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc,
 			cfg.pending_flush_mask);
 
 		ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
-			&sde_crtc->stage_cfg, &sde_crtc->active_cfg);
+			&sde_crtc->stage_cfg);
 	}
 
 	_sde_crtc_program_lm_output_roi(crtc);
@@ -3179,6 +3159,8 @@ static void _sde_crtc_clear_all_blend_stages(struct sde_crtc *sde_crtc)
 		mixer = sde_crtc->mixers[0];
 		if (mixer.hw_ctl && mixer.hw_ctl->ops.clear_all_blendstages)
 			mixer.hw_ctl->ops.clear_all_blendstages(mixer.hw_ctl);
+		if (mixer.hw_ctl && mixer.hw_ctl->ops.set_active_pipes)
+			mixer.hw_ctl->ops.set_active_pipes(mixer.hw_ctl, NULL);
 	}
 }
 

+ 0 - 2
msm/sde/sde_crtc.h

@@ -225,7 +225,6 @@ struct sde_crtc_misr_info {
  * @property_defaults : Array of default values for generic property support
  * @output_fence  : output release fence context
  * @stage_cfg     : H/w mixer stage configuration
- * @active_cfg    : H/w pipes active that shouldn't be staged
  * @debugfs_root  : Parent of debugfs node
  * @priv_handle   : Pointer to external private handle, if present
  * @vblank_cb_count : count of vblank callback since last reset
@@ -298,7 +297,6 @@ struct sde_crtc {
 	struct sde_fence_context *output_fence;
 
 	struct sde_hw_stage_cfg stage_cfg;
-	struct sde_hw_stage_cfg active_cfg;
 	struct dentry *debugfs_root;
 	void *priv_handle;
 

+ 1 - 1
msm/sde/sde_encoder.c

@@ -4232,7 +4232,7 @@ int sde_encoder_helper_reset_mixers(struct sde_encoder_phys *phys_enc,
 		/* only enable border color on LM */
 		if (phys_enc->hw_ctl->ops.setup_blendstage)
 			phys_enc->hw_ctl->ops.setup_blendstage(
-				phys_enc->hw_ctl, hw_lm->idx, NULL, NULL);
+				phys_enc->hw_ctl, hw_lm->idx, NULL);
 	}
 
 	if (!lm_valid) {

+ 87 - 77
msm/sde/sde_hw_ctl.c

@@ -266,6 +266,13 @@ static const struct ctl_hw_flush_cfg
 			intf_flush_tbl } /* SDE_HW_FLUSH_INTF */
 };
 
+struct sde_ctl_mixer_cfg {
+	u32 cfg;
+	u32 ext;
+	u32 ext2;
+	u32 ext3;
+};
+
 static struct sde_ctl_cfg *_ctl_offset(enum sde_ctl ctl,
 		struct sde_mdss_cfg *m,
 		void __iomem *addr,
@@ -625,6 +632,23 @@ static inline int sde_hw_ctl_update_bitmask_dspp_subblk(struct sde_hw_ctl *ctx,
 	return 0;
 }
 
+static void sde_hw_ctl_set_fetch_pipe_active(struct sde_hw_ctl *ctx,
+		unsigned long *fetch_active)
+{
+	int i;
+	u32 val = 0;
+
+	if (fetch_active) {
+		for (i = 0; i < SSPP_MAX; i++) {
+			if (test_bit(i, fetch_active) &&
+					fetch_tbl[i] != CTL_INVALID_BIT)
+				val |= BIT(fetch_tbl[i]);
+		}
+	}
+
+	SDE_REG_WRITE(&ctx->hw, CTL_FETCH_PIPE_ACTIVE, val);
+}
+
 static inline void _sde_hw_ctl_write_dspp_flushes(struct sde_hw_ctl *ctx) {
 	int i;
 	bool has_dspp_flushes = ctx->caps->features &
@@ -815,35 +839,18 @@ static void sde_hw_ctl_clear_all_blendstages(struct sde_hw_ctl *ctx)
 	SDE_REG_WRITE(c, CTL_FETCH_PIPE_ACTIVE, 0);
 }
 
-static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
-	enum sde_lm lm, struct sde_hw_stage_cfg *stage_cfg,
-	struct sde_hw_stage_cfg *active_cfg)
+static void _sde_hw_ctl_get_mixer_cfg(struct sde_hw_ctl *ctx,
+		struct sde_hw_stage_cfg *stage_cfg, int stages,
+		struct sde_ctl_mixer_cfg *cfg)
 {
-	struct sde_hw_blk_reg_map *c;
-	u32 mixercfg = 0, mixercfg_ext = 0, mix, ext;
-	u32 mixercfg_ext2 = 0, mixercfg_ext3 = 0;
-	u32 active_fetch_pipes = 0;
-	int i, j;
-	u8 stages;
-	int pipes_per_stage;
-
-	if (!ctx)
-		return;
+	int i, j, pipes_per_stage;
+	u32 mix, ext;
 
-	c = &ctx->hw;
-	stages = _mixer_stages(ctx->mixer_hw_caps, ctx->mixer_count, lm);
-	if ((int)stages < 0)
-		return;
-
-	if (test_bit(SDE_MIXER_SOURCESPLIT,
-		&ctx->mixer_hw_caps->features))
+	if (test_bit(SDE_MIXER_SOURCESPLIT, &ctx->mixer_hw_caps->features))
 		pipes_per_stage = PIPES_PER_STAGE;
 	else
 		pipes_per_stage = 1;
 
-	if (!stage_cfg)
-		goto exit;
-
 	for (i = 0; i <= stages; i++) {
 		/* overflow to ext register if 'i + 1 > 7' */
 		mix = (i + 1) & 0x7;
@@ -853,125 +860,127 @@ static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
 			enum sde_sspp pipe = stage_cfg->stage[i][j];
 			enum sde_sspp_multirect_index rect_index =
 				stage_cfg->multirect_index[i][j];
-
 			switch (pipe) {
 			case SSPP_VIG0:
 				if (rect_index == SDE_SSPP_RECT_1) {
-					mixercfg_ext3 |= ((i + 1) & 0xF) << 0;
+					cfg->ext3 |= ((i + 1) & 0xF) << 0;
 				} else {
-					mixercfg |= mix << 0;
-					mixercfg_ext |= ext << 0;
+					cfg->cfg |= mix << 0;
+					cfg->ext |= ext << 0;
 				}
 				break;
 			case SSPP_VIG1:
 				if (rect_index == SDE_SSPP_RECT_1) {
-					mixercfg_ext3 |= ((i + 1) & 0xF) << 4;
+					cfg->ext3 |= ((i + 1) & 0xF) << 4;
 				} else {
-					mixercfg |= mix << 3;
-					mixercfg_ext |= ext << 2;
+					cfg->cfg |= mix << 3;
+					cfg->ext |= ext << 2;
 				}
 				break;
 			case SSPP_VIG2:
 				if (rect_index == SDE_SSPP_RECT_1) {
-					mixercfg_ext3 |= ((i + 1) & 0xF) << 8;
+					cfg->ext3 |= ((i + 1) & 0xF) << 8;
 				} else {
-					mixercfg |= mix << 6;
-					mixercfg_ext |= ext << 4;
+					cfg->cfg |= mix << 6;
+					cfg->ext |= ext << 4;
 				}
 				break;
 			case SSPP_VIG3:
 				if (rect_index == SDE_SSPP_RECT_1) {
-					mixercfg_ext3 |= ((i + 1) & 0xF) << 12;
+					cfg->ext3 |= ((i + 1) & 0xF) << 12;
 				} else {
-					mixercfg |= mix << 26;
-					mixercfg_ext |= ext << 6;
+					cfg->cfg |= mix << 26;
+					cfg->ext |= ext << 6;
 				}
 				break;
 			case SSPP_RGB0:
-				mixercfg |= mix << 9;
-				mixercfg_ext |= ext << 8;
+				cfg->cfg |= mix << 9;
+				cfg->ext |= ext << 8;
 				break;
 			case SSPP_RGB1:
-				mixercfg |= mix << 12;
-				mixercfg_ext |= ext << 10;
+				cfg->cfg |= mix << 12;
+				cfg->ext |= ext << 10;
 				break;
 			case SSPP_RGB2:
-				mixercfg |= mix << 15;
-				mixercfg_ext |= ext << 12;
+				cfg->cfg |= mix << 15;
+				cfg->ext |= ext << 12;
 				break;
 			case SSPP_RGB3:
-				mixercfg |= mix << 29;
-				mixercfg_ext |= ext << 14;
+				cfg->cfg |= mix << 29;
+				cfg->ext |= ext << 14;
 				break;
 			case SSPP_DMA0:
 				if (rect_index == SDE_SSPP_RECT_1) {
-					mixercfg_ext2 |= ((i + 1) & 0xF) << 8;
+					cfg->ext2 |= ((i + 1) & 0xF) << 8;
 				} else {
-					mixercfg |= mix << 18;
-					mixercfg_ext |= ext << 16;
+					cfg->cfg |= mix << 18;
+					cfg->ext |= ext << 16;
 				}
 				break;
 			case SSPP_DMA1:
 				if (rect_index == SDE_SSPP_RECT_1) {
-					mixercfg_ext2 |= ((i + 1) & 0xF) << 12;
+					cfg->ext2 |= ((i + 1) & 0xF) << 12;
 				} else {
-					mixercfg |= mix << 21;
-					mixercfg_ext |= ext << 18;
+					cfg->cfg |= mix << 21;
+					cfg->ext |= ext << 18;
 				}
 				break;
 			case SSPP_DMA2:
 				if (rect_index == SDE_SSPP_RECT_1) {
-					mixercfg_ext2 |= ((i + 1) & 0xF) << 16;
+					cfg->ext2 |= ((i + 1) & 0xF) << 16;
 				} else {
 					mix |= (i + 1) & 0xF;
-					mixercfg_ext2 |= mix << 0;
+					cfg->ext2 |= mix << 0;
 				}
 				break;
 			case SSPP_DMA3:
 				if (rect_index == SDE_SSPP_RECT_1) {
-					mixercfg_ext2 |= ((i + 1) & 0xF) << 20;
+					cfg->ext2 |= ((i + 1) & 0xF) << 20;
 				} else {
 					mix |= (i + 1) & 0xF;
-					mixercfg_ext2 |= mix << 4;
+					cfg->ext2 |= mix << 4;
 				}
 				break;
 			case SSPP_CURSOR0:
-				mixercfg_ext |= ((i + 1) & 0xF) << 20;
+				cfg->ext |= ((i + 1) & 0xF) << 20;
 				break;
 			case SSPP_CURSOR1:
-				mixercfg_ext |= ((i + 1) & 0xF) << 26;
+				cfg->ext |= ((i + 1) & 0xF) << 26;
 				break;
 			default:
 				break;
 			}
-
-			if (fetch_tbl[pipe] != CTL_INVALID_BIT)
-				active_fetch_pipes |= BIT(fetch_tbl[pipe]);
 		}
 	}
+}
 
-	for (i = 0; i <= stages && active_cfg; i++) {
-		enum sde_sspp pipe = active_cfg->stage[i][0];
+static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
+	enum sde_lm lm, struct sde_hw_stage_cfg *stage_cfg)
+{
+	struct sde_hw_blk_reg_map *c;
+	struct sde_ctl_mixer_cfg cfg = { 0 };
+	int stages;
 
-		if (pipe == SSPP_NONE)
-			break;
-		if (fetch_tbl[pipe] != CTL_INVALID_BIT) {
-			active_fetch_pipes |= BIT(fetch_tbl[pipe]);
-			SDE_DEBUG("fetch pipe %d active pipes %x\n",
-				pipe, active_fetch_pipes);
-		}
-	}
+	if (!ctx)
+		return;
+
+	stages = _mixer_stages(ctx->mixer_hw_caps, ctx->mixer_count, lm);
+	if (stages < 0)
+		return;
+
+	c = &ctx->hw;
+
+	if (stage_cfg)
+		_sde_hw_ctl_get_mixer_cfg(ctx, stage_cfg, stages, &cfg);
 
-exit:
-	if ((!mixercfg && !mixercfg_ext && !mixercfg_ext2 && !mixercfg_ext3) ||
+	if ((!cfg.cfg && !cfg.ext && !cfg.ext2 && !cfg.ext3) ||
 			(stage_cfg && !stage_cfg->stage[0][0]))
-		mixercfg |= CTL_MIXER_BORDER_OUT;
+		cfg.cfg |= CTL_MIXER_BORDER_OUT;
 
-	SDE_REG_WRITE(c, CTL_LAYER(lm), mixercfg);
-	SDE_REG_WRITE(c, CTL_LAYER_EXT(lm), mixercfg_ext);
-	SDE_REG_WRITE(c, CTL_LAYER_EXT2(lm), mixercfg_ext2);
-	SDE_REG_WRITE(c, CTL_LAYER_EXT3(lm), mixercfg_ext3);
-	SDE_REG_WRITE(c, CTL_FETCH_PIPE_ACTIVE, active_fetch_pipes);
+	SDE_REG_WRITE(c, CTL_LAYER(lm), cfg.cfg);
+	SDE_REG_WRITE(c, CTL_LAYER_EXT(lm), cfg.ext);
+	SDE_REG_WRITE(c, CTL_LAYER_EXT2(lm), cfg.ext2);
+	SDE_REG_WRITE(c, CTL_LAYER_EXT3(lm), cfg.ext3);
 }
 
 static u32 sde_hw_ctl_get_staged_sspp(struct sde_hw_ctl *ctx, enum sde_lm lm,
@@ -1352,6 +1361,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops,
 		ops->reset_post_disable = sde_hw_ctl_reset_post_disable;
 		ops->get_scheduler_status = sde_hw_ctl_get_scheduler_status;
 		ops->read_active_status = sde_hw_ctl_read_active_status;
+		ops->set_active_pipes = sde_hw_ctl_set_fetch_pipe_active;
 	} else {
 		ops->update_pending_flush = sde_hw_ctl_update_pending_flush;
 		ops->trigger_flush = sde_hw_ctl_trigger_flush;

+ 9 - 3
msm/sde/sde_hw_ctl.h

@@ -433,11 +433,9 @@ struct sde_hw_ctl_ops {
 	 * @ctx       : ctl path ctx pointer
 	 * @lm        : layer mixer enumeration
 	 * @cfg       : blend stage configuration
-	 * @active_cfg: active no blend stage configuration
 	 */
 	void (*setup_blendstage)(struct sde_hw_ctl *ctx,
-		enum sde_lm lm, struct sde_hw_stage_cfg *cfg,
-		struct sde_hw_stage_cfg *active_cfg);
+		enum sde_lm lm, struct sde_hw_stage_cfg *cfg);
 
 	/**
 	 * Get all the sspp staged on a layer mixer
@@ -465,6 +463,14 @@ struct sde_hw_ctl_ops {
 	 * @Return: error code
 	 */
 	int (*get_start_state)(struct sde_hw_ctl *ctx);
+
+	/**
+	 * set the active fetch pipes attached to this CTL
+	 * @ctx         : ctl path ctx pointer
+	 * @fetch_active: bitmap of enum sde_sspp pipes attached
+	 */
+	void (*set_active_pipes)(struct sde_hw_ctl *ctx,
+			unsigned long *fetch_active);
 };
 
 /**