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>
Tento commit je obsažen v:

odevzdal
Gerrit - the friendly Code Review server

rodič
bf06be4737
revize
1a9e3bae54
@@ -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,12 +1743,130 @@ static void sde_encoder_phys_cmd_update_split_role(
|
||||
_sde_encoder_phys_cmd_update_flush_mask(phys_enc);
|
||||
}
|
||||
|
||||
static void _sde_encoder_autorefresh_disable_seq1(
|
||||
struct sde_encoder_phys *phys_enc)
|
||||
{
|
||||
int trial = 0;
|
||||
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 - caller will take care of it
|
||||
* 2. Disable autorefresh config
|
||||
* 4. Poll for frame transfer ongoing to be false
|
||||
* 5. Enable TE back - caller will take care of it
|
||||
*/
|
||||
_sde_encoder_phys_cmd_config_autorefresh(phys_enc, 0);
|
||||
|
||||
do {
|
||||
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");
|
||||
|
||||
phys_enc->enable_state = SDE_ENC_ERR_NEEDS_HW_RESET;
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
int trial = 0;
|
||||
|
||||
if (!phys_enc)
|
||||
return;
|
||||
@@ -1761,35 +1880,12 @@ static void sde_encoder_phys_cmd_prepare_commit(
|
||||
if (!sde_encoder_phys_cmd_is_autorefresh_enabled(phys_enc))
|
||||
return;
|
||||
|
||||
/*
|
||||
* 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
|
||||
* 2. Disable autorefresh config
|
||||
* 4. Poll for frame transfer ongoing to be false
|
||||
* 5. Enable TE back
|
||||
*/
|
||||
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)
|
||||
> (KICKOFF_TIMEOUT_MS * USEC_PER_MSEC)) {
|
||||
SDE_ERROR_CMDENC(cmd_enc,
|
||||
"disable autorefresh failed\n");
|
||||
|
||||
phys_enc->enable_state = SDE_ENC_ERR_NEEDS_HW_RESET;
|
||||
break;
|
||||
}
|
||||
|
||||
trial++;
|
||||
} while (_sde_encoder_phys_cmd_is_ongoing_pptx(phys_enc));
|
||||
|
||||
_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(
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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 {
|
||||
|
Odkázat v novém úkolu
Zablokovat Uživatele