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

Commit f6f6ba22 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/gem: add cache flush api in msm_gem"

parents c538e1a2 6d3f4120
Loading
Loading
Loading
Loading
+111 −11
Original line number Diff line number Diff line
@@ -33,24 +33,52 @@
/* Register Offsets from PLL base address */
#define PLL_ANALOG_CONTROLS_ONE			0x000
#define PLL_ANALOG_CONTROLS_TWO			0x004
#define PLL_INT_LOOP_SETTINGS			0x008
#define PLL_INT_LOOP_SETTINGS_TWO		0x00c
#define PLL_ANALOG_CONTROLS_THREE		0x010
#define PLL_ANALOG_CONTROLS_FOUR		0x014
#define PLL_INT_LOOP_CONTROLS			0x018
#define PLL_DSM_DIVIDER				0x01c
#define PLL_FEEDBACK_DIVIDER			0x020
#define PLL_SYSTEM_MUXES			0x024
#define PLL_FREQ_UPDATE_CONTROL_OVERRIDES	0x028
#define PLL_CMODE				0x02c
#define PLL_CALIBRATION_SETTINGS		0x030
#define PLL_BAND_SEL_CAL_TIMER_LOW		0x034
#define PLL_BAND_SEL_CAL_TIMER_HIGH		0x038
#define PLL_BAND_SEL_CAL_SETTINGS		0x03c
#define PLL_BAND_SEL_MIN			0x040
#define PLL_BAND_SEL_MAX			0x044
#define PLL_BAND_SEL_PFILT			0x048
#define PLL_BAND_SEL_IFILT			0x04c
#define PLL_BAND_SEL_CAL_SETTINGS_TWO		0x050
#define PLL_BAND_SEL_CAL_SETTINGS_THREE		0x054
#define PLL_BAND_SEL_CAL_SETTINGS_FOUR		0x058
#define PLL_BAND_SEL_ICODE_HIGH			0x05c
#define PLL_BAND_SEL_ICODE_LOW			0x060
#define PLL_FREQ_DETECT_SETTINGS_ONE		0x064
#define PLL_PFILT				0x07c
#define PLL_IFILT				0x080
#define PLL_GAIN				0x084
#define PLL_ICODE_LOW				0x088
#define PLL_ICODE_HIGH				0x08c
#define PLL_LOCKDET				0x090
#define PLL_OUTDIV				0x094
#define PLL_FASTLOCK_CONTROL			0x098
#define PLL_PASS_OUT_OVERRIDE_ONE		0x09c
#define PLL_PASS_OUT_OVERRIDE_TWO		0x0a0
#define PLL_CORE_OVERRIDE			0x0a4
#define PLL_CORE_INPUT_OVERRIDE			0x0a8
#define PLL_RATE_CHANGE				0x0ac
#define PLL_PLL_DIGITAL_TIMERS			0x0b0
#define PLL_PLL_DIGITAL_TIMERS_TWO		0x0b4
#define PLL_DEC_FRAC_MUXES			0x0c8
#define PLL_DECIMAL_DIV_START_1			0x0cc
#define PLL_FRAC_DIV_START_LOW_1		0x0d0
#define PLL_FRAC_DIV_START_MID_1		0x0d4
#define PLL_FRAC_DIV_START_HIGH_1		0x0d8
#define PLL_MASH_CONTROL			0x0ec
#define PLL_SSC_MUX_CONTROL			0x108
#define PLL_SSC_STEPSIZE_LOW_1			0x10c
#define PLL_SSC_STEPSIZE_HIGH_1			0x110
#define PLL_SSC_DIV_PER_LOW_1			0x114
@@ -64,9 +92,16 @@
#define PLL_PLL_BAND_SET_RATE_1			0x154
#define PLL_PLL_INT_GAIN_IFILT_BAND_1		0x15c
#define PLL_PLL_FL_INT_GAIN_PFILT_BAND_1	0x164
#define PLL_FASTLOCK_EN_BAND			0x16c
#define PLL_FREQ_TUNE_ACCUM_INIT_MUX		0x17c
#define PLL_PLL_LOCK_OVERRIDE			0x180
#define PLL_PLL_LOCK_DELAY			0x184
#define PLL_PLL_LOCK_MIN_DELAY			0x188
#define PLL_CLOCK_INVERTERS			0x18c
#define PLL_SPARE_AND_JPC_OVERRIDES		0x190
#define PLL_BIAS_CONTROL_1			0x194
#define PLL_BIAS_CONTROL_2			0x198
#define PLL_ALOG_OBSV_BUS_CTRL_1		0x19c
#define PLL_COMMON_STATUS_ONE			0x1a0

/* Register Offsets from PHY base address */
@@ -249,7 +284,7 @@ static inline int pclk_mux_read_sel(void *context, unsigned int reg,
	if (rc)
		pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
	else
		*val = (MDSS_PLL_REG_R(rsc->pll_base, reg) & 0x3);
		*val = (MDSS_PLL_REG_R(rsc->phy_base, reg) & 0x3);

	(void)mdss_pll_resource_enable(rsc, false);
	return rc;
@@ -503,6 +538,49 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_10nm *pll,
	MDSS_PLL_REG_W(pll_base, PLL_IFILT, 0x3f);
}

static void dsi_pll_init_val(struct mdss_pll_resources *rsc)
{
	void __iomem *pll_base = rsc->pll_base;

	MDSS_PLL_REG_W(pll_base, PLL_CORE_INPUT_OVERRIDE, 0x10);
	MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS, 0x3f);
	MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS_TWO, 0x0);
	MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_FOUR, 0x0);
	MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_CONTROLS, 0x80);
	MDSS_PLL_REG_W(pll_base, PLL_FREQ_UPDATE_CONTROL_OVERRIDES, 0x0);
	MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_LOW, 0x0);
	MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_HIGH, 0x02);
	MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS, 0x82);
	MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_MIN, 0x00);
	MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_MAX, 0xff);
	MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_PFILT, 0x00);
	MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_IFILT, 0x00);
	MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_TWO, 0x25);
	MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_FOUR, 0x4f);
	MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_HIGH, 0x0a);
	MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_LOW, 0x0);
	MDSS_PLL_REG_W(pll_base, PLL_GAIN, 0x42);
	MDSS_PLL_REG_W(pll_base, PLL_ICODE_LOW, 0x00);
	MDSS_PLL_REG_W(pll_base, PLL_ICODE_HIGH, 0x00);
	MDSS_PLL_REG_W(pll_base, PLL_LOCKDET, 0x30);
	MDSS_PLL_REG_W(pll_base, PLL_FASTLOCK_CONTROL, 0x04);
	MDSS_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_ONE, 0x00);
	MDSS_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_TWO, 0x00);
	MDSS_PLL_REG_W(pll_base, PLL_RATE_CHANGE, 0x01);
	MDSS_PLL_REG_W(pll_base, PLL_PLL_DIGITAL_TIMERS, 0x08);
	MDSS_PLL_REG_W(pll_base, PLL_DEC_FRAC_MUXES, 0x00);
	MDSS_PLL_REG_W(pll_base, PLL_MASH_CONTROL, 0x03);
	MDSS_PLL_REG_W(pll_base, PLL_SSC_MUX_CONTROL, 0x0);
	MDSS_PLL_REG_W(pll_base, PLL_SSC_CONTROL, 0x0);
	MDSS_PLL_REG_W(pll_base, PLL_FASTLOCK_EN_BAND, 0x03);
	MDSS_PLL_REG_W(pll_base, PLL_FREQ_TUNE_ACCUM_INIT_MUX, 0x0);
	MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_MIN_DELAY, 0x19);
	MDSS_PLL_REG_W(pll_base, PLL_SPARE_AND_JPC_OVERRIDES, 0x0);
	MDSS_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_1, 0x40);
	MDSS_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_2, 0x20);
	MDSS_PLL_REG_W(pll_base, PLL_ALOG_OBSV_BUS_CTRL_1, 0x0);
}

static void dsi_pll_commit(struct dsi_pll_10nm *pll,
			   struct mdss_pll_resources *rsc)
{
@@ -559,6 +637,8 @@ static int vco_10nm_set_rate(struct clk_hw *hw, unsigned long rate,
		return rc;
	}

	dsi_pll_init_val(rsc);

	dsi_pll_setup_config(pll, rsc);

	dsi_pll_calc_dec_frac(pll, rsc);
@@ -741,12 +821,32 @@ static void vco_10nm_unprepare(struct clk_hw *hw)
		pr_err("dsi pll resources not available\n");
		return;
	}
	pll->cached_cfg0 = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0);
	pll->cached_outdiv = MDSS_PLL_REG_R(pll->pll_base, PLL_PLL_OUTDIV_RATE);

	/*
	 * During unprepare in continuous splash use case we want driver
	 * to pick all dividers instead of retaining bootloader configurations.
	 */
	if (!pll->handoff_resources) {
		pll->cached_cfg0 = MDSS_PLL_REG_R(pll->phy_base,
							PHY_CMN_CLK_CFG0);
		pll->cached_outdiv = MDSS_PLL_REG_R(pll->pll_base,
							PLL_PLL_OUTDIV_RATE);
		pr_debug("cfg0=%d,cfg1=%d, outdiv=%d\n", pll->cached_cfg0,
					pll->cached_cfg1, pll->cached_outdiv);

		pll->vco_cached_rate = clk_hw_get_rate(hw);
	}

	/*
	 * When continuous splash screen feature is enabled, we need to cache
	 * the mux configuration for the pixel_clk_src mux clock. The clock
	 * framework does not call back to re-configure the mux value if it is
	 * does not change.For such usecases, we need to ensure that the cached
	 * value is programmed prior to PLL being locked
	 */
	if (pll->handoff_resources)
		pll->cached_cfg1 = MDSS_PLL_REG_R(pll->phy_base,
							PHY_CMN_CLK_CFG1);
	dsi_pll_disable(vco);
	mdss_pll_resource_enable(pll, false);
}
@@ -1026,8 +1126,8 @@ static struct regmap_bus pll_regmap_bus = {
	.reg_read = pll_reg_read,
};

static struct regmap_bus pclk_mux_regmap_bus = {
	.reg_read = phy_reg_read,
static struct regmap_bus pclk_src_mux_regmap_bus = {
	.reg_read = pclk_mux_read_sel,
	.reg_write = pclk_mux_write_sel,
};

@@ -1472,7 +1572,7 @@ int dsi_pll_clock_register_10nm(struct platform_device *pdev,
				pll_res, &dsi_pll_10nm_config);
		dsi0pll_pclk_mux.clkr.regmap = rmap;

		rmap = devm_regmap_init(&pdev->dev, &pclk_mux_regmap_bus,
		rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus,
				pll_res, &dsi_pll_10nm_config);
		dsi0pll_pclk_src_mux.clkr.regmap = rmap;
		rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
@@ -1510,11 +1610,11 @@ int dsi_pll_clock_register_10nm(struct platform_device *pdev,
				pll_res, &dsi_pll_10nm_config);
		dsi1pll_pclk_src.clkr.regmap = rmap;

		rmap = devm_regmap_init(&pdev->dev, &pclk_mux_regmap_bus,
		rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
				pll_res, &dsi_pll_10nm_config);
		dsi1pll_pclk_mux.clkr.regmap = rmap;

		rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
		rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus,
				pll_res, &dsi_pll_10nm_config);
		dsi1pll_pclk_src_mux.clkr.regmap = rmap;
		rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
+4 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
			dsi_ctrl_hw_14_reg_dump_to_buffer;
		ctrl->ops.schedule_dma_cmd = NULL;
		ctrl->ops.get_cont_splash_status = NULL;
		ctrl->ops.kickoff_command_non_embedded_mode = NULL;
		break;
	case DSI_CTRL_VERSION_2_0:
		ctrl->ops.setup_lane_map = dsi_ctrl_hw_20_setup_lane_map;
@@ -97,6 +98,7 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
		ctrl->ops.clamp_disable = NULL;
		ctrl->ops.schedule_dma_cmd = NULL;
		ctrl->ops.get_cont_splash_status = NULL;
		ctrl->ops.kickoff_command_non_embedded_mode = NULL;
		break;
	case DSI_CTRL_VERSION_2_2:
		ctrl->ops.phy_reset_config = dsi_ctrl_hw_22_phy_reset_config;
@@ -113,6 +115,8 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
		ctrl->ops.clamp_enable = NULL;
		ctrl->ops.clamp_disable = NULL;
		ctrl->ops.schedule_dma_cmd = dsi_ctrl_hw_22_schedule_dma_cmd;
		ctrl->ops.kickoff_command_non_embedded_mode =
			dsi_ctrl_hw_kickoff_non_embedded_mode;
		break;
	default:
		break;
+3 −0
Original line number Diff line number Diff line
@@ -213,6 +213,9 @@ int dsi_ctrl_hw_20_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes);
ssize_t dsi_ctrl_hw_20_reg_dump_to_buffer(struct dsi_ctrl_hw *ctrl,
					  char *buf,
					  u32 size);
void dsi_ctrl_hw_kickoff_non_embedded_mode(struct dsi_ctrl_hw *ctrl,
					struct dsi_ctrl_cmd_dma_info *cmd,
					u32 flags);

/* Definitions specific to 2.2 DSI controller hardware */
bool dsi_ctrl_hw_22_get_cont_splash_status(struct dsi_ctrl_hw *ctrl);
+134 −31
Original line number Diff line number Diff line
@@ -940,6 +940,62 @@ static void dsi_ctrl_wait_for_video_done(struct dsi_ctrl *dsi_ctrl)
	udelay(sleep_ms * 1000);
}

void dsi_message_setup_tx_mode(struct dsi_ctrl *dsi_ctrl,
		u32 cmd_len,
		u32 *flags)
{
	/**
	 * Setup the mode of transmission
	 * override cmd fetch mode during secure session
	 */
	if (dsi_ctrl->secure_mode) {
		*flags &= ~DSI_CTRL_CMD_FETCH_MEMORY;
		*flags |= DSI_CTRL_CMD_FIFO_STORE;
		pr_debug("[%s] override to TPG during secure session\n",
				dsi_ctrl->name);
		return;
	}

	/* Check to see if cmd len plus header is greater than fifo size */
	if ((cmd_len + 4) > DSI_EMBEDDED_MODE_DMA_MAX_SIZE_BYTES) {
		*flags |= DSI_CTRL_CMD_NON_EMBEDDED_MODE;
		pr_debug("[%s] override to non-embedded mode,cmd len =%d\n",
				dsi_ctrl->name, cmd_len);
		return;
	}
}

int dsi_message_validate_tx_mode(struct dsi_ctrl *dsi_ctrl,
		u32 cmd_len,
		u32 *flags)
{
	int rc = 0;

	if (*flags & DSI_CTRL_CMD_FIFO_STORE) {
		/* if command size plus header is greater than fifo size */
		if ((cmd_len + 4) > DSI_CTRL_MAX_CMD_FIFO_STORE_SIZE) {
			pr_err("Cannot transfer Cmd in FIFO config\n");
			return -ENOTSUPP;
		}
		if (!dsi_ctrl->hw.ops.kickoff_fifo_command) {
			pr_err("Cannot transfer command,ops not defined\n");
			return -ENOTSUPP;
		}
	}

	if (*flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
		if (*flags & DSI_CTRL_CMD_BROADCAST) {
			pr_err("Non embedded not supported with broadcast\n");
			return -ENOTSUPP;
		}
		if (!dsi_ctrl->hw.ops.kickoff_command_non_embedded_mode) {
			pr_err(" Cannot transfer command,ops not defined\n");
			return -ENOTSUPP;
		}
	}
	return rc;
}

static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
			  const struct mipi_dsi_msg *msg,
			  u32 flags)
@@ -954,28 +1010,41 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
	u32 cnt = 0, line_no = 0x1;
	u8 *cmdbuf;
	struct dsi_mode_info *timing;
	struct dsi_ctrl_hw_ops dsi_hw_ops = dsi_ctrl->hw.ops;

	/* override cmd fetch mode during secure session */
	if (dsi_ctrl->secure_mode) {
		flags &= ~DSI_CTRL_CMD_FETCH_MEMORY;
		flags |= DSI_CTRL_CMD_FIFO_STORE;
		pr_debug("[%s] override to TPG during secure session\n",
				dsi_ctrl->name);
	}
	/* Select the tx mode to transfer the command */
	dsi_message_setup_tx_mode(dsi_ctrl, msg->tx_len, &flags);

	rc = mipi_dsi_create_packet(&packet, msg);
	/* Validate the mode before sending the command */
	rc = dsi_message_validate_tx_mode(dsi_ctrl, msg->tx_len, &flags);
	if (rc) {
		pr_err("Failed to create message packet, rc=%d\n", rc);
		pr_err(" Cmd tx validation failed, cannot transfer cmd\n");
		rc = -ENOTSUPP;
		goto error;
	}

	/* fail cmds more than the supported size in TPG mode */
	if ((flags & DSI_CTRL_CMD_FIFO_STORE) &&
			(msg->tx_len > DSI_CTRL_MAX_CMD_FIFO_STORE_SIZE)) {
		pr_err("[%s] TPG cmd size:%zd not supported, secure:%d\n",
				dsi_ctrl->name, msg->tx_len,
				dsi_ctrl->secure_mode);
		rc = -ENOTSUPP;
	if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
		cmd_mem.offset = dsi_ctrl->cmd_buffer_iova;
		cmd_mem.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ?
			true : false;
		cmd_mem.is_master = (flags & DSI_CTRL_CMD_BROADCAST_MASTER) ?
			true : false;
		cmd_mem.use_lpm = (msg->flags & MIPI_DSI_MSG_USE_LPM) ?
			true : false;
		cmd_mem.datatype = msg->type;
		cmd_mem.length = msg->tx_len;

		dsi_ctrl->cmd_len = msg->tx_len;
		memcpy(dsi_ctrl->vaddr, msg->tx_buf, msg->tx_len);
		pr_debug(" non-embedded mode , size of command =%zd\n",
					msg->tx_len);

		goto kickoff;
	}

	rc = mipi_dsi_create_packet(&packet, msg);
	if (rc) {
		pr_err("Failed to create message packet, rc=%d\n", rc);
		goto error;
	}

@@ -993,6 +1062,7 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
		buffer[3] |= BIT(7);//set the last cmd bit in header.

	if (flags & DSI_CTRL_CMD_FETCH_MEMORY) {
		/* Embedded mode config is selected */
		cmd_mem.offset = dsi_ctrl->cmd_buffer_iova;
		cmd_mem.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ?
			true : false;
@@ -1006,6 +1076,7 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
		for (cnt = 0; cnt < length; cnt++)
			cmdbuf[dsi_ctrl->cmd_len + cnt] = buffer[cnt];

		msm_gem_sync(dsi_ctrl->tx_cmd_buf);
		dsi_ctrl->cmd_len += length;

		if (!(msg->flags & MIPI_DSI_MSG_LASTCOMMAND)) {
@@ -1026,15 +1097,16 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
				  true : false;
	}

kickoff:
	timing = &(dsi_ctrl->host_config.video_timing);
	if (timing)
		line_no += timing->v_back_porch + timing->v_sync_width +
				timing->v_active;
	if ((dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) &&
		dsi_ctrl->hw.ops.schedule_dma_cmd &&
		dsi_hw_ops.schedule_dma_cmd &&
		(dsi_ctrl->current_state.vid_engine_state ==
					DSI_CTRL_ENGINE_ON))
		dsi_ctrl->hw.ops.schedule_dma_cmd(&dsi_ctrl->hw,
		dsi_hw_ops.schedule_dma_cmd(&dsi_ctrl->hw,
				line_no);

	hw_flags |= (flags & DSI_CTRL_CMD_DEFER_TRIGGER) ?
@@ -1045,11 +1117,19 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,

	if (flags & DSI_CTRL_CMD_DEFER_TRIGGER) {
		if (flags & DSI_CTRL_CMD_FETCH_MEMORY) {
			dsi_ctrl->hw.ops.kickoff_command(&dsi_ctrl->hw,
			if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
				dsi_hw_ops.kickoff_command_non_embedded_mode(
							&dsi_ctrl->hw,
							&cmd_mem,
							hw_flags);
			} else {
				dsi_hw_ops.kickoff_command(
						&dsi_ctrl->hw,
						&cmd_mem,
						hw_flags);
			}
		} else if (flags & DSI_CTRL_CMD_FIFO_STORE) {
			dsi_ctrl->hw.ops.kickoff_fifo_command(&dsi_ctrl->hw,
			dsi_hw_ops.kickoff_fifo_command(&dsi_ctrl->hw,
							      &cmd,
							      hw_flags);
		}
@@ -1059,17 +1139,25 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
		dsi_ctrl_wait_for_video_done(dsi_ctrl);
		dsi_ctrl_enable_status_interrupt(dsi_ctrl,
					DSI_SINT_CMD_MODE_DMA_DONE, NULL);
		if (dsi_ctrl->hw.ops.mask_error_intr)
			dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
		if (dsi_hw_ops.mask_error_intr)
			dsi_hw_ops.mask_error_intr(&dsi_ctrl->hw,
					BIT(DSI_FIFO_OVERFLOW), true);
		reinit_completion(&dsi_ctrl->irq_info.cmd_dma_done);

		if (flags & DSI_CTRL_CMD_FETCH_MEMORY) {
			dsi_ctrl->hw.ops.kickoff_command(&dsi_ctrl->hw,
			if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
				dsi_hw_ops.kickoff_command_non_embedded_mode(
							&dsi_ctrl->hw,
							&cmd_mem,
							hw_flags);
			} else {
				dsi_hw_ops.kickoff_command(
						&dsi_ctrl->hw,
						&cmd_mem,
						hw_flags);
			}
		} else if (flags & DSI_CTRL_CMD_FIFO_STORE) {
			dsi_ctrl->hw.ops.kickoff_fifo_command(&dsi_ctrl->hw,
			dsi_hw_ops.kickoff_fifo_command(&dsi_ctrl->hw,
							      &cmd,
							      hw_flags);
		}
@@ -1079,14 +1167,14 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
				msecs_to_jiffies(DSI_CTRL_TX_TO_MS));

		if (ret == 0) {
			u32 status = dsi_ctrl->hw.ops.get_interrupt_status(
			u32 status = dsi_hw_ops.get_interrupt_status(
								&dsi_ctrl->hw);
			u32 mask = DSI_CMD_MODE_DMA_DONE;

			if (status & mask) {
				status |= (DSI_CMD_MODE_DMA_DONE |
						DSI_BTA_DONE);
				dsi_ctrl->hw.ops.clear_interrupt_status(
				dsi_hw_ops.clear_interrupt_status(
								&dsi_ctrl->hw,
								status);
				dsi_ctrl_disable_status_interrupt(dsi_ctrl,
@@ -1102,10 +1190,20 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
			}
		}

		if (dsi_ctrl->hw.ops.mask_error_intr)
			dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
		if (dsi_hw_ops.mask_error_intr)
			dsi_hw_ops.mask_error_intr(&dsi_ctrl->hw,
					BIT(DSI_FIFO_OVERFLOW), false);
		dsi_ctrl->hw.ops.reset_cmd_fifo(&dsi_ctrl->hw);
		dsi_hw_ops.reset_cmd_fifo(&dsi_ctrl->hw);

		/*
		 * DSI 2.2 needs a soft reset whenever we send non-embedded
		 * mode command followed by embedded mode. Otherwise it will
		 * result in smmu write faults with DSI as client.
		 */
		if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
			dsi_hw_ops.soft_reset(&dsi_ctrl->hw);
			dsi_ctrl->cmd_len = 0;
		}
	}
error:
	if (buffer)
@@ -2682,6 +2780,11 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags)
		if (dsi_ctrl->hw.ops.mask_error_intr)
			dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
					BIT(DSI_FIFO_OVERFLOW), false);

		if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
			dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw);
			dsi_ctrl->cmd_len = 0;
		}
	}

	mutex_unlock(&dsi_ctrl->ctrl_lock);
+23 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
 *				   and transfer it.
 * @DSI_CTRL_CMD_LAST_COMMAND:     Trigger the DMA cmd transfer if this is last
 *				   command in the batch.
 * @DSI_CTRL_CMD_NON_EMBEDDED_MODE:Transfer cmd packets in non embedded mode.
 */
#define DSI_CTRL_CMD_READ             0x1
#define DSI_CTRL_CMD_BROADCAST        0x2
@@ -45,6 +46,12 @@
#define DSI_CTRL_CMD_FIFO_STORE       0x10
#define DSI_CTRL_CMD_FETCH_MEMORY     0x20
#define DSI_CTRL_CMD_LAST_COMMAND     0x40
#define DSI_CTRL_CMD_NON_EMBEDDED_MODE 0x80

/* DSI embedded mode fifo size
 * If the command is greater than 256 bytes it is sent in non-embedded mode.
 */
#define DSI_EMBEDDED_MODE_DMA_MAX_SIZE_BYTES 256

/* max size supported for dsi cmd transfer using TPG */
#define DSI_CTRL_MAX_CMD_FIFO_STORE_SIZE 64
@@ -680,4 +687,20 @@ int dsi_ctrl_get_hw_version(struct dsi_ctrl *dsi_ctrl);
 */
int dsi_ctrl_vid_engine_en(struct dsi_ctrl *dsi_ctrl, bool on);

/**
 * @dsi_ctrl:        DSI controller handle.
 * cmd_len:	     Length of command.
 * flags:	     Config mode flags.
 */
void dsi_message_setup_tx_mode(struct dsi_ctrl *dsi_ctrl, u32 cmd_len,
		u32 *flags);

/**
 * @dsi_ctrl:        DSI controller handle.
 * cmd_len:	     Length of command.
 * flags:	     Config mode flags.
 */
int dsi_message_validate_tx_mode(struct dsi_ctrl *dsi_ctrl, u32 cmd_len,
		u32 *flags);

#endif /* _DSI_CTRL_H_ */
Loading