platform: msm_shared: Send DCS on commands after tg is enabled

Some DSI panels require blank frames to be sent before receiving
the ON commands. This requires DSI to send out all the commands
once MDP is enabled(timging generator enabled).
The following flag needs to be set to enable this mode.

    - pinfo->mipi.cmds_post_tg = 1;

Change-Id: I5d5856cddf96399c1eed0c1523c9747be4e970a4
diff --git a/platform/msm_shared/display.c b/platform/msm_shared/display.c
index 849b294..37b066a 100644
--- a/platform/msm_shared/display.c
+++ b/platform/msm_shared/display.c
@@ -170,6 +170,11 @@
 		ret = mdp_dsi_video_on(pinfo);
 		if (ret)
 			goto msm_display_on_out;
+
+		ret = mdss_dsi_post_on(panel);
+		if (ret)
+			goto msm_display_on_out;
+
 		ret = mipi_dsi_on();
 		if (ret)
 			goto msm_display_on_out;
@@ -185,6 +190,11 @@
 			if (ret)
 				goto msm_display_on_out;
 		}
+
+		ret = mdss_dsi_post_on(panel);
+		if (ret)
+			goto msm_display_on_out;
+
 		break;
 	case LCDC_PANEL:
 		dprintf(INFO, "Turn on LCDC PANEL.\n");
diff --git a/platform/msm_shared/include/mipi_dsi.h b/platform/msm_shared/include/mipi_dsi.h
index cabafbf..84d5b44 100644
--- a/platform/msm_shared/include/mipi_dsi.h
+++ b/platform/msm_shared/include/mipi_dsi.h
@@ -79,6 +79,10 @@
 
 #define DSI_LANE_CTRL                         REG_DSI(0x0A8)
 
+#define DSI_VIDEO_MODE_DONE_MASK              BIT(17)
+#define DSI_VIDEO_MODE_DONE_AK                BIT(16)
+#define DSI_VIDEO_MODE_DONE_STAT              BIT(16)
+
 /**********************************************************
   DSI register configuration options
  **********************************************************/
@@ -200,6 +204,7 @@
 	int size;
 	char *payload;
 	int wait;
+	uint8_t cmds_post_tg;
 };
 
 struct mipi_dsi_panel_config {
@@ -214,6 +219,7 @@
 	struct mipi_dsi_cmd *panel_cmds;
 	int num_of_panel_cmds;
 	uint32_t signature;
+	char cmds_post_tg;
 };
 
 static char read_id_a1h_cmd[4] = { 0xA1, 0x00, 0x06, 0xA0 };	/* DTYPE_DCS_READ */
diff --git a/platform/msm_shared/include/msm_panel.h b/platform/msm_shared/include/msm_panel.h
index 6befefd..456b7cb 100755
--- a/platform/msm_shared/include/msm_panel.h
+++ b/platform/msm_shared/include/msm_panel.h
@@ -114,6 +114,7 @@
 };
 
 struct mipi_panel_info {
+	char cmds_post_tg;	/* send on commands after tg on */
 	char mode;		/* video/cmd */
 	char interleave_mode;
 	int eof_bllp_power;
diff --git a/platform/msm_shared/mipi_dsi.c b/platform/msm_shared/mipi_dsi.c
index 3878be3..003dd04 100644
--- a/platform/msm_shared/mipi_dsi.c
+++ b/platform/msm_shared/mipi_dsi.c
@@ -158,6 +158,35 @@
 	return status;
 }
 
+int mdss_dsi_wait4_video_done()
+{
+	unsigned long read;
+	unsigned long count = 0;
+	int status = 0;
+
+	read = readl(DSI_INT_CTRL);
+	/* Enable VIDEO MODE DONE MASK and clear the interrupt */
+	read = read | DSI_VIDEO_MODE_DONE_MASK | DSI_VIDEO_MODE_DONE_AK;
+	writel(read, DSI_INT_CTRL);
+	dsb();
+	read = readl(DSI_INT_CTRL) & DSI_VIDEO_MODE_DONE_STAT;
+	while (!read) {
+		read = readl(DSI_INT_CTRL) & DSI_VIDEO_MODE_DONE_STAT;
+		count++;
+		if (count > 0xffff) {
+			status = FAIL;
+			dprintf(CRITICAL,
+				"Panel CMD: Did not recieve video mode done interrupt\n");
+			return status;
+		}
+	}
+
+	writel((readl(DSI_INT_CTRL) | 0x01000001), DSI_INT_CTRL);
+	dprintf(SPEW, "Panel wait_4_video_done: Recieved video mode done ack\n");
+	return status;
+
+}
+
 int mdss_dual_dsi_cmds_tx(struct mipi_dsi_cmd *cmds, int count)
 {
 	int ret = 0;
@@ -176,6 +205,16 @@
 
 	cm = cmds;
 	for (i = 0; i < count; i++) {
+		if (cmds->cmds_post_tg) {
+			/* Wait for VIDEO_MODE_DONE */
+			ret = mdss_dsi_wait4_video_done();
+			if (ret)
+				goto wait4video_error;
+
+			/* Skip BLLP 4ms */
+			mdelay(4);
+		}
+
 		memcpy((void *)off, (cm->payload), cm->size);
 		writel(off, MIPI_DSI0_BASE + DMA_CMD_OFFSET);
 		writel(cm->size, MIPI_DSI0_BASE + DMA_CMD_LENGTH);	// reg 0x48 for this build
@@ -190,6 +229,7 @@
 		cm++;
 	}
 #endif
+wait4video_error:
 	return ret;
 }
 
@@ -262,6 +302,15 @@
 
 	cm = cmds;
 	for (i = 0; i < count; i++) {
+		if (cmds->cmds_post_tg) {
+			/* Wait for VIDEO_MODE_DONE */
+			ret = mdss_dsi_wait4_video_done();
+			if (ret)
+				goto mipi_cmds_error;
+
+			/* Skip BLLP 4ms */
+			mdelay(4);
+		}
 		memcpy((void *)off, (cm->payload), cm->size);
 		writel(off, DSI_DMA_CMD_OFFSET);
 		writel(cm->size, DSI_DMA_CMD_LENGTH);	// reg 0x48 for this build
@@ -274,6 +323,7 @@
 			udelay(80);
 		cm++;
 	}
+mipi_cmds_error:
 	return ret;
 }
 
@@ -365,6 +415,7 @@
 	uint8_t lane_swap = 0;
 	uint32_t timing_ctl = 0;
 	uint32_t lane_swap_dsi1 = 0;
+	uint32_t ctrl_mode = 0x105;	//Default is command mode to send cmds.
 
 #if (DISPLAY_TYPE_MDSS == 1)
 	switch (pinfo->num_of_lanes) {
@@ -387,6 +438,14 @@
 	lane_swap = pinfo->lane_swap;
 	timing_ctl = ((pinfo->t_clk_post << 8) | pinfo->t_clk_pre);
 
+	if (pinfo->cmds_post_tg) {
+		/*
+		 * Need to send pixel data before sending the ON commands
+		 * so need to configure controller to VIDEO MODE.
+		 */
+		ctrl_mode = 0x103;
+	}
+
 	if (dual_dsi) {
 		writel(0x0001, MIPI_DSI1_BASE + SOFT_RESET);
 		writel(0x0000, MIPI_DSI1_BASE + SOFT_RESET);
@@ -395,7 +454,7 @@
 		writel(DMA_STREAM1 << 8 | 0x04, MIPI_DSI1_BASE + TRIG_CTRL);	// reg 0x80 dma trigger: sw
 		// trigger 0x4; dma stream1
 
-		writel(0 << 30 | DLNx_EN << 4 | 0x105, MIPI_DSI1_BASE + CTRL);	// reg 0x00 for this
+		writel(0 << 30 | DLNx_EN << 4 | ctrl_mode, MIPI_DSI1_BASE + CTRL);	// reg 0x00 for this
 		// build
 		writel(broadcast << 31 | EMBED_MODE1 << 28 | POWER_MODE2 << 26
 				| PACK_TYPE1 << 24 | VC1 << 22 | DT1 << 16 | WC1,
@@ -416,7 +475,7 @@
 	writel(DMA_STREAM1 << 8 | 0x04, MIPI_DSI0_BASE + TRIG_CTRL);	// reg 0x80 dma trigger: sw
 	// trigger 0x4; dma stream1
 
-	writel(0 << 30 | DLNx_EN << 4 | 0x105, MIPI_DSI0_BASE + CTRL);	// reg 0x00 for this
+	writel(0 << 30 | DLNx_EN << 4 | ctrl_mode, MIPI_DSI0_BASE + CTRL);	// reg 0x00 for this
 	// build
 	writel(broadcast << 31 | EMBED_MODE1 << 28 | POWER_MODE2 << 26
 	       | PACK_TYPE1 << 24 | VC1 << 22 | DT1 << 16 | WC1,
@@ -433,17 +492,27 @@
 		broadcast)
 {
 	int status = 0;
+	uint32_t ctrl_mode = 0;
 
 #if (DISPLAY_TYPE_MDSS == 1)
 	if (pinfo->panel_cmds) {
 
+		ctrl_mode = readl(MIPI_DSI0_BASE + CTRL);
 		if (broadcast) {
+			/* Enable command mode before sending the commands. */
+			writel(ctrl_mode | 0x04, MIPI_DSI0_BASE + CTRL);
+			writel(ctrl_mode | 0x04, MIPI_DSI1_BASE + CTRL);
 			status = mdss_dual_dsi_cmds_tx(pinfo->panel_cmds,
 					pinfo->num_of_panel_cmds);
+			writel(ctrl_mode, MIPI_DSI0_BASE + CTRL);
+			writel(ctrl_mode, MIPI_DSI1_BASE + CTRL);
 
 		} else {
+			/* Enable command mode before sending the commands. */
+			writel(ctrl_mode | 0x04, MIPI_DSI0_BASE + CTRL);
 			status = mipi_dsi_cmds_tx(pinfo->panel_cmds,
 					pinfo->num_of_panel_cmds);
+			writel(ctrl_mode, MIPI_DSI0_BASE + CTRL);
 			if (!status && target_panel_auto_detect_enabled())
 				status =
 					mdss_dsi_read_panel_signature(pinfo->signature);
@@ -680,6 +749,7 @@
 	mipi_pinfo.t_clk_pre = pinfo->mipi.t_clk_pre;
 	mipi_pinfo.t_clk_post = pinfo->mipi.t_clk_post;
 	mipi_pinfo.signature = pinfo->mipi.signature;
+	mipi_pinfo.cmds_post_tg = pinfo->mipi.cmds_post_tg;
 
 	mdss_dsi_phy_init(&mipi_pinfo, MIPI_DSI0_BASE, DSI0_PHY_BASE);
 	if (pinfo->mipi.dual_dsi)
@@ -702,10 +772,12 @@
 		}
 	}
 
-	ret = mdss_dsi_panel_initialize(&mipi_pinfo, pinfo->mipi.broadcast);
-	if (ret) {
-		dprintf(CRITICAL, "dsi panel init error\n");
-		goto error;
+	if (!mipi_pinfo.cmds_post_tg) {
+		ret = mdss_dsi_panel_initialize(&mipi_pinfo, pinfo->mipi.broadcast);
+		if (ret) {
+			dprintf(CRITICAL, "dsi panel init error\n");
+			goto error;
+		}
 	}
 
 	if (pinfo->rotate && panel->rotate)
@@ -716,6 +788,25 @@
 	return ret;
 }
 
+int mdss_dsi_post_on(struct msm_fb_panel_data *panel)
+{
+	int ret = 0;
+	struct msm_panel_info *pinfo = &(panel->panel_info);
+	struct mipi_dsi_panel_config mipi_pinfo;
+
+	if (pinfo->mipi.cmds_post_tg) {
+		mipi_pinfo.panel_cmds = pinfo->mipi.panel_cmds;
+		mipi_pinfo.num_of_panel_cmds = pinfo->mipi.num_of_panel_cmds;
+		mipi_pinfo.signature = pinfo->mipi.signature;
+
+		ret = mdss_dsi_panel_initialize(&mipi_pinfo, pinfo->mipi.broadcast);
+		if (ret) {
+			dprintf(CRITICAL, "dsi panel init error\n");
+		}
+	}
+	return ret;
+}
+
 int mdss_dsi_cmd_mode_config(uint16_t disp_width,
 	uint16_t disp_height,
 	uint16_t img_width,