Forráskód Böngészése

disp: msm: sde: check fetch active registers for active data planes

Continuous splash setup checks the CTL configuration to determine and
log all planes that have been enabled for continuous splash boot.
This logic currently only checks the planes mapped to each LM on
a given control path, resulting in data planes being missed.

Update the boot plane enumeration logic to additionally check the CTL
fetch active registers to detect and log missed planes. This logic
checks against all planes found through the original enumeration path
to avoid logging the same plane twice. Note that planes found via the
fetch registers are assumed to be used across both rectangles due to
hardware logging limitations.

Change-Id: Ic1f4aaba94111fe096ba9764eeaef242beb6adf5
Signed-off-by: Christopher Braga <[email protected]>
Christopher Braga 5 éve
szülő
commit
812782e76b
5 módosított fájl, 120 hozzáadás és 18 törlés
  1. 23 0
      msm/sde/sde_hw_ctl.c
  2. 8 1
      msm/sde/sde_hw_ctl.h
  3. 7 1
      msm/sde/sde_hw_mdss.h
  4. 0 7
      msm/sde/sde_plane.c
  5. 82 9
      msm/sde/sde_rm.c

+ 23 - 0
msm/sde/sde_hw_ctl.c

@@ -638,6 +638,28 @@ static void sde_hw_ctl_set_fetch_pipe_active(struct sde_hw_ctl *ctx,
 	SDE_REG_WRITE(&ctx->hw, CTL_FETCH_PIPE_ACTIVE, val);
 }
 
+static u32 sde_hw_ctl_get_active_fetch_pipes(struct sde_hw_ctl *ctx)
+{
+	int i;
+	u32 fetch_info, fetch_active = 0;
+
+	if (!ctx)  {
+		DRM_ERROR("invalid args - ctx invalid\n");
+		return 0;
+	}
+
+	fetch_info = SDE_REG_READ(&ctx->hw, CTL_FETCH_PIPE_ACTIVE);
+
+	for (i = SSPP_VIG0; i < SSPP_MAX; i++) {
+		if (fetch_tbl[i] != CTL_INVALID_BIT &&
+				fetch_info & BIT(fetch_tbl[i])) {
+			fetch_active |= BIT(i);
+		}
+	}
+
+	return fetch_active;
+}
+
 static inline void _sde_hw_ctl_write_dspp_flushes(struct sde_hw_ctl *ctx) {
 	int i;
 	bool has_dspp_flushes = ctx->caps->features &
@@ -1275,6 +1297,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops,
 		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;
+		ops->get_active_pipes = sde_hw_ctl_get_active_fetch_pipes;
 	} else {
 		ops->update_pending_flush = sde_hw_ctl_update_pending_flush;
 		ops->trigger_flush = sde_hw_ctl_trigger_flush;

+ 8 - 1
msm/sde/sde_hw_ctl.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _SDE_HW_CTL_H
@@ -466,6 +466,13 @@ struct sde_hw_ctl_ops {
 	 */
 	void (*set_active_pipes)(struct sde_hw_ctl *ctx,
 			unsigned long *fetch_active);
+
+	/**
+	 * Get all the sspp marked for fetching on the control path.
+	 * @ctx       : ctl path ctx pointer
+	 * @Return: bitmap of enum sde_sspp pipes found
+	 */
+	u32 (*get_active_pipes)(struct sde_hw_ctl *ctx);
 };
 
 /**

+ 7 - 1
msm/sde/sde_hw_mdss.h

@@ -161,6 +161,12 @@ enum sde_sspp_type {
 	SSPP_TYPE_MAX
 };
 
+enum sde_sspp_rect {
+	R0,
+	R1,
+	R_MAX
+};
+
 enum sde_lm {
 	LM_0 = 1,
 	LM_1,
@@ -655,7 +661,7 @@ struct sde_splash_display {
 	u8 lm_ids[MAX_DATA_PATH_PER_DSIPLAY];
 	u8 dsc_ids[MAX_DATA_PATH_PER_DSIPLAY];
 	u8 vdc_ids[MAX_DATA_PATH_PER_DSIPLAY];
-	struct sde_sspp_index_info pipes[MAX_DATA_PATH_PER_DSIPLAY];
+	struct sde_sspp_index_info pipes[SSPP_MAX];
 	u8 ctl_cnt;
 	u8 lm_cnt;
 	u8 dsc_cnt;

+ 0 - 7
msm/sde/sde_plane.c

@@ -60,13 +60,6 @@
 #define TIME_MULTIPLEX_RECT(r0, r1, buffer_lines) \
 	 ((r0).y >= ((r1).y + (r1).h + buffer_lines))
 
-/* multirect rect index */
-enum {
-	R0,
-	R1,
-	R_MAX
-};
-
 #define SDE_QSEED_DEFAULT_DYN_EXP 0x0
 
 /**

+ 82 - 9
msm/sde/sde_rm.c

@@ -1857,6 +1857,60 @@ static int _sde_rm_make_next_rsvp(struct sde_rm *rm, struct drm_encoder *enc,
 	return ret;
 }
 
+static int _sde_rm_update_pipe_cnt_from_active(
+		struct sde_splash_display *splash_display,
+		u32 active_pipes_mask)
+{
+	int i;
+	u32 sspp_present = 0, space_remain = 0;
+
+	if (!active_pipes_mask) {
+		return 0;
+	} else if (!splash_display) {
+		SDE_ERROR("invalid splash display provided\n");
+		return -EINVAL;
+	} else if (splash_display->pipe_cnt >=
+			ARRAY_SIZE(splash_display->pipes)) {
+		SDE_ERROR("no room to add active pipes to pipe array\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < splash_display->pipe_cnt; i++)
+		sspp_present |= BIT(splash_display->pipes[i].sspp);
+
+	space_remain = ARRAY_SIZE(splash_display->pipes)
+			- splash_display->pipe_cnt;
+
+	for (i = SSPP_VIG0; i < SSPP_MAX; i++) {
+		/* Skip planes already present in the array */
+		if (!(active_pipes_mask & BIT(i)) ||
+				(sspp_present & BIT(i)))
+			continue;
+
+		if (space_remain < R_MAX) {
+			SDE_ERROR("not enough room to add active pipe %d", i);
+			return -EINVAL;
+		}
+
+		/*
+		 * A plane in active but not sspp_present indicates a non-pixel
+		 * plane. Register both rectangles as we can't differentiate
+		 */
+		splash_display->pipes[splash_display->pipe_cnt].sspp = i;
+		splash_display->pipes[splash_display->pipe_cnt].is_virtual =
+				false;
+		splash_display->pipe_cnt++;
+		space_remain--;
+		splash_display->pipes[splash_display->pipe_cnt].sspp = i;
+		splash_display->pipes[splash_display->pipe_cnt].is_virtual =
+				true;
+		splash_display->pipe_cnt++;
+		space_remain--;
+	}
+
+	return 0;
+}
+
 /**
  * _sde_rm_get_hw_blk_for_cont_splash - retrieve the LM blocks on given CTL
  * and populate the connected HW blk ids in sde_splash_display
@@ -1869,9 +1923,10 @@ static int _sde_rm_get_hw_blk_for_cont_splash(struct sde_rm *rm,
 		struct sde_hw_ctl *ctl,
 		struct sde_splash_display *splash_display)
 {
-	u32 lm_reg;
+	u32 lm_reg, max_cnt, active_pipes_mask = 0;
 	struct sde_rm_hw_iter iter_lm, iter_dsc;
 	struct sde_kms *sde_kms;
+	size_t start_count;
 
 	if (!rm || !ctl || !splash_display) {
 		SDE_ERROR("invalid input parameters\n");
@@ -1879,6 +1934,7 @@ static int _sde_rm_get_hw_blk_for_cont_splash(struct sde_rm *rm,
 	}
 
 	sde_kms = container_of(rm, struct sde_kms, rm);
+	max_cnt = ARRAY_SIZE(splash_display->pipes);
 
 	sde_rm_init_hw_iter(&iter_lm, 0, SDE_HW_BLK_LM);
 	sde_rm_init_hw_iter(&iter_dsc, 0, SDE_HW_BLK_DSC);
@@ -1895,24 +1951,41 @@ static int _sde_rm_get_hw_blk_for_cont_splash(struct sde_rm *rm,
 		SDE_DEBUG("lm_cnt=%d lm_reg[%d]=0x%x\n", splash_display->lm_cnt,
 				iter_lm.blk->id - LM_0, lm_reg);
 
-		if (ctl->ops.get_staged_sspp &&
-				ctl->ops.get_staged_sspp(ctl, iter_lm.blk->id,
-					&splash_display->pipes[
-					splash_display->pipe_cnt], 1)) {
-			splash_display->pipe_cnt++;
-		} else if (sde_kms->splash_data.type == SDE_VM_HANDOFF) {
+		start_count = splash_display->pipe_cnt;
+		if (ctl->ops.get_staged_sspp) {
+			struct sde_sspp_index_info *start =
+				&splash_display->pipes[
+					splash_display->pipe_cnt];
+
+			splash_display->pipe_cnt += ctl->ops.get_staged_sspp(
+					ctl, iter_lm.blk->id, start,
+					max_cnt - splash_display->pipe_cnt);
+		}
+
+		if (sde_kms->splash_data.type == SDE_VM_HANDOFF) {
 			/* Allow VM handoff without any pipes, as it is a
 			 * valid case to have NULL commit before the
 			 * transition.
 			 */
 			SDE_DEBUG("VM handoff with no pipes staged\n");
-		} else {
-			SDE_ERROR("no pipe detected on LM-%d\n",
+		} else if (start_count == splash_display->pipe_cnt) {
+			SDE_ERROR("no pipes detected on LM-%d\n",
 					iter_lm.blk->id - LM_0);
 			return 0;
+		} else if (splash_display->pipe_cnt > max_cnt) {
+			SDE_ERROR("found %d pipes exceed max of %d\n",
+					splash_display->pipe_cnt, max_cnt);
+			return 0;
 		}
 	}
 
+	if (ctl->ops.get_active_pipes)
+		active_pipes_mask = ctl->ops.get_active_pipes(ctl);
+
+	if (_sde_rm_update_pipe_cnt_from_active(splash_display,
+			active_pipes_mask))
+		return 0;
+
 	while (_sde_rm_get_hw_locked(rm, &iter_dsc)) {
 		if (ctl->ops.read_active_status &&
 				!(ctl->ops.read_active_status(ctl,