summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorPadmanabhan Komanduru <pkomandu@codeaurora.org>2014-09-05 21:54:30 +0530
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:33:50 -0700
commitf3263cd2d5c423fdddb9dfe9adf68343c29450ef (patch)
treec80a304db356ca1702f9cb02e80ad6be7d608e80 /drivers
parent72454981c60a53efd2ec2272d28ba5afcc674479 (diff)
msm: mdss: handle DSI command rx for less than 8 bytes requested
Currently, for long read response commands with rlen less than 8, there are padding bytes being expected to be sent by the panel. However, there might be some panels which do not support extra padding bytes. Due to this, the read response might not be stored in the first byte of the rx buffer. The RDBK_DATA_CTRL register is available from DSI6G v1.1.0 and above. Make use of this register to check the number of bytes returned by the panel. Based on this, calculate the offset of the first valid byte of the response in the rx buffer. For targets which do not have this register, calculate the offset based on the software state of the read length variable. Change-Id: I94d3f6d7a453f925bdfd967cdb23cf6aab1ac3a8 Signed-off-by: Padmanabhan Komanduru <pkomandu@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_cmd.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_cmd.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_host.c69
3 files changed, 69 insertions, 7 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi_cmd.c b/drivers/video/fbdev/msm/mdss_dsi_cmd.c
index 9d94fc548265..c5d4a11e647b 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_cmd.c
@@ -66,6 +66,7 @@ char *mdss_dsi_buf_init(struct dsi_buf *dp)
off = 8 - off;
dp->data += off;
dp->len = 0;
+ dp->read_cnt = 0;
return dp->data;
}
@@ -85,6 +86,7 @@ int mdss_dsi_buf_alloc(struct device *ctrl_dev, struct dsi_buf *dp, int size)
dp->data = dp->start;
dp->len = 0;
+ dp->read_cnt = 0;
return size;
}
@@ -573,6 +575,8 @@ int mdss_dsi_short_read1_resp(struct dsi_buf *rp)
/* strip out dcs type */
rp->data++;
rp->len = 1;
+ /* 1 byte for dcs type + 1 byte for ECC + 1 byte for 2nd data byte */
+ rp->read_cnt -= 3;
return rp->len;
}
@@ -584,6 +588,7 @@ int mdss_dsi_short_read2_resp(struct dsi_buf *rp)
/* strip out dcs type */
rp->data++;
rp->len = 2;
+ rp->read_cnt -= 2; /* 1 byte for dcs type + 1 byte for ECC */
return rp->len;
}
@@ -592,6 +597,7 @@ int mdss_dsi_long_read_resp(struct dsi_buf *rp)
/* strip out dcs header */
rp->data += 4;
rp->len -= 4;
+ rp->read_cnt -= 6; /* 4 bytes for dcs header + 2 bytes for CRC */
return rp->len;
}
diff --git a/drivers/video/fbdev/msm/mdss_dsi_cmd.h b/drivers/video/fbdev/msm/mdss_dsi_cmd.h
index 96bf55271f17..119ce349100e 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_cmd.h
+++ b/drivers/video/fbdev/msm/mdss_dsi_cmd.h
@@ -39,6 +39,7 @@ struct dsi_buf {
int size; /* size of buffer */
char *data; /* buffer */
int len; /* data length */
+ int read_cnt; /* DSI read count */
dma_addr_t dmap; /* mapped dma addr */
};
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index 225ace633641..1655d134acbc 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -1060,6 +1060,7 @@ do_send:
pr_err("%s: failed to add max_pkt_size\n",
__func__);
rp->len = 0;
+ rp->read_cnt = 0;
goto end;
}
@@ -1072,6 +1073,7 @@ do_send:
pr_err("%s: failed to tx max_pkt_size\n",
__func__);
rp->len = 0;
+ rp->read_cnt = 0;
goto end;
}
pr_debug("%s: max_pkt_size=%d sent\n",
@@ -1083,6 +1085,7 @@ do_send:
pr_err("%s: failed to add cmd = 0x%x\n",
__func__, cmds->payload[0]);
rp->len = 0;
+ rp->read_cnt = 0;
goto end;
}
@@ -1095,8 +1098,10 @@ do_send:
pr_err("%s: failed to tx cmd = 0x%x\n",
__func__, cmds->payload[0]);
rp->len = 0;
+ rp->read_cnt = 0;
goto end;
}
+
/*
* once cmd_dma_done interrupt received,
* return data from client is ready and stored
@@ -1106,6 +1111,9 @@ do_send:
*/
dlen = mdss_dsi_cmd_dma_rx(ctrl, rp, rx_byte);
+ if (!dlen)
+ goto end;
+
if (short_response)
break;
@@ -1122,19 +1130,31 @@ do_send:
dlen -= diff;
rp->data += dlen; /* next start position */
rp->len += dlen;
- data_byte = 12; /* NOT first read */
- pkt_size += data_byte;
+ if (!end) {
+ data_byte = 12; /* NOT first read */
+ pkt_size += data_byte;
+ }
pr_debug("%s: rp data=%x len=%d dlen=%d diff=%d\n",
__func__, (int) (unsigned long) rp->data,
rp->len, dlen, diff);
}
- rp->data = rp->start; /* move back to start position */
+ /*
+ * For single Long read, if the requested rlen < 10,
+ * we need to shift the start position of rx
+ * data buffer to skip the bytes which are not
+ * updated.
+ */
+ if (rp->read_cnt < 16 && !short_response)
+ rp->data = rp->start + (16 - rp->read_cnt);
+ else
+ rp->data = rp->start;
cmd = rp->data[0];
switch (cmd) {
case DTYPE_ACK_ERR_RESP:
pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
rp->len = 0;
+ rp->read_cnt = 0;
case DTYPE_GEN_READ1_RESP:
case DTYPE_DCS_READ1_RESP:
mdss_dsi_short_read1_resp(rp);
@@ -1150,6 +1170,7 @@ do_send:
default:
pr_warning("%s:Invalid response cmd\n", __func__);
rp->len = 0;
+ rp->read_cnt = 0;
}
end:
@@ -1163,7 +1184,11 @@ end:
ctrl->cmd_cfg_restore = false;
}
- return rp->len;
+ if (rp->len && (rp->len != rp->read_cnt))
+ pr_err("Bytes read: %d requested:%d mismatch\n",
+ rp->read_cnt, rp->len);
+
+ return rp->read_cnt;
}
#define DMA_TX_TIMEOUT 200
@@ -1253,17 +1278,40 @@ static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
struct dsi_buf *rp, int rx_byte)
{
- u32 *lp, data;
- int i, off, cnt;
+ u32 *lp, data, ctrl_rev;
+ int i, off, cnt, ret = rx_byte;
+ bool ack_error = false;
lp = (u32 *)rp->data;
cnt = rx_byte;
cnt += 3;
cnt >>= 2;
+ ctrl_rev = MIPI_INP(ctrl->ctrl_base);
+
if (cnt > 4)
cnt = 4; /* 4 x 32 bits registers only */
+ if (ctrl_rev >= MDSS_DSI_HW_REV_101) {
+ rp->read_cnt = (MIPI_INP((ctrl->ctrl_base) + 0x01d4) >> 16);
+ pr_debug("%s: bytes read:%d\n", __func__, rp->read_cnt);
+
+ ack_error = (rx_byte == 4) ? (rp->read_cnt == 8) :
+ ((rp->read_cnt - 4) == (max_pktsize[0] + 6));
+
+ if (ack_error)
+ rp->read_cnt -= 4; /* 4 byte read err report */
+ if (!rp->read_cnt) {
+ pr_err("%s: Errors detected, no data rxed\n", __func__);
+ ret = 0;
+ goto exit;
+ }
+ } else if (rx_byte == 4) {
+ rp->read_cnt = 4;
+ } else {
+ rp->read_cnt = (max_pktsize[0] + 6);
+ }
+
off = 0x06c; /* DSI_RDBK_DATA0 */
off += ((cnt - 1) * 4);
@@ -1275,7 +1323,14 @@ static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
off -= 4;
}
- return rx_byte;
+exit:
+ if (ctrl_rev >= MDSS_DSI_HW_REV_101) {
+ /* clear the RDBK_DATA registers */
+ MIPI_OUTP(ctrl->ctrl_base + 0x01d4, 0x1);
+ MIPI_OUTP(ctrl->ctrl_base + 0x01d4, 0x0);
+ }
+
+ return ret;
}
void mdss_dsi_en_wait4dynamic_done(struct mdss_dsi_ctrl_pdata *ctrl)