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

Commit dbeab897 authored by Vara Reddy's avatar Vara Reddy Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm/dsi-staging: add support for non-embedded cmd transfer



Enable non-embedded mode hardware feature to transfer commands of size
greater than present DMA fifo size of 256 bytes.

Change-Id: I9763d364b6997e9efb5610d89b350f72966ea1cd
Signed-off-by: default avatarVara Reddy <varar@codeaurora.org>
parent b3227c4f
Loading
Loading
Loading
Loading
+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);
+123 −20
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)
@@ -955,27 +1011,39 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
	u8 *cmdbuf;
	struct dsi_mode_info *timing;

	/* 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 +1061,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;
@@ -1026,6 +1095,7 @@ 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 +
@@ -1045,9 +1115,18 @@ 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_ctrl->hw.ops.
					kickoff_command_non_embedded_mode(
							&dsi_ctrl->hw,
							&cmd_mem,
							hw_flags);
			} else {
				dsi_ctrl->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,
							      &cmd,
@@ -1065,9 +1144,18 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
		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_ctrl->hw.ops.
					kickoff_command_non_embedded_mode(
							&dsi_ctrl->hw,
							&cmd_mem,
							hw_flags);
			} else {
				dsi_ctrl->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,
							      &cmd,
@@ -1106,6 +1194,16 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
			dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
					BIT(DSI_FIFO_OVERFLOW), false);
		dsi_ctrl->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_ctrl->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:Trasfer 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_ */
+21 −0
Original line number Diff line number Diff line
@@ -296,6 +296,7 @@ enum dsi_error_int_type {
 * struct dsi_ctrl_cmd_dma_info - command buffer information
 * @offset:        IOMMU VA for command buffer address.
 * @length:        Length of the command buffer.
 * @datatype:      Datatype of cmd.
 * @en_broadcast:  Enable broadcast mode if set to true.
 * @is_master:     Is master in broadcast mode.
 * @use_lpm:       Use low power mode for command transmission.
@@ -303,6 +304,7 @@ enum dsi_error_int_type {
struct dsi_ctrl_cmd_dma_info {
	u32 offset;
	u32 length;
	u8  datatype;
	bool en_broadcast;
	bool is_master;
	bool use_lpm;
@@ -496,6 +498,25 @@ struct dsi_ctrl_hw_ops {
				struct dsi_ctrl_cmd_dma_info *cmd,
				u32 flags);

	/**
	 * kickoff_command_non_embedded_mode() - cmd in non embedded mode
	 * @ctrl:          Pointer to the controller host hardware.
	 * @cmd:           Command information.
	 * @flags:         Modifiers for command transmission.
	 *
	 * If command length is greater than DMA FIFO size of 256 bytes we use
	 * this non- embedded mode.
	 * The controller hardware is programmed with address and size of the
	 * command buffer. The transmission is kicked off if
	 * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag is not set. If this flag is
	 * set, caller should make a separate call to trigger_command_dma() to
	 * transmit the command.
	 */

	void (*kickoff_command_non_embedded_mode)(struct dsi_ctrl_hw *ctrl,
				struct dsi_ctrl_cmd_dma_info *cmd,
				u32 flags);

	/**
	 * kickoff_fifo_command() - transmits a command using FIFO in dsi
	 *                          hardware.
Loading