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>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
bf06be4737
commit
1a9e3bae54
@@ -34,8 +34,9 @@
|
|||||||
#define DEFAULT_TEARCHECK_SYNC_THRESH_CONTINUE 4
|
#define DEFAULT_TEARCHECK_SYNC_THRESH_CONTINUE 4
|
||||||
|
|
||||||
#define SDE_ENC_WR_PTR_START_TIMEOUT_US 20000
|
#define SDE_ENC_WR_PTR_START_TIMEOUT_US 20000
|
||||||
|
#define AUTOREFRESH_SEQ1_POLL_TIME 2000
|
||||||
#define SDE_ENC_MAX_POLL_TIMEOUT_US 2000
|
#define AUTOREFRESH_SEQ2_POLL_TIME 25000
|
||||||
|
#define AUTOREFRESH_SEQ2_POLL_TIMEOUT 1000000
|
||||||
|
|
||||||
static inline int _sde_encoder_phys_cmd_get_idle_timeout(
|
static inline int _sde_encoder_phys_cmd_get_idle_timeout(
|
||||||
struct sde_encoder_phys_cmd *cmd_enc)
|
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);
|
_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(
|
static void sde_encoder_phys_cmd_prepare_commit(
|
||||||
struct sde_encoder_phys *phys_enc)
|
struct sde_encoder_phys *phys_enc)
|
||||||
{
|
{
|
||||||
struct sde_encoder_phys_cmd *cmd_enc =
|
struct sde_encoder_phys_cmd *cmd_enc =
|
||||||
to_sde_encoder_phys_cmd(phys_enc);
|
to_sde_encoder_phys_cmd(phys_enc);
|
||||||
int trial = 0;
|
|
||||||
|
|
||||||
if (!phys_enc)
|
if (!phys_enc)
|
||||||
return;
|
return;
|
||||||
@@ -1761,35 +1880,12 @@ static void sde_encoder_phys_cmd_prepare_commit(
|
|||||||
if (!sde_encoder_phys_cmd_is_autorefresh_enabled(phys_enc))
|
if (!sde_encoder_phys_cmd_is_autorefresh_enabled(phys_enc))
|
||||||
return;
|
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_connect_te(phys_enc, false);
|
||||||
|
_sde_encoder_autorefresh_disable_seq1(phys_enc);
|
||||||
_sde_encoder_phys_cmd_config_autorefresh(phys_enc, 0);
|
_sde_encoder_autorefresh_disable_seq2(phys_enc);
|
||||||
|
|
||||||
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_phys_cmd_connect_te(phys_enc, true);
|
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(
|
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;
|
c = &intf->hw;
|
||||||
|
|
||||||
|
refresh_cfg = SDE_REG_READ(c, INTF_TEAR_AUTOREFRESH_CONFIG);
|
||||||
if (cfg->enable)
|
if (cfg->enable)
|
||||||
refresh_cfg = BIT(31) | cfg->frame_count;
|
refresh_cfg = BIT(31) | cfg->frame_count;
|
||||||
else
|
else
|
||||||
refresh_cfg = 0;
|
refresh_cfg &= ~BIT(31);
|
||||||
|
|
||||||
SDE_REG_WRITE(c, INTF_TEAR_AUTOREFRESH_CONFIG, refresh_cfg);
|
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_INTF_2_SW_TRG_MUX BIT(8)
|
||||||
#define FLD_TE_LINE_INTER_WATERLEVEL_MASK 0xFFFF
|
#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 DANGER_STATUS 0x360
|
||||||
#define SAFE_STATUS 0x364
|
#define SAFE_STATUS 0x364
|
||||||
|
|
||||||
@@ -37,6 +39,7 @@
|
|||||||
#define MDP_WD_TIMER_1_CTL 0x390
|
#define MDP_WD_TIMER_1_CTL 0x390
|
||||||
#define MDP_WD_TIMER_1_CTL2 0x394
|
#define MDP_WD_TIMER_1_CTL2 0x394
|
||||||
#define MDP_WD_TIMER_1_LOAD_VALUE 0x398
|
#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_CTL 0x420
|
||||||
#define MDP_WD_TIMER_2_CTL2 0x424
|
#define MDP_WD_TIMER_2_CTL2 0x424
|
||||||
#define MDP_WD_TIMER_2_LOAD_VALUE 0x428
|
#define MDP_WD_TIMER_2_LOAD_VALUE 0x428
|
||||||
@@ -51,6 +54,9 @@
|
|||||||
#define XO_CLK_RATE 19200
|
#define XO_CLK_RATE 19200
|
||||||
#define MS_TICKS_IN_SEC 1000
|
#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) \
|
#define CALCULATE_WD_LOAD_VALUE(fps) \
|
||||||
((uint32_t)((MS_TICKS_IN_SEC * XO_CLK_RATE)/(MDP_TICK_COUNT * 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,
|
static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops,
|
||||||
unsigned long cap)
|
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) ||
|
if (cap & BIT(SDE_MDP_DHDR_MEMPOOL_4K) ||
|
||||||
cap & BIT(SDE_MDP_DHDR_MEMPOOL))
|
cap & BIT(SDE_MDP_DHDR_MEMPOOL))
|
||||||
ops->set_hdr_plus_metadata = sde_hw_set_hdr_plus_metadata;
|
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,
|
static const struct sde_mdp_cfg *_top_offset(enum sde_mdp mdp,
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* 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
|
#ifndef _SDE_HW_TOP_H
|
||||||
@@ -215,6 +215,14 @@ struct sde_hw_mdp_ops {
|
|||||||
*/
|
*/
|
||||||
void (*set_hdr_plus_metadata)(struct sde_hw_mdp *mdp,
|
void (*set_hdr_plus_metadata)(struct sde_hw_mdp *mdp,
|
||||||
u8 *payload, u32 len, u32 stream_id);
|
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 {
|
struct sde_hw_mdp {
|
||||||
|
Reference in New Issue
Block a user