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:
Dhaval Patel
2020-01-31 14:20:32 -08:00
odevzdal Gerrit - the friendly Code Review server
rodič bf06be4737
revize 1a9e3bae54
4 změnil soubory, kde provedl 165 přidání a 31 odebrání

Zobrazit soubor

@@ -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(

Zobrazit soubor

@@ -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);

Zobrazit soubor

@@ -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,

Zobrazit soubor

@@ -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 {