diff options
author | Dhaval Patel <pdhaval@codeaurora.org> | 2020-01-31 14:20:32 -0800 |
---|---|---|
committer | Dhaval Patel <pdhaval@codeaurora.org> | 2020-02-03 14:57:16 -0800 |
commit | 2ce4335f1ba4c150846815a40b5a6e211cc7744b (patch) | |
tree | a293eaad0f873be26bcac084adb5aa16420d9284 | |
parent | c0018ab698f7a12456290a6b48b4b0b0c2c4a9cc (diff) | |
download | display-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.c | 144 | ||||
-rw-r--r-- | msm/sde/sde_hw_intf.c | 5 | ||||
-rw-r--r-- | msm/sde/sde_hw_top.c | 31 | ||||
-rw-r--r-- | msm/sde/sde_hw_top.h | 10 |
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 { |