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

Commit bbe18a16 authored by Satya Rama Aditya Pinapala's avatar Satya Rama Aditya Pinapala
Browse files

disp: msm: dsi: batching multiple DSI commands using debugfs node



The change batches DSI commands sent using the debugfs node, in a
separate buffer from the TX command buffer to ensure that they are not
triggered before the last command bit is set. Once the last command
bit is set the buffer is then copied to the DSI TX buffer and triggered.

Change-Id: I9ba624e4e19341696a974994817603315c6c8a45
Signed-off-by: default avatarSatya Rama Aditya Pinapala <psraditya30@codeaurora.org>
parent 36685664
Loading
Loading
Loading
Loading
+23 −3
Original line number Diff line number Diff line
@@ -1352,7 +1352,8 @@ static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl,
	hw_flags |= (flags & DSI_CTRL_CMD_DEFER_TRIGGER) ?
			DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER : 0;

	if ((msg->flags & MIPI_DSI_MSG_LASTCOMMAND))
	if ((msg->flags & MIPI_DSI_MSG_LASTCOMMAND) ||
			(flags & DSI_CTRL_CMD_LAST_COMMAND))
		hw_flags |= DSI_CTRL_CMD_LAST_COMMAND;

	if (flags & DSI_CTRL_CMD_DEFER_TRIGGER) {
@@ -1488,6 +1489,8 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,

	dsi_ctrl_validate_msg_flags(dsi_ctrl, msg, flags);

	SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_ENTRY, flags);

	if (dsi_ctrl->dma_wait_queued)
		dsi_ctrl_flush_cmd_dma_queue(dsi_ctrl);

@@ -1527,7 +1530,23 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
		goto error;
	}

	if ((msg->flags & MIPI_DSI_MSG_LASTCOMMAND))
	/*
	 * In case of broadcast CMD length cannot be greater than 512 bytes
	 * as specified by HW limitations. Need to overwrite the flags to
	 * set the LAST_COMMAND flag to ensure no command transfer failures.
	 */
	if ((*flags & DSI_CTRL_CMD_FETCH_MEMORY) &&
			(*flags & DSI_CTRL_CMD_BROADCAST)) {
		if ((dsi_ctrl->cmd_len + length) > 240) {
			dsi_ctrl_mask_overflow(dsi_ctrl, true);
			*flags |= DSI_CTRL_CMD_LAST_COMMAND;
			SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_CASE1,
					flags);
		}
	}

	if ((msg->flags & MIPI_DSI_MSG_LASTCOMMAND) ||
			(*flags & DSI_CTRL_CMD_LAST_COMMAND))
		buffer[3] |= BIT(7);//set the last cmd bit in header.

	if (*flags & DSI_CTRL_CMD_FETCH_MEMORY) {
@@ -1548,7 +1567,8 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,

		dsi_ctrl->cmd_len += length;

		if (!(msg->flags & MIPI_DSI_MSG_LASTCOMMAND)) {
		if (!(msg->flags & MIPI_DSI_MSG_LASTCOMMAND) &&
				!(*flags & DSI_CTRL_CMD_LAST_COMMAND)) {
			goto error;
		} else {
			cmd_mem.length = dsi_ctrl->cmd_len;
+59 −12
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@

#define SEC_PANEL_NAME_MAX_LEN  256

u8 dbgfs_tx_cmd_buf[SZ_4K];
static char dsi_display_primary[MAX_CMDLINE_PARAM_LEN];
static char dsi_display_secondary[MAX_CMDLINE_PARAM_LEN];
static struct dsi_display_boot_param boot_displays[MAX_DSI_ACTIVE_DISPLAY] = {
@@ -1014,10 +1015,9 @@ int dsi_display_cmd_transfer(struct drm_connector *connector,
		u32 cmd_buf_len)
{
	struct dsi_display *dsi_display = display;
	struct dsi_cmd_desc cmd;
	u8 cmd_payload[MAX_CMD_PAYLOAD_SIZE];
	int rc = 0;
	bool state = false;
	int rc = 0, cnt = 0, i = 0;
	bool state = false, transfer = false;
	struct dsi_panel_cmd_set *set;

	if (!dsi_display || !cmd_buf) {
		DSI_ERR("[DSI] invalid params\n");
@@ -1026,12 +1026,8 @@ int dsi_display_cmd_transfer(struct drm_connector *connector,

	DSI_DEBUG("[DSI] Display command transfer\n");

	rc = dsi_display_cmd_prepare(cmd_buf, cmd_buf_len,
			&cmd, cmd_payload, MAX_CMD_PAYLOAD_SIZE);
	if (rc) {
		DSI_ERR("[DSI] command prepare failed. rc %d\n", rc);
		return rc;
	}
	if ((cmd_buf[1]) || (cmd_buf[3] & MIPI_DSI_MSG_LASTCOMMAND))
		transfer = true;

	mutex_lock(&dsi_display->display_lock);
	rc = dsi_display_ctrl_get_host_init_state(dsi_display, &state);
@@ -1053,8 +1049,59 @@ int dsi_display_cmd_transfer(struct drm_connector *connector,
		goto end;
	}

	/*
	 * Reset the dbgfs buffer if the commands sent exceed the available
	 * buffer size. For video mode, limiting the buffer size to 2K to
	 * ensure no performance issues.
	 */
	if (dsi_display->panel->panel_mode == DSI_OP_CMD_MODE) {
		if ((dsi_display->tx_cmd_buf_ndx + cmd_buf_len) > SZ_4K) {
			memset(dbgfs_tx_cmd_buf, 0, SZ_4K);
			dsi_display->tx_cmd_buf_ndx = 0;
		}
	} else {
		if ((dsi_display->tx_cmd_buf_ndx + cmd_buf_len) > SZ_2K) {
			memset(dbgfs_tx_cmd_buf, 0, SZ_4K);
			dsi_display->tx_cmd_buf_ndx = 0;
		}
	}

	memcpy(&dbgfs_tx_cmd_buf[dsi_display->tx_cmd_buf_ndx], cmd_buf,
			cmd_buf_len);
	dsi_display->tx_cmd_buf_ndx += cmd_buf_len;
	if (transfer) {
		struct dsi_cmd_desc *cmds;

		set = &dsi_display->cmd_set;
		set->count = 0;
		dsi_panel_get_cmd_pkt_count(dbgfs_tx_cmd_buf,
				dsi_display->tx_cmd_buf_ndx, &cnt);
		dsi_panel_alloc_cmd_packets(set, cnt);
		dsi_panel_create_cmd_packets(dbgfs_tx_cmd_buf,
				dsi_display->tx_cmd_buf_ndx, cnt, set->cmds);
		cmds = set->cmds;
		dsi_display->tx_cmd_buf_ndx = 0;

		for (i = 0; i < cnt; i++) {
			if (cmds->last_command)
				cmds->msg.flags |= MIPI_DSI_MSG_LASTCOMMAND;
			rc = dsi_display->host.ops->transfer(&dsi_display->host,
			&cmd.msg);
					&cmds->msg);
			if (rc < 0) {
				DSI_ERR("failed to send command, rc=%d\n", rc);
				goto end;
			}
			if (cmds->post_wait_ms)
				usleep_range(cmds->post_wait_ms*1000,
						((cmds->post_wait_ms*1000)+10));
			cmds++;
		}

		memset(dbgfs_tx_cmd_buf, 0, SZ_4K);
		dsi_panel_destroy_cmd_packets(set);
		dsi_panel_dealloc_cmd_packets(set);
	}

end:
	mutex_unlock(&dsi_display->display_lock);
	return rc;
+5 −0
Original line number Diff line number Diff line
@@ -192,6 +192,8 @@ struct dsi_display_ext_bridge {
 * @is_active:        status of the display
 * @trusted_vm_env:   Set to true, it the executing VM is Trusted VM.
 *                    Set to false, otherwise.
 * @tx_cmd_buf_ndx:   Index to the DSI debugfs TX CMD buffer.
 * @cmd_set:	      Debugfs TX cmd set.
 */
struct dsi_display {
	struct platform_device *pdev;
@@ -287,6 +289,9 @@ struct dsi_display {
	bool is_active;

	bool trusted_vm_env;

	int tx_cmd_buf_ndx;
	struct dsi_panel_cmd_set cmd_set;
};

int dsi_display_dev_probe(struct platform_device *pdev);
+5 −5
Original line number Diff line number Diff line
@@ -1730,7 +1730,7 @@ const char *cmd_set_state_map[DSI_CMD_SET_MAX] = {
	"qcom,mdss-dsi-qsync-off-commands-state",
};

static int dsi_panel_get_cmd_pkt_count(const char *data, u32 length, u32 *cnt)
int dsi_panel_get_cmd_pkt_count(const char *data, u32 length, u32 *cnt)
{
	const u32 cmd_set_min_size = 7;
	u32 count = 0;
@@ -1754,7 +1754,7 @@ static int dsi_panel_get_cmd_pkt_count(const char *data, u32 length, u32 *cnt)
	return 0;
}

static int dsi_panel_create_cmd_packets(const char *data,
int dsi_panel_create_cmd_packets(const char *data,
					u32 length,
					u32 count,
					struct dsi_cmd_desc *cmd)
@@ -1799,7 +1799,7 @@ static int dsi_panel_create_cmd_packets(const char *data,
	return rc;
}

static void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set)
void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set)
{
	u32 i = 0;
	struct dsi_cmd_desc *cmd;
@@ -1810,12 +1810,12 @@ static void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set)
	}
}

static void dsi_panel_dealloc_cmd_packets(struct dsi_panel_cmd_set *set)
void dsi_panel_dealloc_cmd_packets(struct dsi_panel_cmd_set *set)
{
	kfree(set->cmds);
}

static int dsi_panel_alloc_cmd_packets(struct dsi_panel_cmd_set *cmd,
int dsi_panel_alloc_cmd_packets(struct dsi_panel_cmd_set *cmd,
					u32 packet_count)
{
	u32 size;
+11 −0
Original line number Diff line number Diff line
@@ -378,4 +378,15 @@ int dsi_panel_get_io_resources(struct dsi_panel *panel,
void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config,
		struct dsi_display_mode *mode, u32 frame_threshold_us);

int dsi_panel_get_cmd_pkt_count(const char *data, u32 length, u32 *cnt);

int dsi_panel_alloc_cmd_packets(struct dsi_panel_cmd_set *cmd,
		u32 packet_count);

int dsi_panel_create_cmd_packets(const char *data, u32 length, u32 count,
					struct dsi_cmd_desc *cmd);

void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set);

void dsi_panel_dealloc_cmd_packets(struct dsi_panel_cmd_set *set);
#endif /* _DSI_PANEL_H_ */