msm: camera: Fix for inline jpeg corrupted image

Enable IMEM clock for Inline mode. For Inline mode, VFE writes MCUs
of frame to IMEM and GEMINI reads it from IMEM and encode the image.

Sync VFE, IMEM and GEMINI clock to 228MHz. VFE and IMEM are running
at 228MHz. But Gemini was running at 158Mhz that creates bootleneck and
generat overflow irq error.

Add VFE_OUTPUTS_JPEG_AND_THUMBANIL operation mode to fix
FE overflow IRQ error in gemini.

Change-Id: Iaf20892d33d30e7cb8d6ab5fd75551aff260098f
Signed-off-by: Jignesh Mehta <jigneshm@codeaurora.org>
diff --git a/drivers/media/video/msm/gemini/msm_gemini_sync.c b/drivers/media/video/msm/gemini/msm_gemini_sync.c
index 0f0bd67..f035ad6 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_sync.c
+++ b/drivers/media/video/msm/gemini/msm_gemini_sync.c
@@ -435,8 +435,11 @@
 	}
 
 	buf_cmd = buf_p->vbuf;
-	msm_gemini_platform_p2v(buf_p->file, &buf_p->msm_buffer,
-				&buf_p->handle);
+	if (pgmn_dev->op_mode == MSM_GEMINI_MODE_OFFLINE_ENCODE ||
+		pgmn_dev->op_mode == MSM_GEMINI_MODE_OFFLINE_ROTATION) {
+		msm_gemini_platform_p2v(buf_p->file, &buf_p->msm_buffer,
+			&buf_p->handle);
+	}
 	kfree(buf_p->subsystem_id);
 	kfree(buf_p);
 
@@ -484,16 +487,23 @@
 		kfree(buf_p);
 		return -ENOMEM;
 	}
+	if (pgmn_dev->op_mode == MSM_GEMINI_MODE_REALTIME_ENCODE) {
+		buf_p->y_buffer_addr    = buf_cmd.y_off;
+	} else {
 	buf_p->y_buffer_addr    = msm_gemini_platform_v2p(buf_cmd.fd,
 		buf_cmd.y_len + buf_cmd.cbcr_len, &buf_p->file,
 			&buf_p->msm_buffer, buf_p->subsystem_id, &buf_p->handle)
 			+ buf_cmd.offset;
+	}
 	buf_p->y_len          = buf_cmd.y_len;
 
 	buf_p->cbcr_buffer_addr = buf_p->y_buffer_addr + buf_cmd.y_len;
 	buf_p->cbcr_len       = buf_cmd.cbcr_len;
 
 	buf_p->num_of_mcu_rows = buf_cmd.num_of_mcu_rows;
+	GMN_DBG("%s: y_addr=%x,y_len=%x,cbcr_addr=%x,cbcr_len=%x\n", __func__,
+		buf_p->y_buffer_addr, buf_p->y_len, buf_p->cbcr_buffer_addr,
+		buf_p->cbcr_len);
 
 	if (!buf_p->y_buffer_addr || !buf_p->cbcr_buffer_addr) {
 		GMN_PR_ERR("%s:%d] v2p wrong\n", __func__, __LINE__);
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index ea969cf..9bfc239 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -117,7 +117,7 @@
 	case CAMIO_JPEG_CLK:
 		camio_jpeg_clk =
 		clk = clk_get(NULL, "ijpeg_clk");
-		clk_set_rate(clk, 153600000);
+		clk_set_rate(clk, 228571000);
 		break;
 
 	case CAMIO_JPEG_PCLK:
@@ -191,6 +191,11 @@
 	if (rc < 0)
 		return rc;
 	rc = msm_camio_clk_disable(CAMIO_JPEG_CLK);
+	if (rc < 0)
+		return rc;
+	rc = msm_camio_clk_disable(CAMIO_IMEM_CLK);
+	if (rc < 0)
+		return rc;
 
 	if (fs_ijpeg) {
 		rc = regulator_disable(fs_ijpeg);
@@ -225,6 +230,10 @@
 	if (rc < 0)
 		return rc;
 
+	rc = msm_camio_clk_enable(CAMIO_IMEM_CLK);
+	if (rc < 0)
+		return rc;
+
 	CDBG("%s: exit %d\n", __func__, rc);
 	return rc;
 }
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index fdd1f0e..a0ac70d 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -90,6 +90,7 @@
 		case VFE_OUTPUTS_MAIN_AND_VIDEO:
 		case VFE_OUTPUTS_MAIN_AND_THUMB:
 		case VFE_OUTPUTS_RAW:
+		case VFE_OUTPUTS_JPEG_AND_THUMB:
 			image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
 			break;
 		case VFE_OUTPUTS_THUMB_AND_MAIN:
@@ -123,6 +124,9 @@
 		case VFE_OUTPUTS_THUMB_AND_MAIN:
 			image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
 			break;
+		case VFE_OUTPUTS_JPEG_AND_THUMB:
+			image_mode = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
+			break;
 		default:
 			image_mode = -1;
 			break;
@@ -200,16 +204,27 @@
 		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
 		break;
 	case VFE_MSG_V32_JPEG_CAPTURE:
+		D("%s:VFE_MSG_V32_JPEG_CAPTURE vdata->type %d\n", __func__,
+			vdata->type);
 		free_buf.num_planes = 1;
-		free_buf.ch_paddr[0] = IMEM_Y_OFFSET;
-		free_buf.ch_paddr[1] = IMEM_CBCR_OFFSET;
+		free_buf.ch_paddr[0] = IMEM_Y_PING_OFFSET;
+		free_buf.ch_paddr[1] = IMEM_CBCR_PING_OFFSET;
 		cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
 		cfgcmd.value = &vfe_id;
 		vfe_params.vfe_cfg = &cfgcmd;
 		vfe_params.data = (void *)&free_buf;
+		D("%s:VFE_MSG_V32_JPEG_CAPTURE y_ping=%x cbcr_ping=%x\n",
+			__func__, free_buf.ch_paddr[0], free_buf.ch_paddr[1]);
 		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
 		/* Write the same buffer into PONG */
+		free_buf.ch_paddr[0] = IMEM_Y_PONG_OFFSET;
+		free_buf.ch_paddr[1] = IMEM_CBCR_PONG_OFFSET;
 		cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
+		cfgcmd.value = &vfe_id;
+		vfe_params.vfe_cfg = &cfgcmd;
+		vfe_params.data = (void *)&free_buf;
+		D("%s:VFE_MSG_V32_JPEG_CAPTURE y_pong=%x cbcr_pong=%x\n",
+			__func__, free_buf.ch_paddr[0], free_buf.ch_paddr[1]);
 		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
 		break;
 	case VFE_MSG_OUTPUT_IRQ:
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index b539d19..e9201ea 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -868,6 +868,7 @@
 	irq_comp_mask	= msm_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 
 	if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
+		vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
 		vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
 		if (vfe32_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_PRIMARY) {
@@ -1297,8 +1298,6 @@
 		rc = vfe32_capture_raw(snapshot_cnt);
 		break;
 	case VFE_CMD_CAPTURE:
-		CDBG("vfe32_proc_general: cmdID = %s op mode = %d\n",
-			vfe32_general_cmd[cmd->id], vfe32_ctrl->operation_mode);
 		if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
 				sizeof(uint32_t))) {
 			rc = -EFAULT;
@@ -2960,13 +2959,14 @@
 
 	free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
 		VFE_MSG_OUTPUT_SECONDARY);
-
 	out_bool = ((vfe32_ctrl->operation_mode ==
 				VFE_OUTPUTS_THUMB_AND_MAIN ||
 			vfe32_ctrl->operation_mode ==
 				VFE_OUTPUTS_MAIN_AND_THUMB ||
 			vfe32_ctrl->operation_mode ==
-				VFE_OUTPUTS_RAW) &&
+				VFE_OUTPUTS_RAW ||
+			vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_JPEG_AND_THUMB) &&
 			(vfe32_ctrl->vfe_capture_count <= 1)) || free_buf;
 
 	if (out_bool) {
@@ -3003,7 +3003,9 @@
 			vfe32_ctrl->operation_mode ==
 				VFE_OUTPUTS_MAIN_AND_THUMB ||
 			vfe32_ctrl->operation_mode ==
-				VFE_OUTPUTS_RAW)
+				VFE_OUTPUTS_RAW ||
+			vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_JPEG_AND_THUMB)
 			vfe32_ctrl->outpath.out1.capture_cnt--;
 
 		vfe_send_outmsg(&vfe32_ctrl->subdev,
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 07784e2..e02597a 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -241,8 +241,17 @@
 #define VPE_SCALER_CONFIG_LEN           260
 #define VPE_DIS_OFFSET_CFG_LEN          12
 
-#define IMEM_Y_OFFSET  0x2E000000
-#define IMEM_CBCR_OFFSET  0x2E00FA00
+
+#define CAPTURE_WIDTH          1280
+#define IMEM_Y_SIZE            (CAPTURE_WIDTH*16)
+#define IMEM_CBCR_SIZE         (CAPTURE_WIDTH*8)
+
+#define IMEM_Y_PING_OFFSET     0x2E000000
+#define IMEM_CBCR_PING_OFFSET  (IMEM_Y_PING_OFFSET + IMEM_Y_SIZE)
+
+#define IMEM_Y_PONG_OFFSET     (IMEM_CBCR_PING_OFFSET + IMEM_CBCR_SIZE)
+#define IMEM_CBCR_PONG_OFFSET  (IMEM_Y_PONG_OFFSET + IMEM_Y_SIZE)
+
 
 struct msm_vpe_op_mode_cfg {
 	uint8_t op_mode_cfg[VPE_OPERATION_MODE_CFG_LEN];