Browse Source

disp: msm: sde: update autorefresh disable sequence

Autorefresh might be still in enabled state after
write_ptr reached to display height. This patch
checks the autorefresh status bit and keeps polling
the bit till autorefresh sequence is in enabled
state. It times out after 1 second if autorefresh
is still in enabled state.

Change-Id: I5d4f4cb35e5cc8c680c1878f52cee385f709d764
Signed-off-by: Dhaval Patel <[email protected]>
Dhaval Patel 5 years ago
parent
commit
1a9e3bae54
4 changed files with 160 additions and 26 deletions
  1. 120 24
      msm/sde/sde_encoder_phys_cmd.c
  2. 2 1
      msm/sde/sde_hw_intf.c
  3. 29 0
      msm/sde/sde_hw_top.c
  4. 9 1
      msm/sde/sde_hw_top.h

+ 120 - 24
msm/sde/sde_encoder_phys_cmd.c

@@ -34,8 +34,9 @@
 #define DEFAULT_TEARCHECK_SYNC_THRESH_CONTINUE	4
 
 #define SDE_ENC_WR_PTR_START_TIMEOUT_US 20000
-
-#define SDE_ENC_MAX_POLL_TIMEOUT_US	2000
+#define AUTOREFRESH_SEQ1_POLL_TIME	2000
+#define AUTOREFRESH_SEQ2_POLL_TIME	25000
+#define AUTOREFRESH_SEQ2_POLL_TIMEOUT	1000000
 
 static inline int _sde_encoder_phys_cmd_get_idle_timeout(
 		struct sde_encoder_phys_cmd *cmd_enc)
@@ -1742,40 +1743,26 @@ static void sde_encoder_phys_cmd_update_split_role(
 	_sde_encoder_phys_cmd_update_flush_mask(phys_enc);
 }
 
-static void sde_encoder_phys_cmd_prepare_commit(
+static void _sde_encoder_autorefresh_disable_seq1(
 		struct sde_encoder_phys *phys_enc)
 {
-	struct sde_encoder_phys_cmd *cmd_enc =
-		to_sde_encoder_phys_cmd(phys_enc);
 	int trial = 0;
-
-	if (!phys_enc)
-		return;
-
-	if (!sde_encoder_phys_cmd_is_master(phys_enc))
-		return;
-
-	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->intf_idx - INTF_0,
-			cmd_enc->autorefresh.cfg.enable);
-
-	if (!sde_encoder_phys_cmd_is_autorefresh_enabled(phys_enc))
-		return;
+	struct sde_encoder_phys_cmd *cmd_enc =
+				to_sde_encoder_phys_cmd(phys_enc);
 
 	/*
 	 * If autorefresh is enabled, disable it and make sure it is safe to
 	 * proceed with current frame commit/push. Sequence fallowed is,
-	 * 1. Disable TE
+	 * 1. Disable TE - caller will take care of it
 	 * 2. Disable autorefresh config
 	 * 4. Poll for frame transfer ongoing to be false
-	 * 5. Enable TE back
+	 * 5. Enable TE back - caller will take care of it
 	 */
-	sde_encoder_phys_cmd_connect_te(phys_enc, false);
-
 	_sde_encoder_phys_cmd_config_autorefresh(phys_enc, 0);
 
 	do {
-		udelay(SDE_ENC_MAX_POLL_TIMEOUT_US);
-		if ((trial * SDE_ENC_MAX_POLL_TIMEOUT_US)
+		udelay(AUTOREFRESH_SEQ1_POLL_TIME);
+		if ((trial * AUTOREFRESH_SEQ1_POLL_TIME)
 				> (KICKOFF_TIMEOUT_MS * USEC_PER_MSEC)) {
 			SDE_ERROR_CMDENC(cmd_enc,
 					"disable autorefresh failed\n");
@@ -1786,10 +1773,119 @@ static void sde_encoder_phys_cmd_prepare_commit(
 
 		trial++;
 	} while (_sde_encoder_phys_cmd_is_ongoing_pptx(phys_enc));
+}
+
+static void _sde_encoder_autorefresh_disable_seq2(
+		struct sde_encoder_phys *phys_enc)
+{
+	int trial = 0;
+	struct sde_hw_mdp *hw_mdp = phys_enc->hw_mdptop;
+	u32 autorefresh_status = 0;
+	struct sde_encoder_phys_cmd *cmd_enc =
+				to_sde_encoder_phys_cmd(phys_enc);
+
+	if (!hw_mdp->ops.get_autorefresh_status) {
+		SDE_DEBUG_CMDENC(cmd_enc,
+			"autofresh disable seq2 not supported\n");
+		return;
+	}
+
+	/*
+	 * If autorefresh is still enabled after sequence-1, proceed with
+	 * below sequence-2.
+	 * 1. Disable TEAR CHECK
+	 * 2. Disable autorefresh config
+	 * 4. Poll for autorefresh to be disabled
+	 * 5. Enable TEAR CHECK
+	 */
+	autorefresh_status = hw_mdp->ops.get_autorefresh_status(hw_mdp,
+					phys_enc->intf_idx);
+	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->intf_idx - INTF_0,
+				autorefresh_status, SDE_EVTLOG_FUNC_CASE1);
+
+	if (!(autorefresh_status & BIT(7))) {
+		usleep_range(AUTOREFRESH_SEQ2_POLL_TIME,
+			AUTOREFRESH_SEQ2_POLL_TIME + 1);
 
+		autorefresh_status = hw_mdp->ops.get_autorefresh_status(hw_mdp,
+					phys_enc->intf_idx);
+		SDE_EVT32(DRMID(phys_enc->parent), phys_enc->intf_idx - INTF_0,
+				autorefresh_status, SDE_EVTLOG_FUNC_CASE2);
+	}
+
+	if (autorefresh_status & BIT(7)) {
+		SDE_ERROR_CMDENC(cmd_enc, "autofresh status:0x%x intf:%d\n",
+			autorefresh_status, phys_enc->intf_idx - INTF_0);
+
+		if (phys_enc->has_intf_te &&
+		    phys_enc->hw_intf->ops.enable_tearcheck)
+			phys_enc->hw_intf->ops.enable_tearcheck(
+				phys_enc->hw_intf, false);
+		else if (phys_enc->hw_pp->ops.enable_tearcheck)
+			phys_enc->hw_pp->ops.enable_tearcheck(
+				phys_enc->hw_pp, false);
+
+		_sde_encoder_phys_cmd_config_autorefresh(phys_enc, 0);
+
+		do {
+			usleep_range(AUTOREFRESH_SEQ2_POLL_TIME,
+				AUTOREFRESH_SEQ2_POLL_TIME + 1);
+			if ((trial * AUTOREFRESH_SEQ2_POLL_TIME)
+				> AUTOREFRESH_SEQ2_POLL_TIMEOUT) {
+				SDE_ERROR_CMDENC(cmd_enc,
+					"disable autorefresh failed\n");
+				SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus",
+						"panic");
+				break;
+			}
+
+			trial++;
+			autorefresh_status =
+			    hw_mdp->ops.get_autorefresh_status(hw_mdp,
+					phys_enc->intf_idx);
+			SDE_ERROR_CMDENC(cmd_enc,
+				"autofresh status:0x%x intf:%d\n",
+				autorefresh_status,
+				phys_enc->intf_idx - INTF_0);
+			SDE_EVT32(DRMID(phys_enc->parent),
+				phys_enc->intf_idx - INTF_0,
+				autorefresh_status);
+		} while (autorefresh_status & BIT(7));
+
+		if (phys_enc->has_intf_te &&
+		    phys_enc->hw_intf->ops.enable_tearcheck)
+			phys_enc->hw_intf->ops.enable_tearcheck(
+				phys_enc->hw_intf, true);
+		else if (phys_enc->hw_pp->ops.enable_tearcheck)
+			phys_enc->hw_pp->ops.enable_tearcheck(
+				phys_enc->hw_pp, true);
+	}
+}
+
+static void sde_encoder_phys_cmd_prepare_commit(
+		struct sde_encoder_phys *phys_enc)
+{
+	struct sde_encoder_phys_cmd *cmd_enc =
+		to_sde_encoder_phys_cmd(phys_enc);
+
+	if (!phys_enc)
+		return;
+
+	if (!sde_encoder_phys_cmd_is_master(phys_enc))
+		return;
+
+	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->intf_idx - INTF_0,
+			cmd_enc->autorefresh.cfg.enable);
+
+	if (!sde_encoder_phys_cmd_is_autorefresh_enabled(phys_enc))
+		return;
+
+	sde_encoder_phys_cmd_connect_te(phys_enc, false);
+	_sde_encoder_autorefresh_disable_seq1(phys_enc);
+	_sde_encoder_autorefresh_disable_seq2(phys_enc);
 	sde_encoder_phys_cmd_connect_te(phys_enc, true);
 
-	SDE_DEBUG_CMDENC(cmd_enc, "disabled autorefresh\n");
+	SDE_DEBUG_CMDENC(cmd_enc, "autorefresh disabled successfully\n");
 }
 
 static void sde_encoder_phys_cmd_trigger_start(

+ 2 - 1
msm/sde/sde_hw_intf.c

@@ -550,10 +550,11 @@ static int sde_hw_intf_setup_autorefresh_config(struct sde_hw_intf *intf,
 
 	c = &intf->hw;
 
+	refresh_cfg = SDE_REG_READ(c, INTF_TEAR_AUTOREFRESH_CONFIG);
 	if (cfg->enable)
 		refresh_cfg = BIT(31) | cfg->frame_count;
 	else
-		refresh_cfg = 0;
+		refresh_cfg &= ~BIT(31);
 
 	SDE_REG_WRITE(c, INTF_TEAR_AUTOREFRESH_CONFIG, refresh_cfg);
 

+ 29 - 0
msm/sde/sde_hw_top.c

@@ -21,6 +21,8 @@
 #define FLD_INTF_2_SW_TRG_MUX             BIT(8)
 #define FLD_TE_LINE_INTER_WATERLEVEL_MASK 0xFFFF
 
+#define MDP_DSPP_DBGBUS_CTRL              0x348
+#define MDP_DSPP_DBGBUS_STATUS            0x34C
 #define DANGER_STATUS                     0x360
 #define SAFE_STATUS                       0x364
 
@@ -37,6 +39,7 @@
 #define MDP_WD_TIMER_1_CTL                0x390
 #define MDP_WD_TIMER_1_CTL2               0x394
 #define MDP_WD_TIMER_1_LOAD_VALUE         0x398
+#define MDP_PERIPH_DBGBUS_CTRL            0x418
 #define MDP_WD_TIMER_2_CTL                0x420
 #define MDP_WD_TIMER_2_CTL2               0x424
 #define MDP_WD_TIMER_2_LOAD_VALUE         0x428
@@ -51,6 +54,9 @@
 #define XO_CLK_RATE                       19200
 #define MS_TICKS_IN_SEC                   1000
 
+#define AUTOREFRESH_TEST_POINT	0x2
+#define TEST_MASK(id, tp)	((id << 4) | (tp << 1) | BIT(0))
+
 #define CALCULATE_WD_LOAD_VALUE(fps) \
 	((uint32_t)((MS_TICKS_IN_SEC * XO_CLK_RATE)/(MDP_TICK_COUNT * fps)))
 
@@ -526,6 +532,28 @@ static void sde_hw_set_hdr_plus_metadata(struct sde_hw_mdp *mdp,
 	}
 }
 
+static u32 sde_hw_get_autorefresh_status(struct sde_hw_mdp *mdp, u32 intf_idx)
+{
+	struct sde_hw_blk_reg_map *c;
+	u32 autorefresh_status;
+	u32 blk_id = (intf_idx == INTF_2) ? 65 : 64;
+
+	if (!mdp)
+		return 0;
+
+	c = &mdp->hw;
+
+	SDE_REG_WRITE(&mdp->hw, MDP_PERIPH_DBGBUS_CTRL,
+			TEST_MASK(blk_id, AUTOREFRESH_TEST_POINT));
+	SDE_REG_WRITE(&mdp->hw, MDP_DSPP_DBGBUS_CTRL, 0x7001);
+	wmb(); /* make sure test bits were written */
+
+	autorefresh_status = SDE_REG_READ(&mdp->hw, MDP_DSPP_DBGBUS_STATUS);
+	SDE_REG_WRITE(&mdp->hw, MDP_PERIPH_DBGBUS_CTRL, 0x0);
+
+	return autorefresh_status;
+}
+
 static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops,
 		unsigned long cap)
 {
@@ -550,6 +578,7 @@ static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops,
 	if (cap & BIT(SDE_MDP_DHDR_MEMPOOL_4K) ||
 			cap & BIT(SDE_MDP_DHDR_MEMPOOL))
 		ops->set_hdr_plus_metadata = sde_hw_set_hdr_plus_metadata;
+	ops->get_autorefresh_status = sde_hw_get_autorefresh_status;
 }
 
 static const struct sde_mdp_cfg *_top_offset(enum sde_mdp mdp,

+ 9 - 1
msm/sde/sde_hw_top.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _SDE_HW_TOP_H
@@ -215,6 +215,14 @@ struct sde_hw_mdp_ops {
 	 */
 	void (*set_hdr_plus_metadata)(struct sde_hw_mdp *mdp,
 			u8 *payload, u32 len, u32 stream_id);
+
+	/**
+	 * get_autorefresh_status - get autorefresh status
+	 * @mdp:     mdp top context driver
+	 * @intf_idx:  intf block index for relative information
+	 */
+	u32 (*get_autorefresh_status)(struct sde_hw_mdp *mdp,
+			u32 intf_idx);
 };
 
 struct sde_hw_mdp {