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

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

Merge changes I58ab04da,I129f5c56 into msm-next

* changes:
  drm/msm: create ESD worker thread to check panel status
  drm/msm/dsi-staging: add support for checking panel status
parents 68ddeb8e 222e8d90
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -60,6 +60,8 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
	ctrl->ops.setup_misr = dsi_ctrl_hw_cmn_setup_misr;
	ctrl->ops.collect_misr = dsi_ctrl_hw_cmn_collect_misr;
	ctrl->ops.debug_bus = dsi_ctrl_hw_cmn_debug_bus;
	ctrl->ops.get_cmd_read_data = dsi_ctrl_hw_cmn_get_cmd_read_data;
	ctrl->ops.clear_rdbk_register = dsi_ctrl_hw_cmn_clear_rdbk_reg;

	switch (version) {
	case DSI_CTRL_VERSION_1_4:
+6 −0
Original line number Diff line number Diff line
@@ -170,6 +170,12 @@ void dsi_ctrl_hw_cmn_phy_reset_config(struct dsi_ctrl_hw *ctrl,
			bool enable);
void dsi_ctrl_hw_22_phy_reset_config(struct dsi_ctrl_hw *ctrl,
			bool enable);
u32 dsi_ctrl_hw_cmn_get_cmd_read_data(struct dsi_ctrl_hw *ctrl,
				     u8 *rd_buf,
				     u32 read_offset,
				     u32 rx_byte,
				     u32 pkt_size, u32 *hw_read_cnt);
void dsi_ctrl_hw_cmn_clear_rdbk_reg(struct dsi_ctrl_hw *ctrl);

/* Definitions specific to 1.4 DSI controller hardware */
int dsi_ctrl_hw_14_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes);
+126 −11
Original line number Diff line number Diff line
@@ -886,6 +886,11 @@ static int dsi_ctrl_copy_and_pad_cmd(struct dsi_ctrl *dsi_ctrl,
		buf[3] |= BIT(6);

	buf[3] |= BIT(7);

	/* send embedded BTA for read commands */
	if ((buf[2] & 0x3f) == MIPI_DSI_DCS_READ)
		buf[3] |= BIT(5);

	*buffer = buf;
	*size = len;

@@ -1061,6 +1066,7 @@ static int dsi_set_max_return_size(struct dsi_ctrl *dsi_ctrl,
{
	int rc = 0;
	u8 tx[2] = { (u8)(size & 0xFF), (u8)(size >> 8) };
	u32 flags = DSI_CTRL_CMD_FETCH_MEMORY;
	struct mipi_dsi_msg msg = {
		.channel = rx_msg->channel,
		.type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
@@ -1068,24 +1074,77 @@ static int dsi_set_max_return_size(struct dsi_ctrl *dsi_ctrl,
		.tx_buf = tx,
	};

	rc = dsi_message_tx(dsi_ctrl, &msg, 0x0);
	rc = dsi_message_tx(dsi_ctrl, &msg, flags);
	if (rc)
		pr_err("failed to send max return size packet, rc=%d\n", rc);

	return rc;
}

/* Helper functions to support DCS read operation */
static int dsi_parse_short_read1_resp(const struct mipi_dsi_msg *msg,
		unsigned char *buff)
{
	u8 *data = msg->rx_buf;
	int read_len = 1;

	if (!data)
		return 0;

	/* remove dcs type */
	if (msg->rx_len >= 1)
		data[0] = buff[1];
	else
		read_len = 0;

	return read_len;
}

static int dsi_parse_short_read2_resp(const struct mipi_dsi_msg *msg,
		unsigned char *buff)
{
	u8 *data = msg->rx_buf;
	int read_len = 2;

	if (!data)
		return 0;

	/* remove dcs type */
	if (msg->rx_len >= 2) {
		data[0] = buff[1];
		data[1] = buff[2];
	} else {
		read_len = 0;
	}

	return read_len;
}

static int dsi_parse_long_read_resp(const struct mipi_dsi_msg *msg,
		unsigned char *buff)
{
	if (!msg->rx_buf)
		return 0;

	/* remove dcs type */
	if (msg->rx_buf && msg->rx_len)
		memcpy(msg->rx_buf, buff + 4, msg->rx_len);

	return msg->rx_len;
}

static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl,
			  const struct mipi_dsi_msg *msg,
			  u32 flags)
{
	int rc = 0;
	u32 rd_pkt_size;
	u32 total_read_len;
	u32 bytes_read = 0, tot_bytes_read = 0;
	u32 current_read_len;
	u32 rd_pkt_size, total_read_len, hw_read_cnt;
	u32 current_read_len = 0, total_bytes_read = 0;
	bool short_resp = false;
	bool read_done = false;
	u32 dlen, diff, rlen = msg->rx_len;
	unsigned char *buff;
	char cmd;

	if (msg->rx_len <= 2) {
		short_resp = true;
@@ -1101,6 +1160,7 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl,

		total_read_len = current_read_len + 6;
	}
	buff = msg->rx_buf;

	while (!read_done) {
		rc = dsi_set_max_return_size(dsi_ctrl, msg, rd_pkt_size);
@@ -1110,24 +1170,79 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl,
			goto error;
		}

		/* clear RDBK_DATA registers before proceeding */
		dsi_ctrl->hw.ops.clear_rdbk_register(&dsi_ctrl->hw);

		rc = dsi_message_tx(dsi_ctrl, msg, flags);
		if (rc) {
			pr_err("Message transmission failed, rc=%d\n", rc);
			goto error;
		}

		dlen = dsi_ctrl->hw.ops.get_cmd_read_data(&dsi_ctrl->hw,
					buff, total_bytes_read,
					total_read_len, rd_pkt_size,
					&hw_read_cnt);
		if (!dlen)
			goto error;

		tot_bytes_read += bytes_read;
		if (short_resp)
			break;

		if (rlen <= current_read_len) {
			diff = current_read_len - rlen;
			read_done = true;
		else if (msg->rx_len <= tot_bytes_read)
			read_done = true;
		} else {
			diff = 0;
			rlen -= current_read_len;
		}

		dlen -= 2; /* 2 bytes of CRC */
		dlen -= diff;
		buff += dlen;
		total_bytes_read += dlen;
		if (!read_done) {
			current_read_len = 14; /* Not first read */
			if (rlen < current_read_len)
				rd_pkt_size += rlen;
			else
				rd_pkt_size += current_read_len;
		}
	}

	if (hw_read_cnt < 16 && !short_resp)
		buff = msg->rx_buf + (16 - hw_read_cnt);
	else
		buff = msg->rx_buf;

	/* parse the data read from panel */
	cmd = buff[0];
	switch (cmd) {
	case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
		pr_err("Rx ACK_ERROR\n");
		rc = 0;
		break;
	case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
		rc = dsi_parse_short_read1_resp(msg, buff);
		break;
	case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
		rc = dsi_parse_short_read2_resp(msg, buff);
		break;
	case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
	case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
		rc = dsi_parse_long_read_resp(msg, buff);
		break;
	default:
		pr_warn("Invalid response\n");
		rc = 0;
	}

error:
	return rc;
}


static int dsi_enable_ulps(struct dsi_ctrl *dsi_ctrl)
{
	int rc = 0;
@@ -2335,8 +2450,8 @@ int dsi_ctrl_cmd_transfer(struct dsi_ctrl *dsi_ctrl,

	if (flags & DSI_CTRL_CMD_READ) {
		rc = dsi_message_rx(dsi_ctrl, msg, flags);
		if (rc)
			pr_err("read message failed, rc=%d\n", rc);
		if (rc <= 0)
			pr_err("read message failed read length, rc=%d\n", rc);
	} else {
		rc = dsi_message_tx(dsi_ctrl, msg, flags);
		if (rc)
+13 −2
Original line number Diff line number Diff line
@@ -520,11 +520,17 @@ struct dsi_ctrl_hw_ops {
	 * get_cmd_read_data() - get data read from the peripheral
	 * @ctrl:           Pointer to the controller host hardware.
	 * @rd_buf:         Buffer where data will be read into.
	 * @total_read_len: Number of bytes to read.
	 * @read_offset:    Offset from where to read.
	 * @rx_byte:        Number of bytes to be read.
	 * @pkt_size:        Size of response expected.
	 * @hw_read_cnt:    Actual number of bytes read by HW.
	 */
	u32 (*get_cmd_read_data)(struct dsi_ctrl_hw *ctrl,
				 u8 *rd_buf,
				 u32 total_read_len);
				 u32 read_offset,
				 u32 rx_byte,
				 u32 pkt_size,
				 u32 *hw_read_cnt);

	/**
	 * wait_for_lane_idle() - wait for DSI lanes to go to idle state
@@ -710,6 +716,11 @@ struct dsi_ctrl_hw_ops {
	 */
	void (*set_timing_db)(struct dsi_ctrl_hw *ctrl,
				 bool enable);
	/**
	 * clear_rdbk_register() - Clear and reset read back register
	 * @ctrl:         Pointer to the controller host hardware.
	 */
	void (*clear_rdbk_register)(struct dsi_ctrl_hw *ctrl);
};

/*
+57 −19
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/iopoll.h>

#include "dsi_catalog.h"
#include "dsi_ctrl_hw.h"
#include "dsi_ctrl_reg.h"
#include "dsi_hw.h"
@@ -708,6 +709,22 @@ void dsi_ctrl_hw_cmn_trigger_command_dma(struct dsi_ctrl_hw *ctrl)
	pr_debug("[DSI_%d] CMD DMA triggered\n", ctrl->index);
}

/**
 * clear_rdbk_reg() - clear previously read panel data.
 * @ctrl:          Pointer to the controller host hardware.
 *
 * This function is called before sending DSI Rx command to
 * panel in order to clear if any stale data remaining from
 * previous read operation.
 */
void dsi_ctrl_hw_cmn_clear_rdbk_reg(struct dsi_ctrl_hw *ctrl)
{
	DSI_W32(ctrl, DSI_RDBK_DATA_CTRL, 0x1);
	wmb(); /* ensure read back register is reset */
	DSI_W32(ctrl, DSI_RDBK_DATA_CTRL, 0x0);
	wmb(); /* ensure read back register is cleared */
}

/**
 * get_cmd_read_data() - get data read from the peripheral
 * @ctrl:           Pointer to the controller host hardware.
@@ -719,16 +736,16 @@ void dsi_ctrl_hw_cmn_trigger_command_dma(struct dsi_ctrl_hw *ctrl)
u32 dsi_ctrl_hw_cmn_get_cmd_read_data(struct dsi_ctrl_hw *ctrl,
				     u8 *rd_buf,
				     u32 read_offset,
				     u32 total_read_len)
				     u32 rx_byte,
				     u32 pkt_size,
				     u32 *hw_read_cnt)
{
	u32 *lp, *temp, data;
	int i, j = 0, cnt;
	int i, j = 0, cnt, off;
	u32 read_cnt;
	u32 rx_byte = 0;
	u32 repeated_bytes = 0;
	u8 reg[16] = {0};
	u32 pkt_size = 0;
	int buf_offset = read_offset;
	bool ack_err = false;

	lp = (u32 *)rd_buf;
	temp = (u32 *)reg;
@@ -737,28 +754,49 @@ u32 dsi_ctrl_hw_cmn_get_cmd_read_data(struct dsi_ctrl_hw *ctrl,
	if (cnt > 4)
		cnt = 4;

	if (rx_byte == 4)
		read_cnt = 4;
	else
		read_cnt = pkt_size + 6;
	read_cnt = (DSI_R32(ctrl, DSI_RDBK_DATA_CTRL) >> 16);
	ack_err = (rx_byte == 4) ? (read_cnt == 8) :
			((read_cnt - 4) == (pkt_size + 6));

	if (ack_err)
		read_cnt -= 4;
	if (!read_cnt) {
		pr_err("Panel detected error, no data read\n");
		return 0;
	}

	if (read_cnt > 16) {
		int bytes_shifted;
		int bytes_shifted, data_lost = 0, rem_header = 0;

		bytes_shifted = read_cnt - rx_byte;
		if (bytes_shifted >= 4)
			data_lost = bytes_shifted - 4; /* remove DCS header */
		else
			rem_header = 4 - bytes_shifted; /* remaining header */

		bytes_shifted = read_cnt - 16;
		repeated_bytes = buf_offset - bytes_shifted;
		repeated_bytes = (read_offset - 4) - data_lost + rem_header;
	}

	for (i = cnt - 1; i >= 0; i--) {
		data = DSI_R32(ctrl, DSI_RDBK_DATA0 + i*4);
	off = DSI_RDBK_DATA0;
	off += ((cnt - 1) * 4);

	for (i = 0; i < cnt; i++) {
		data = DSI_R32(ctrl, off);
		if (!repeated_bytes)
			*lp++ = ntohl(data);
		else
			*temp++ = ntohl(data);
		off -= 4;
	}

	if (repeated_bytes) {
		for (i = repeated_bytes; i < 16; i++)
			rd_buf[j++] = reg[i];
	}

	pr_debug("[DSI_%d] Read %d bytes\n", ctrl->index, j);
	return j;
	*hw_read_cnt = read_cnt;
	pr_debug("[DSI_%d] Read %d bytes\n", ctrl->index, rx_byte);
	return rx_byte;
}

/**
Loading