msm_fb: display: Copy splash image to kernel memory

The bootloader memory from which the splashscreen is shown
gets reclaimed before frame update happens from framework.
Hence, copy the splash image to a local buffer as soon as
display is initialized. This will ensure proper continuous
splashscreen functionality.

CRs-Fixed: 378721
Change-Id: I55a7b97eeced56d2f108d34998d58966610c4305
Signed-off-by: Pradeep Jilagam <pjilagam@codeaurora.org>

Conflicts:

	drivers/video/msm/msm_fb.h

Signed-off-by: Mayank Goyal <goyalm@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index 75ae5ce..ecf5ec6 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -586,6 +586,8 @@
 	.mem_hid = MEMTYPE_EBI1,
 #endif
 	.cont_splash_enabled = 0x01,
+	.splash_screen_addr = 0x00,
+	.splash_screen_size = 0x00,
 	.mdp_iommu_split_domain = 0,
 };
 
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index ea887dc..a7183f1 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -2674,6 +2674,7 @@
 	struct mipi_panel_info *mipi;
 #endif
 	static int contSplash_update_done;
+	char *cp;
 
 	if ((pdev->id == 0) && (pdev->num_resources > 0)) {
 		mdp_init_pdev = pdev;
@@ -2746,7 +2747,44 @@
 	if (mdp_pdata) {
 		if (mdp_pdata->cont_splash_enabled) {
 			mfd->cont_splash_done = 0;
+
 			if (!contSplash_update_done) {
+				uint32 bpp = 3;
+				/*read panel wxh and calculate splash screen
+				size*/
+				mdp_pdata->splash_screen_size =
+						inpdw(MDP_BASE + 0x90004);
+				mdp_pdata->splash_screen_size =
+				(((mdp_pdata->splash_screen_size >> 16) &
+					0x00000FFF) * (
+					mdp_pdata->splash_screen_size &
+					0x00000FFF)) * bpp;
+
+				mdp_pdata->splash_screen_addr =
+						inpdw(MDP_BASE + 0x90008);
+
+				mfd->copy_splash_buf = dma_alloc_coherent(NULL,
+					mdp_pdata->splash_screen_size,
+					(dma_addr_t *) &(mfd->copy_splash_phys),
+					GFP_KERNEL);
+
+				if (!mfd->copy_splash_buf) {
+					pr_err("DMA ALLOC FAILED for SPLASH\n");
+					return -ENOMEM;
+				}
+				cp = (char *)ioremap(
+						mdp_pdata->splash_screen_addr,
+						mdp_pdata->splash_screen_size);
+				if (!cp) {
+					pr_err("IOREMAP FAILED for SPLASH\n");
+					return -ENOMEM;
+				}
+				memcpy(mfd->copy_splash_buf, cp,
+					mdp_pdata->splash_screen_size);
+
+				MDP_OUTP(MDP_BASE + 0x90008,
+						mfd->copy_splash_phys);
+
 				if (mfd->panel.type == MIPI_VIDEO_PANEL ||
 				    mfd->panel.type == LCDC_PANEL)
 					mdp_pipe_ctrl(MDP_CMD_BLOCK,
@@ -3155,6 +3193,17 @@
 	mutex_unlock(&mdp_suspend_mutex);
 }
 
+void mdp_free_splash_buffer(struct msm_fb_data_type *mfd)
+{
+	if (mfd->copy_splash_buf) {
+		dma_free_coherent(NULL,	mdp_pdata->splash_screen_size,
+			mfd->copy_splash_buf,
+			(dma_addr_t) mfd->copy_splash_phys);
+
+		mfd->copy_splash_buf = NULL;
+	}
+}
+
 #ifdef CONFIG_PM
 static void mdp_suspend_sub(void)
 {
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 7bcea6e..046e161 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -776,7 +776,7 @@
 int mdp_lcdc_on(struct platform_device *pdev);
 int mdp_lcdc_off(struct platform_device *pdev);
 void mdp_lcdc_update(struct msm_fb_data_type *mfd);
-
+void mdp_free_splash_buffer(struct msm_fb_data_type *mfd);
 #ifdef CONFIG_FB_MSM_MDP303
 int mdp_dsi_video_on(struct platform_device *pdev);
 int mdp_dsi_video_off(struct platform_device *pdev);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 3818d09..4412221 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -2003,6 +2003,9 @@
 		}
 	}
 
+	if (info->node == 0 && (mfd->cont_splash_done)) /* primary */
+		mdp_free_splash_buffer(mfd);
+
 	++mfd->panel_info.frame_count;
 	return 0;
 }
@@ -3214,6 +3217,9 @@
 		}
 	}
 
+	if (info->node == 0 && (mfd->cont_splash_done)) /* primary */
+		mdp_free_splash_buffer(mfd);
+
 	return ret;
 }
 
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 2f915b9..1a185fb 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -211,6 +211,8 @@
 	void *msm_fb_backup;
 	boolean panel_driver_on;
 	int vsync_sysfs_created;
+	void *copy_splash_buf;
+	unsigned char *copy_splash_phys;
 };
 struct msm_fb_backup_type {
 	struct fb_info info;