Skip to content

Instantly share code, notes, and snippets.

@invisiblek
Created March 28, 2015 15:40
Show Gist options
  • Select an option

  • Save invisiblek/faa4a59f7fc6772bc19d to your computer and use it in GitHub Desktop.

Select an option

Save invisiblek/faa4a59f7fc6772bc19d to your computer and use it in GitHub Desktop.
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index f6d97f7..68c991c 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -26,6 +26,7 @@
#include "dsi_io_v2.h"
#include "dsi_host_v2.h"
#include "mdss_debug.h"
+#include "mdp3.h"
#define DSI_POLL_SLEEP_US 1000
#define DSI_POLL_TIMEOUT_US 16000
@@ -652,14 +653,25 @@ int msm_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
return rc;
}
+/* MIPI_DSI_MRPS, Maximum Return Packet Size */
+static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
+
+static struct dsi_cmd_desc pkt_size_cmd = {
+ {DTYPE_MAX_PKTSIZE, 1, 0, 0, 0, sizeof(max_pktsize)},
+ max_pktsize,
+};
+
int msm_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
struct dsi_buf *rp, int rlen)
{
- u32 *lp, data;
- int i, off, cnt;
+ u32 *lp, data, *temp;
+ int i, j = 0, off, cnt;
unsigned char *ctrl_base = dsi_host_private->dsi_base;
+ char reg[16];
+ int repeated_bytes = 0;
lp = (u32 *)rp->data;
+ temp = (u32 *)reg;
cnt = rlen;
cnt += 3;
cnt >>= 2;
@@ -667,16 +679,52 @@ int msm_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
if (cnt > 4)
cnt = 4; /* 4 x 32 bits registers only */
+ if (rlen == 4)
+ rp->read_cnt = 4;
+ else
+ rp->read_cnt = (max_pktsize[0] + 6);
+
+ if (rp->read_cnt > 16) {
+ int bytes_shifted, data_lost = 0, rem_header_bytes = 0;
+ /* Any data more than 16 bytes will be shifted out */
+ bytes_shifted = rp->read_cnt - rlen;
+ if (bytes_shifted >= 4)
+ data_lost = bytes_shifted - 4; /* remove dcs header */
+ else
+ rem_header_bytes = 4 - bytes_shifted; /* rem header */
+ /*
+ * (rp->len - 4) -> current rx buffer data length.
+ * If data_lost > 0, then ((rp->len - 4) - data_lost) will be
+ * the number of repeating bytes.
+ * If data_lost == 0, then ((rp->len - 4) + rem_header_bytes)
+ * will be the number of bytes repeating in between rx buffer
+ * and the current RDBK_DATA registers. We need to skip the
+ * repeating bytes.
+ */
+ repeated_bytes = (rp->len - 4) - data_lost + rem_header_bytes;
+ }
+
off = DSI_RDBK_DATA0;
off += ((cnt - 1) * 4);
for (i = 0; i < cnt; i++) {
data = (u32)MIPI_INP(ctrl_base + off);
- *lp++ = ntohl(data); /* to network byte order */
+ /* to network byte order */
+ if (!repeated_bytes)
+ *lp++ = ntohl(data);
+ else
+ *temp++ = ntohl(data);
pr_debug("%s: data = 0x%x and ntohl(data) = 0x%x\n",
__func__, data, ntohl(data));
off -= 4;
- rp->len += sizeof(*lp);
+ if (rlen == 4)
+ rp->len += sizeof(*lp);
+ }
+
+ /* Skip duplicates and append other data to the rx buffer */
+ if (repeated_bytes) {
+ for (i = repeated_bytes; i < 16; i++)
+ rp->data[j++] = reg[i];
}
return rlen;
@@ -768,14 +816,6 @@ static int msm_dsi_parse_rx_response(struct dsi_buf *rp)
return rc;
}
-/* MIPI_DSI_MRPS, Maximum Return Packet Size */
-static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
-
-static struct dsi_cmd_desc pkt_size_cmd = {
- {DTYPE_MAX_PKTSIZE, 1, 0, 0, 0, sizeof(max_pktsize)},
- max_pktsize,
-};
-
static int msm_dsi_set_max_packet_size(struct mdss_dsi_ctrl_pdata *ctrl,
int size)
{
@@ -813,10 +853,23 @@ static int msm_dsi_cmds_rx_1(struct mdss_dsi_ctrl_pdata *ctrl,
{
int rc;
struct dsi_buf *tp, *rp;
+ int rx_byte = 0;
+
+ if (rlen <= 2)
+ rx_byte = 4;
+ else
+ rx_byte = DSI_MAX_BYTES_TO_READ;
tp = &ctrl->tx_buf;
rp = &ctrl->rx_buf;
mdss_dsi_buf_init(rp);
+ rc = msm_dsi_set_max_packet_size(ctrl, rlen);
+ if (rc) {
+ pr_err("%s: dsi_set_max_pkt failed\n", __func__);
+ rc = -EINVAL;
+ goto dsi_cmds_rx_1_error;
+ }
+
mdss_dsi_buf_init(tp);
rc = mdss_dsi_cmd_dma_add(tp, cmds);
@@ -839,10 +892,12 @@ static int msm_dsi_cmds_rx_1(struct mdss_dsi_ctrl_pdata *ctrl,
}
if (rlen <= DSI_SHORT_PKT_DATA_SIZE) {
- msm_dsi_cmd_dma_rx(ctrl, rp, rlen);
+ msm_dsi_cmd_dma_rx(ctrl, rp, rx_byte);
} else {
- msm_dsi_cmd_dma_rx(ctrl, rp, rlen + DSI_HOST_HDR_SIZE);
- rp->len = rlen + DSI_HOST_HDR_SIZE;
+ msm_dsi_cmd_dma_rx(ctrl, rp, rx_byte);
+ rp->len = rx_byte - 2; /*2 bytes for CRC*/
+ rp->len = rp->len - (DSI_MAX_PKT_SIZE - rlen);
+ rp->data = rp->start + (16 - (rlen + 2 + DSI_HOST_HDR_SIZE));
}
rc = msm_dsi_parse_rx_response(rp);
@@ -859,16 +914,15 @@ static int msm_dsi_cmds_rx_2(struct mdss_dsi_ctrl_pdata *ctrl,
{
int rc;
struct dsi_buf *tp, *rp;
- int pkt_size, data_bytes, total;
+ int pkt_size, data_bytes, dlen, end = 0, diff;
tp = &ctrl->tx_buf;
rp = &ctrl->rx_buf;
mdss_dsi_buf_init(rp);
pkt_size = DSI_MAX_PKT_SIZE;
data_bytes = MDSS_DSI_LEN;
- total = 0;
- while (true) {
+ while (!end) {
rc = msm_dsi_set_max_packet_size(ctrl, pkt_size);
if (rc)
break;
@@ -879,7 +933,7 @@ static int msm_dsi_cmds_rx_2(struct mdss_dsi_ctrl_pdata *ctrl,
pr_err("%s: dsi_cmd_dma_add failed\n", __func__);
rc = -EINVAL;
break;
- }
+ }
rc = msm_dsi_wait4video_eng_busy(ctrl);
if (rc) {
pr_err("%s: wait4video_eng failed\n", __func__);
@@ -893,19 +947,32 @@ static int msm_dsi_cmds_rx_2(struct mdss_dsi_ctrl_pdata *ctrl,
}
msm_dsi_cmd_dma_rx(ctrl, rp, DSI_MAX_BYTES_TO_READ);
-
- rp->data += DSI_MAX_BYTES_TO_READ - DSI_HOST_HDR_SIZE;
- total += data_bytes;
- if (total >= rlen)
- break;
-
- data_bytes = DSI_MAX_BYTES_TO_READ - DSI_HOST_HDR_SIZE;
- pkt_size += data_bytes;
+ if (rlen <= data_bytes) {
+ diff = data_bytes - rlen;
+ end = 1;
+ } else {
+ diff = 0;
+ rlen -= data_bytes;
+ }
+ dlen = DSI_MAX_BYTES_TO_READ - 2;
+ dlen -= diff;
+ rp->data += dlen;
+ rp->len += dlen;
+
+ if (!end) {
+ data_bytes = 14;
+ if (rlen < data_bytes)
+ pkt_size += rlen;
+ else
+ pkt_size += data_bytes;
+ }
+ pr_debug("%s: rp data=%x len=%d dlen=%d diff=%d\n",
+ __func__, (int) (unsigned long) rp->data,
+ rp->len, dlen, diff);
}
if (!rc) {
rp->data = rp->start;
- rp->len = rlen + DSI_HOST_HDR_SIZE;
rc = msm_dsi_parse_rx_response(rp);
}
@@ -976,7 +1043,13 @@ int msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
mutex_unlock(&ctrl->cmd_mutex);
return ret;
}
-
+ /*
+ * mdss interrupt is generated in mdp core clock domain
+ * mdp clock need to be enabled to receive dsi interrupt
+ * also, axi bus bandwidth need since dsi controller will
+ * fetch dcs commands from axi bus
+ */
+ mdp3_res_update(1, 1, MDP3_CLIENT_DMA_P);
msm_dsi_clk_ctrl(&ctrl->panel_data, 1);
if (0 == (req->flags & CMD_REQ_LP_MODE))
@@ -991,6 +1064,7 @@ int msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
dsi_set_tx_power_mode(1);
msm_dsi_clk_ctrl(&ctrl->panel_data, 0);
+ mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P);
mutex_unlock(&ctrl->cmd_mutex);
return 0;
@@ -1255,7 +1329,83 @@ static int msm_dsi_cont_on(struct mdss_panel_data *pdata)
return 0;
}
-int msm_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+static int msm_dsi_read_status(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ struct dcs_cmd_req cmdreq;
+
+ memset(&cmdreq, 0, sizeof(cmdreq));
+ cmdreq.cmds = ctrl->status_cmds.cmds;
+ cmdreq.cmds_cnt = ctrl->status_cmds.cmd_cnt;
+ cmdreq.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL | CMD_REQ_RX;
+ cmdreq.rlen = 1;
+ cmdreq.cb = NULL;
+ cmdreq.rbuf = ctrl->status_buf.data;
+
+ return mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+}
+
+
+/**
+ * msm_dsi_reg_status_check() - Check dsi panel status through reg read
+ * @ctrl_pdata: pointer to the dsi controller structure
+ *
+ * This function can be used to check the panel status through reading the
+ * status register from the panel.
+ *
+ * Return: positive value if the panel is in good state, negative value or
+ * zero otherwise.
+ */
+int msm_dsi_reg_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+{
+ int ret = 0;
+
+ if (ctrl_pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return 0;
+ }
+
+ pr_debug("%s: Checking Register status\n", __func__);
+
+ msm_dsi_clk_ctrl(&ctrl_pdata->panel_data, 1);
+
+ if (ctrl_pdata->status_cmds.link_state == DSI_HS_MODE)
+ dsi_set_tx_power_mode(0);
+
+ ret = msm_dsi_read_status(ctrl_pdata);
+
+ if (ctrl_pdata->status_cmds.link_state == DSI_HS_MODE)
+ dsi_set_tx_power_mode(1);
+
+ if (ret == 0) {
+ if (ctrl_pdata->status_buf.data[0] !=
+ ctrl_pdata->status_value) {
+ pr_err("%s: Read back value from panel is incorrect\n",
+ __func__);
+ ret = -EINVAL;
+ } else {
+ ret = 1;
+ }
+ } else {
+ pr_err("%s: Read status register returned error\n", __func__);
+ }
+
+ msm_dsi_clk_ctrl(&ctrl_pdata->panel_data, 0);
+ pr_debug("%s: Read register done with ret: %d\n", __func__, ret);
+
+ return ret;
+}
+
+/**
+ * msm_dsi_bta_status_check() - Check dsi panel status through bta check
+ * @ctrl_pdata: pointer to the dsi controller structure
+ *
+ * This function can be used to check status of the panel using bta check
+ * for the panel.
+ *
+ * Return: positive value if the panel is in good state, negative value or
+ * zero otherwise.
+ */
+static int msm_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
int ret = 0;
@@ -1440,13 +1590,16 @@ static int msm_dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable)
&byteclk_rate, &pclk_rate);
msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate,
byteclk_rate, pclk_rate);
+ msm_dsi_prepare_clocks();
msm_dsi_clk_enable();
}
} else {
dsi_host_private->clk_count--;
if (dsi_host_private->clk_count == 0) {
+ msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask);
msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
msm_dsi_clk_disable();
+ msm_dsi_unprepare_clocks();
msm_dsi_ahb_ctrl(0);
}
}
@@ -1467,9 +1620,19 @@ void msm_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl)
complete(&ctrl->mdp_comp);
dsi_buf_alloc(&ctrl->tx_buf, SZ_4K);
dsi_buf_alloc(&ctrl->rx_buf, SZ_4K);
+ dsi_buf_alloc(&ctrl->status_buf, SZ_4K);
ctrl->cmdlist_commit = msm_dsi_cmdlist_commit;
ctrl->panel_mode = ctrl->panel_data.panel_info.mipi.mode;
- ctrl->check_status = msm_dsi_bta_status_check;
+
+ if (ctrl->status_mode == ESD_REG)
+ ctrl->check_status = msm_dsi_reg_status_check;
+ else if (ctrl->status_mode == ESD_BTA)
+ ctrl->check_status = msm_dsi_bta_status_check;
+
+ if (ctrl->status_mode == ESD_MAX) {
+ pr_err("%s: Using default BTA for ESD check\n", __func__);
+ ctrl->check_status = msm_dsi_bta_status_check;
+ }
}
static int __devinit msm_dsi_probe(struct platform_device *pdev)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment