summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDhaval Patel <pdhaval@codeaurora.org>2020-01-31 14:20:32 -0800
committerDhaval Patel <pdhaval@codeaurora.org>2020-02-03 14:57:16 -0800
commit2ce4335f1ba4c150846815a40b5a6e211cc7744b (patch)
treea293eaad0f873be26bcac084adb5aa16420d9284
parentc0018ab698f7a12456290a6b48b4b0b0c2c4a9cc (diff)
downloaddisplay-drivers-2ce4335f1ba4c150846815a40b5a6e211cc7744b.tar.gz
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 <pdhaval@codeaurora.org>
-rw-r--r--msm/sde/sde_encoder_phys_cmd.c144
-rw-r--r--msm/sde/sde_hw_intf.c5
-rw-r--r--msm/sde/sde_hw_top.c31
-rw-r--r--msm/sde/sde_hw_top.h10
4 files changed, 162 insertions, 28 deletions
diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c
index 2f4e8a99..1a49b873 100644
--- a/msm/sde/sde_encoder_phys_cmd.c
+++ b/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)
@@ -1735,40 +1736,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");
@@ -1779,10 +1766,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(
diff --git a/msm/sde/sde_hw_intf.c b/msm/sde/sde_hw_intf.c
index a7a68189..89fd3a55 100644
--- a/msm/sde/sde_hw_intf.c
+++ b/msm/sde/sde_hw_intf.c
@@ -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.
*/
#include <linux/iopoll.h>
@@ -514,10 +514,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);
diff --git a/msm/sde/sde_hw_top.c b/msm/sde/sde_hw_top.c
index 7c2de6c3..b02cd17c 100644
--- a/msm/sde/sde_hw_top.c
+++ b/msm/sde/sde_hw_top.c
@@ -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.
*/
#include "sde_hwio.h"
@@ -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)))
@@ -513,6 +519,28 @@ static void sde_hw_set_hdr_plus_metadata(struct sde_hw_mdp *mdp,
SDE_REG_WRITE(&mdp->hw, DP_DHDR_MEM_POOL_0_DATA + offset, data);
}
+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)
{
@@ -535,6 +563,7 @@ static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops,
ops->setup_vsync_source = sde_hw_setup_vsync_source_v1;
if (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,
diff --git a/msm/sde/sde_hw_top.h b/msm/sde/sde_hw_top.h
index bda4da7d..21f1daf1 100644
--- a/msm/sde/sde_hw_top.h
+++ b/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 {