Merge changes I0e3776c7,I630cc47b into msm-3.0
* changes:
msm_fb: display: add dcs read parser
msm_fb: display: configure dsi control as free run
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 37c9ca8..c522b0f 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -541,7 +541,7 @@
#ifdef CONFIG_FB_MSM_MDP303
#ifdef CONFIG_FB_MSM_MIPI_DSI
- mipi_dsi_cmd_mdp_sw_trigger();
+ mipi_dsi_cmd_mdp_start();
#endif
#endif
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 4cd69ef..0020fd5 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -171,8 +171,8 @@
* dma_p = 0, dma_s = 1
*/
MDP_OUTP(MDP_BASE + 0x000a0, 0x10);
- /* enable dsi trigger on dma_p */
- MDP_OUTP(MDP_BASE + 0x000a4, 0x01);
+ /* disable dsi trigger */
+ MDP_OUTP(MDP_BASE + 0x000a4, 0x00);
/* whole screen for base layer */
src = (uint8 *) iBuf->buf;
@@ -461,7 +461,7 @@
/* kick off dmap */
outpdw(MDP_BASE + 0x000c, 0x0);
/* trigger dsi cmd engine */
- mipi_dsi_cmd_mdp_sw_trigger();
+ mipi_dsi_cmd_mdp_start();
mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
}
@@ -521,7 +521,7 @@
/* kick off dmap */
outpdw(MDP_BASE + 0x000c, 0x0);
/* trigger dsi cmd engine */
- mipi_dsi_cmd_mdp_sw_trigger();
+ mipi_dsi_cmd_mdp_start();
mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
}
@@ -638,6 +638,11 @@
/* change mdp clk */
mdp4_set_perf_level();
+ mipi_dsi_mdp_busy_wait(mfd);
+
+ if (dsi_pipe->blt_addr == 0)
+ mipi_dsi_cmd_mdp_start();
+
mdp4_overlay_dsi_state_set(ST_DSI_PLAYING);
spin_lock_irqsave(&mdp_spin_lock, flag);
@@ -648,11 +653,6 @@
/* start OVERLAY pipe */
spin_unlock_irqrestore(&mdp_spin_lock, flag);
mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
-
- if (dsi_pipe->blt_addr == 0) {
- /* trigger dsi cmd engine */
- mipi_dsi_cmd_mdp_sw_trigger();
- }
}
void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd)
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index c18f2a0..00256e6 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -87,6 +87,7 @@
if (mdp_rev >= MDP_REV_41) {
mdp4_dsi_cmd_dma_busy_wait(mfd);
mdp4_dsi_blt_dmap_busy_wait(mfd);
+ mipi_dsi_mdp_busy_wait(mfd);
} else {
mdp3_dsi_cmd_dma_busy_wait(mfd);
}
diff --git a/drivers/video/msm/mipi_dsi.h b/drivers/video/msm/mipi_dsi.h
index 14d6bd9..9907109 100644
--- a/drivers/video/msm/mipi_dsi.h
+++ b/drivers/video/msm/mipi_dsi.h
@@ -222,6 +222,17 @@
#define DTYPE_PERIPHERAL_OFF 0x22
#define DTYPE_PERIPHERAL_ON 0x32
+/*
+ * dcs response
+ */
+#define DTYPE_ACK_ERR_RESP 0x02
+#define DTYPE_EOT_RESP 0x08 /* end of tx */
+#define DTYPE_GEN_READ1_RESP 0x11 /* 1 parameter, short */
+#define DTYPE_GEN_READ2_RESP 0x12 /* 2 parameter, short */
+#define DTYPE_GEN_LREAD_RESP 0x1a
+#define DTYPE_DCS_LREAD_RESP 0x1c
+#define DTYPE_DCS_READ1_RESP 0x21 /* 1 parameter, short */
+#define DTYPE_DCS_READ2_RESP 0x22 /* 2 parameter, short */
struct dsi_cmd_desc {
int dtype;
@@ -261,7 +272,7 @@
void mipi_dsi_op_mode_config(int mode);
void mipi_dsi_cmd_mode_ctrl(int enable);
void mdp4_dsi_cmd_trigger(void);
-void mipi_dsi_cmd_mdp_sw_trigger(void);
+void mipi_dsi_cmd_mdp_start(void);
void mipi_dsi_cmd_bta_sw_trigger(void);
void mipi_dsi_ack_err_status(void);
void mipi_dsi_set_tear_on(struct msm_fb_data_type *mfd);
@@ -276,6 +287,7 @@
void mipi_dsi_post_kickoff_del(struct dsi_kickoff_action *act);
void mipi_dsi_controller_cfg(int enable);
void mipi_dsi_sw_reset(void);
+void mipi_dsi_mdp_busy_wait(struct msm_fb_data_type *mfd);
irqreturn_t mipi_dsi_isr(int irq, void *ptr);
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index 0697aac..9caa154 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -41,10 +41,12 @@
int mipi_dsi_clk_on;
static struct completion dsi_dma_comp;
+static struct completion dsi_mdp_comp;
static struct dsi_buf dsi_tx_buf;
static int dsi_irq_enabled;
-static int dsi_cmd_trigger;
-static spinlock_t dsi_lock;
+static spinlock_t dsi_irq_lock;
+static spinlock_t dsi_mdp_lock;
+static int dsi_mdp_busy;
static struct list_head pre_kickoff_list;
static struct list_head post_kickoff_list;
@@ -52,54 +54,44 @@
void mipi_dsi_init(void)
{
init_completion(&dsi_dma_comp);
+ init_completion(&dsi_mdp_comp);
mipi_dsi_buf_alloc(&dsi_tx_buf, DSI_BUF_SIZE);
- spin_lock_init(&dsi_lock);
+ spin_lock_init(&dsi_irq_lock);
+ spin_lock_init(&dsi_mdp_lock);
INIT_LIST_HEAD(&pre_kickoff_list);
INIT_LIST_HEAD(&post_kickoff_list);
}
-void mipi_dsi_enable_irq(enum dsi_trigger_type type)
+void mipi_dsi_enable_irq(void)
{
unsigned long flags;
- spin_lock_irqsave(&dsi_lock, flags);
- if (type == DSI_CMD_MODE_DMA)
- dsi_cmd_trigger = 1;
-
- pr_debug("%s(): dsi_irq_enabled %u, dsi_cmd_trigger %u\n",
- __func__, dsi_irq_enabled, dsi_cmd_trigger);
-
+ spin_lock_irqsave(&dsi_irq_lock, flags);
if (dsi_irq_enabled) {
pr_debug("%s: IRQ aleady enabled\n", __func__);
- spin_unlock_irqrestore(&dsi_lock, flags);
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
return;
}
dsi_irq_enabled = 1;
enable_irq(dsi_irq);
- spin_unlock_irqrestore(&dsi_lock, flags);
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
}
-void mipi_dsi_disable_irq(enum dsi_trigger_type type)
+void mipi_dsi_disable_irq(void)
{
unsigned long flags;
- spin_lock_irqsave(&dsi_lock, flags);
- if (type == DSI_CMD_MODE_DMA)
- dsi_cmd_trigger = 0;
-
- pr_debug("%s(): dsi_irq_enabled %u, dsi_cmd_trigger %u\n",
- __func__, dsi_irq_enabled, dsi_cmd_trigger);
-
+ spin_lock_irqsave(&dsi_irq_lock, flags);
if (dsi_irq_enabled == 0) {
pr_debug("%s: IRQ already disabled\n", __func__);
- spin_unlock_irqrestore(&dsi_lock, flags);
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
return;
}
dsi_irq_enabled = 0;
disable_irq(dsi_irq);
- spin_unlock_irqrestore(&dsi_lock, flags);
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
}
/*
@@ -108,19 +100,16 @@
*/
void mipi_dsi_disable_irq_nosync(void)
{
- spin_lock(&dsi_lock);
- pr_debug("%s(): dsi_irq_enabled %u, dsi_cmd_trigger %u\n",
- __func__, dsi_irq_enabled, dsi_cmd_trigger);
-
- if (dsi_irq_enabled == 0 || dsi_cmd_trigger == 1) {
+ spin_lock(&dsi_irq_lock);
+ if (dsi_irq_enabled == 0) {
pr_debug("%s: IRQ cannot be disabled\n", __func__);
- spin_unlock(&dsi_lock);
+ spin_unlock(&dsi_irq_lock);
return;
}
dsi_irq_enabled = 0;
disable_irq_nosync(dsi_irq);
- spin_unlock(&dsi_lock);
+ spin_unlock(&dsi_irq_lock);
}
void mipi_dsi_turn_on_clks(void)
@@ -728,6 +717,43 @@
return len;
}
+/*
+ * mipi_dsi_short_read1_resp: 1 parameter
+ */
+static int mipi_dsi_short_read1_resp(struct dsi_buf *rp)
+{
+ /* strip out dcs type */
+ rp->data++;
+ rp->len = 1;
+ return rp->len;
+}
+
+/*
+ * mipi_dsi_short_read2_resp: 2 parameter
+ */
+static int mipi_dsi_short_read2_resp(struct dsi_buf *rp)
+{
+ /* strip out dcs type */
+ rp->data++;
+ rp->len = 2;
+ return rp->len;
+}
+
+static int mipi_dsi_long_read_resp(struct dsi_buf *rp)
+{
+ short len;
+
+ len = rp->data[2];
+ len <<= 8;
+ len |= rp->data[1];
+ /* strip out dcs header */
+ rp->data += 4;
+ rp->len -= 4;
+ /* strip out 2 bytes of checksum */
+ rp->len -= 2;
+ return len;
+}
+
void mipi_dsi_host_init(struct mipi_panel_info *pinfo)
{
uint32 dsi_ctrl, intr_ctrl;
@@ -936,12 +962,42 @@
wmb();
}
-void mipi_dsi_cmd_mdp_sw_trigger(void)
+void mipi_dsi_mdp_busy_wait(struct msm_fb_data_type *mfd)
{
- mipi_dsi_pre_kickoff_action();
- mipi_dsi_enable_irq(DSI_CMD_MODE_MDP);
- MIPI_OUTP(MIPI_DSI_BASE + 0x090, 0x01); /* trigger */
- wmb();
+ unsigned long flag;
+ int need_wait = 0;
+
+ pr_debug("%s: start pid=%d\n",
+ __func__, current->pid);
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ if (dsi_mdp_busy == TRUE) {
+ INIT_COMPLETION(dsi_mdp_comp);
+ need_wait++;
+ }
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ if (need_wait) {
+ /* wait until DMA finishes the current job */
+ pr_debug("%s: pending pid=%d\n",
+ __func__, current->pid);
+ wait_for_completion(&dsi_mdp_comp);
+ }
+ pr_debug("%s: done pid=%d\n",
+ __func__, current->pid);
+}
+
+void mipi_dsi_cmd_mdp_start(void)
+{
+ unsigned long flag;
+
+
+ if (!in_interrupt())
+ mipi_dsi_pre_kickoff_action();
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ mipi_dsi_enable_irq();
+ dsi_mdp_busy = TRUE;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
}
@@ -1024,6 +1080,7 @@
struct dsi_cmd_desc *cm;
uint32 dsi_ctrl, ctrl;
int i, video_mode;
+ unsigned long flag;
/* turn on cmd mode
* for video mode, do not send cmds more than
@@ -1050,7 +1107,11 @@
}
}
- mipi_dsi_enable_irq(DSI_CMD_MODE_DMA);
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ mipi_dsi_enable_irq();
+ dsi_mdp_busy = TRUE;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
cm = cmds;
mipi_dsi_buf_init(tp);
for (i = 0; i < cnt; i++) {
@@ -1061,7 +1122,12 @@
msleep(cm->wait);
cm++;
}
- mipi_dsi_disable_irq(DSI_CMD_MODE_DMA);
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = FALSE;
+ mipi_dsi_disable_irq();
+ complete(&dsi_mdp_comp);
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
if (video_mode)
MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl); /* restore */
@@ -1091,10 +1157,14 @@
*/
int mipi_dsi_cmds_rx(struct msm_fb_data_type *mfd,
struct dsi_buf *tp, struct dsi_buf *rp,
- struct dsi_cmd_desc *cmds, int len)
+ struct dsi_cmd_desc *cmds, int rlen)
{
- int cnt;
- static int pkt_size;
+ int cnt, len, diff, pkt_size;
+ unsigned long flag;
+ char cmd;
+
+ len = rlen;
+ diff = 0;
if (len <= 2)
cnt = 4; /* short read */
@@ -1108,6 +1178,7 @@
len = MIPI_DSI_LEN; /* 8 bytes at most */
len = (len + 3) & ~0x03; /* len 4 bytes align */
+ diff = len - rlen;
/*
* add extra 2 bytes to len to have overall
* packet size is multipe by 4. This also make
@@ -1128,16 +1199,17 @@
#endif
}
- mipi_dsi_enable_irq(DSI_CMD_MODE_DMA);
- if (pkt_size != len) {
- /* set new max pkt size */
- pkt_size = len;
- max_pktsize[0] = pkt_size;
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ mipi_dsi_enable_irq();
+ dsi_mdp_busy = TRUE;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
- mipi_dsi_buf_init(tp);
- mipi_dsi_cmd_dma_add(tp, pkt_size_cmd);
- mipi_dsi_cmd_dma_tx(tp);
- }
+ /* packet size need to be set at every read */
+ pkt_size = len;
+ max_pktsize[0] = pkt_size;
+ mipi_dsi_buf_init(tp);
+ mipi_dsi_cmd_dma_add(tp, pkt_size_cmd);
+ mipi_dsi_cmd_dma_tx(tp);
mipi_dsi_buf_init(tp);
mipi_dsi_cmd_dma_add(tp, cmds);
@@ -1149,21 +1221,36 @@
* return data from client is ready and stored
* at RDBK_DATA register already
*/
+ mipi_dsi_buf_init(rp);
mipi_dsi_cmd_dma_rx(rp, cnt);
- mipi_dsi_disable_irq(DSI_CMD_MODE_DMA);
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = FALSE;
+ mipi_dsi_disable_irq();
+ complete(&dsi_mdp_comp);
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
- /* strip off dcs header & crc */
- if (cnt > 4) { /* long response */
- if (mfd->panel_info.mipi.fixed_packet_size)
- rp->data += (cnt - len - 6); /* skip padding */
-
- rp->data += 4; /* skip dcs header */
- rp->len -= 6; /* deduct 4 bytes header + 2 bytes crc */
+ cmd = rp->data[0];
+ switch (cmd) {
+ case DTYPE_ACK_ERR_RESP:
+ pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
+ break;
+ case DTYPE_GEN_READ1_RESP:
+ case DTYPE_DCS_READ1_RESP:
+ mipi_dsi_short_read1_resp(rp);
+ break;
+ case DTYPE_GEN_READ2_RESP:
+ case DTYPE_DCS_READ2_RESP:
+ mipi_dsi_short_read2_resp(rp);
+ break;
+ case DTYPE_GEN_LREAD_RESP:
+ case DTYPE_DCS_LREAD_RESP:
+ mipi_dsi_long_read_resp(rp);
rp->len -= 2; /* extra 2 bytes added */
- } else {
- rp->data += 1; /* skip dcs short header */
- rp->len -= 2; /* deduct 1 byte header + 1 byte ecc */
+ rp->len -= diff; /* align bytes */
+ break;
+ default:
+ break;
}
return rp->len;
@@ -1343,6 +1430,10 @@
}
if (isr & DSI_INTR_CMD_MDP_DONE) {
+ spin_lock(&dsi_mdp_lock);
+ dsi_mdp_busy = FALSE;
+ spin_unlock(&dsi_mdp_lock);
+ complete(&dsi_mdp_comp);
mipi_dsi_disable_irq_nosync();
mipi_dsi_post_kickoff_action();
}
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c
index c6fdeff..1ff950d 100644
--- a/drivers/video/msm/mipi_novatek.c
+++ b/drivers/video/msm/mipi_novatek.c
@@ -312,9 +312,6 @@
tp = &novatek_tx_buf;
rp = &novatek_rx_buf;
- mipi_dsi_buf_init(rp);
- mipi_dsi_buf_init(tp);
-
cmd = &novatek_manufacture_id_cmd;
mipi_dsi_cmds_rx(mfd, tp, rp, cmd, 3);
lp = (uint32 *)rp->data;
@@ -445,6 +442,7 @@
/* mdp4_dsi_cmd_busy_wait: will turn on dsi clock also */
mdp4_dsi_cmd_dma_busy_wait(mfd);
mdp4_dsi_blt_dmap_busy_wait(mfd);
+ mipi_dsi_mdp_busy_wait(mfd);
led_pwm1[1] = (unsigned char)(mfd->bl_level);
mipi_dsi_cmds_tx(mfd, &novatek_tx_buf, novatek_cmd_backlight_cmds,
diff --git a/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c b/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c
index 19c91f4..fbd2495 100644
--- a/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c
+++ b/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c
@@ -79,7 +79,7 @@
pinfo.mipi.t_clk_post = 0x22;
pinfo.mipi.t_clk_pre = 0x3f;
pinfo.mipi.stream = 0; /* dma_p */
- pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
pinfo.mipi.te_sel = 1; /* TE from vsycn gpio */
pinfo.mipi.interleave_max = 1;