Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ce4335f authored by Dhaval Patel's avatar Dhaval Patel
Browse files

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: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent c0018ab6
Loading
Loading
Loading
Loading
+120 −24
Original line number Diff line number Diff line
@@ -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)
{
	int trial = 0;
	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;

	/*
	 * 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(
+3 −2
Original line number Diff line number Diff line
// 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);

+30 −1
Original line number Diff line number Diff line
// 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,
+9 −1
Original line number Diff line number Diff line
/* 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 {