Merge "msm: jpeg: Support for decoder 1.0 driver"
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_common.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_common.h
index 88ec1ad..04af6b6 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_common.h
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_common.h
@@ -14,12 +14,13 @@
 #define MSM_JPEG_COMMON_H
 
 #ifdef MSM_JPEG_DEBUG
-#define JPEG_DBG(fmt, args...) printk(fmt, ##args)
+#define JPEG_DBG(fmt, args...) pr_info(fmt, ##args)
 #else
 #define JPEG_DBG(fmt, args...) do { } while (0)
 #endif
 
 #define JPEG_PR_ERR   pr_err
+#define JPEG_DBG_HIGH   pr_err
 
 enum JPEG_MODE {
 	JPEG_MODE_DISABLE,
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_core.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_core.c
index 7905ff3..b67245c 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_core.c
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_core.c
@@ -17,122 +17,130 @@
 #include "msm_jpeg_platform.h"
 #include "msm_jpeg_common.h"
 
-static struct msm_jpeg_hw_pingpong fe_pingpong_buf;
-static struct msm_jpeg_hw_pingpong we_pingpong_buf;
-static int we_pingpong_index;
-static int reset_done_ack;
-static spinlock_t reset_lock;
-static wait_queue_head_t reset_wait;
-
-int msm_jpeg_core_reset(uint8_t op_mode, void *base, int size)
-{
+int msm_jpeg_core_reset(struct msm_jpeg_device *pgmn_dev, uint8_t op_mode,
+	void *base, int size) {
 	unsigned long flags;
 	int rc = 0;
 	int tm = 500; /*500ms*/
-	memset(&fe_pingpong_buf, 0, sizeof(fe_pingpong_buf));
-	fe_pingpong_buf.is_fe = 1;
-	we_pingpong_index = 0;
-	memset(&we_pingpong_buf, 0, sizeof(we_pingpong_buf));
-	spin_lock_irqsave(&reset_lock, flags);
-	reset_done_ack = 0;
+	JPEG_DBG("%s:%d] reset", __func__, __LINE__);
+	memset(&pgmn_dev->fe_pingpong_buf, 0,
+		sizeof(pgmn_dev->fe_pingpong_buf));
+	pgmn_dev->fe_pingpong_buf.is_fe = 1;
+	memset(&pgmn_dev->we_pingpong_buf, 0,
+		sizeof(pgmn_dev->we_pingpong_buf));
+	spin_lock_irqsave(&pgmn_dev->reset_lock, flags);
+	pgmn_dev->reset_done_ack = 0;
 	msm_jpeg_hw_reset(base, size);
-	spin_unlock_irqrestore(&reset_lock, flags);
+	spin_unlock_irqrestore(&pgmn_dev->reset_lock, flags);
 	rc = wait_event_interruptible_timeout(
-			reset_wait,
-			reset_done_ack,
+			pgmn_dev->reset_wait,
+			pgmn_dev->reset_done_ack,
 			msecs_to_jiffies(tm));
 
-	if (!reset_done_ack) {
+	if (!pgmn_dev->reset_done_ack) {
 		JPEG_DBG("%s: reset ACK failed %d", __func__, rc);
 		return -EBUSY;
 	}
 
 	JPEG_DBG("%s: reset_done_ack rc %d", __func__, rc);
-	spin_lock_irqsave(&reset_lock, flags);
-	reset_done_ack = 0;
-	spin_unlock_irqrestore(&reset_lock, flags);
+	spin_lock_irqsave(&pgmn_dev->reset_lock, flags);
+	pgmn_dev->reset_done_ack = 0;
+	spin_unlock_irqrestore(&pgmn_dev->reset_lock, flags);
 
 	return 0;
 }
 
-void msm_jpeg_core_release(int release_buf, int domain_num)
-{
+void msm_jpeg_core_release(struct msm_jpeg_device *pgmn_dev,
+	int domain_num) {
 	int i = 0;
 	for (i = 0; i < 2; i++) {
-		if (we_pingpong_buf.buf_status[i] && release_buf)
-			msm_jpeg_platform_p2v(we_pingpong_buf.buf[i].file,
-				&we_pingpong_buf.buf[i].handle, domain_num);
-		we_pingpong_buf.buf_status[i] = 0;
+		if (pgmn_dev->we_pingpong_buf.buf_status[i] &&
+			pgmn_dev->release_buf)
+			msm_jpeg_platform_p2v(pgmn_dev,
+				pgmn_dev->we_pingpong_buf.buf[i].file,
+				&pgmn_dev->we_pingpong_buf.buf[i].handle,
+					domain_num);
+		pgmn_dev->we_pingpong_buf.buf_status[i] = 0;
 	}
 }
 
-void msm_jpeg_core_init(void)
+void msm_jpeg_core_init(struct msm_jpeg_device *pgmn_dev)
 {
-	init_waitqueue_head(&reset_wait);
-	spin_lock_init(&reset_lock);
+	init_waitqueue_head(&pgmn_dev->reset_wait);
+	spin_lock_init(&pgmn_dev->reset_lock);
 }
 
-int msm_jpeg_core_fe_start(void)
+int msm_jpeg_core_fe_start(struct msm_jpeg_device *pgmn_dev)
 {
-	msm_jpeg_hw_fe_start();
+	msm_jpeg_hw_fe_start(pgmn_dev->base);
 	return 0;
 }
 
 /* fetch engine */
-int msm_jpeg_core_fe_buf_update(struct msm_jpeg_core_buf *buf)
+int msm_jpeg_core_fe_buf_update(struct msm_jpeg_device *pgmn_dev,
+	struct msm_jpeg_core_buf *buf)
 {
+	if (0 == buf->cbcr_len)
+		buf->cbcr_buffer_addr = 0x0;
 	JPEG_DBG("%s:%d] 0x%08x %d 0x%08x %d\n", __func__, __LINE__,
 		(int) buf->y_buffer_addr, buf->y_len,
 		(int) buf->cbcr_buffer_addr, buf->cbcr_len);
-	return msm_jpeg_hw_pingpong_update(&fe_pingpong_buf, buf);
+	return msm_jpeg_hw_pingpong_update(&pgmn_dev->fe_pingpong_buf, buf,
+		pgmn_dev->base);
 }
 
-void *msm_jpeg_core_fe_pingpong_irq(int jpeg_irq_status, void *context)
+void *msm_jpeg_core_fe_pingpong_irq(int jpeg_irq_status,
+	struct msm_jpeg_device *pgmn_dev)
 {
-	return msm_jpeg_hw_pingpong_irq(&fe_pingpong_buf);
+	return msm_jpeg_hw_pingpong_irq(&pgmn_dev->fe_pingpong_buf);
 }
 
 /* write engine */
-int msm_jpeg_core_we_buf_update(struct msm_jpeg_core_buf *buf)
-{
+int msm_jpeg_core_we_buf_update(struct msm_jpeg_device *pgmn_dev,
+	struct msm_jpeg_core_buf *buf) {
 	JPEG_DBG("%s:%d] 0x%08x 0x%08x %d\n", __func__, __LINE__,
 		(int) buf->y_buffer_addr, (int) buf->cbcr_buffer_addr,
 		buf->y_len);
-	we_pingpong_buf.buf[0] = *buf;
-	we_pingpong_buf.buf_status[0] = 1;
+	pgmn_dev->we_pingpong_buf.buf[0] = *buf;
+	pgmn_dev->we_pingpong_buf.buf_status[0] = 1;
 	msm_jpeg_hw_we_buffer_update(
-			&we_pingpong_buf.buf[0], 0);
+		&pgmn_dev->we_pingpong_buf.buf[0], 0, pgmn_dev->base);
 
 	return 0;
 }
 
-int msm_jpeg_core_we_buf_reset(struct msm_jpeg_hw_buf *buf)
+int msm_jpeg_core_we_buf_reset(struct msm_jpeg_device *pgmn_dev,
+	struct msm_jpeg_hw_buf *buf)
 {
 	int i = 0;
 	for (i = 0; i < 2; i++) {
-		if (we_pingpong_buf.buf[i].y_buffer_addr
-					== buf->y_buffer_addr)
-			we_pingpong_buf.buf_status[i] = 0;
+		if (pgmn_dev->we_pingpong_buf.buf[i].y_buffer_addr
+			== buf->y_buffer_addr)
+			pgmn_dev->we_pingpong_buf.buf_status[i] = 0;
 	}
 	return 0;
 }
 
-void *msm_jpeg_core_we_pingpong_irq(int jpeg_irq_status, void *context)
+void *msm_jpeg_core_we_pingpong_irq(int jpeg_irq_status,
+	struct msm_jpeg_device *pgmn_dev)
 {
 	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
 
-	return msm_jpeg_hw_pingpong_irq(&we_pingpong_buf);
+	return msm_jpeg_hw_pingpong_irq(&pgmn_dev->we_pingpong_buf);
 }
 
-void *msm_jpeg_core_framedone_irq(int jpeg_irq_status, void *context)
+void *msm_jpeg_core_framedone_irq(int jpeg_irq_status,
+	struct msm_jpeg_device *pgmn_dev)
 {
 	struct msm_jpeg_hw_buf *buf_p;
 
 	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
 
-	buf_p = msm_jpeg_hw_pingpong_active_buffer(&we_pingpong_buf);
-	if (buf_p) {
-		buf_p->framedone_len = msm_jpeg_hw_encode_output_size();
+	buf_p = msm_jpeg_hw_pingpong_active_buffer(
+		&pgmn_dev->we_pingpong_buf);
+	if (buf_p && !pgmn_dev->decode_flag) {
+		buf_p->framedone_len =
+			msm_jpeg_hw_encode_output_size(pgmn_dev->base);
 		JPEG_DBG("%s:%d] framedone_len %d\n", __func__, __LINE__,
 			buf_p->framedone_len);
 	}
@@ -140,14 +148,16 @@
 	return buf_p;
 }
 
-void *msm_jpeg_core_reset_ack_irq(int jpeg_irq_status, void *context)
+void *msm_jpeg_core_reset_ack_irq(int jpeg_irq_status,
+	struct msm_jpeg_device *pgmn_dev)
 {
 	/* @todo return the status back to msm_jpeg_core_reset */
 	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
 	return NULL;
 }
 
-void *msm_jpeg_core_err_irq(int jpeg_irq_status, void *context)
+void *msm_jpeg_core_err_irq(int jpeg_irq_status,
+	struct msm_jpeg_device *pgmn_dev)
 {
 	JPEG_PR_ERR("%s:%d]\n", __func__, jpeg_irq_status);
 	return NULL;
@@ -155,15 +165,32 @@
 
 static int (*msm_jpeg_irq_handler) (int, void *, void *);
 
+void msm_jpeg_core_return_buffers(struct msm_jpeg_device *pgmn_dev,
+	 int jpeg_irq_status)
+{
+	void *data = NULL;
+	data = msm_jpeg_core_fe_pingpong_irq(jpeg_irq_status,
+		pgmn_dev);
+	if (msm_jpeg_irq_handler)
+		msm_jpeg_irq_handler(MSM_JPEG_HW_MASK_COMP_FE,
+			pgmn_dev, data);
+	data = msm_jpeg_core_we_pingpong_irq(jpeg_irq_status,
+		pgmn_dev);
+	if (msm_jpeg_irq_handler)
+		msm_jpeg_irq_handler(MSM_JPEG_HW_MASK_COMP_WE,
+			pgmn_dev, data);
+}
+
 irqreturn_t msm_jpeg_core_irq(int irq_num, void *context)
 {
 	void *data = NULL;
 	unsigned long flags;
 	int jpeg_irq_status;
+	struct msm_jpeg_device *pgmn_dev = (struct msm_jpeg_device *)context;
 
 	JPEG_DBG("%s:%d] irq_num = %d\n", __func__, __LINE__, irq_num);
 
-	jpeg_irq_status = msm_jpeg_hw_irq_get_status();
+	jpeg_irq_status = msm_jpeg_hw_irq_get_status(pgmn_dev->base);
 
 	JPEG_DBG("%s:%d] jpeg_irq_status = %0x\n", __func__, __LINE__,
 		jpeg_irq_status);
@@ -171,18 +198,26 @@
 	/*For reset and framedone IRQs, clear all bits*/
 	if (jpeg_irq_status & 0x10000000) {
 		msm_jpeg_hw_irq_clear(JPEG_IRQ_CLEAR_BMSK,
-			JPEG_IRQ_CLEAR_ALL);
+			JPEG_IRQ_CLEAR_ALL, pgmn_dev->base);
 	} else if (jpeg_irq_status & 0x1) {
 		msm_jpeg_hw_irq_clear(JPEG_IRQ_CLEAR_BMSK,
-			JPEG_IRQ_CLEAR_ALL);
+			JPEG_IRQ_CLEAR_ALL, pgmn_dev->base);
+		if (pgmn_dev->decode_flag)
+			msm_jpeg_decode_status(pgmn_dev->base);
 	} else {
 		msm_jpeg_hw_irq_clear(JPEG_IRQ_CLEAR_BMSK,
-			jpeg_irq_status);
+			jpeg_irq_status, pgmn_dev->base);
 	}
 
 	if (msm_jpeg_hw_irq_is_frame_done(jpeg_irq_status)) {
+		/* send fe ping pong irq */
+		data = msm_jpeg_core_fe_pingpong_irq(jpeg_irq_status,
+			pgmn_dev);
+		if (msm_jpeg_irq_handler)
+			msm_jpeg_irq_handler(MSM_JPEG_HW_MASK_COMP_FE,
+				context, data);
 		data = msm_jpeg_core_framedone_irq(jpeg_irq_status,
-			context);
+			pgmn_dev);
 		if (msm_jpeg_irq_handler)
 			msm_jpeg_irq_handler(
 				MSM_JPEG_HW_MASK_COMP_FRAMEDONE,
@@ -190,11 +225,11 @@
 	}
 	if (msm_jpeg_hw_irq_is_reset_ack(jpeg_irq_status)) {
 		data = msm_jpeg_core_reset_ack_irq(jpeg_irq_status,
-			context);
-		spin_lock_irqsave(&reset_lock, flags);
-		reset_done_ack = 1;
-		spin_unlock_irqrestore(&reset_lock, flags);
-		wake_up(&reset_wait);
+			pgmn_dev);
+		spin_lock_irqsave(&pgmn_dev->reset_lock, flags);
+		pgmn_dev->reset_done_ack = 1;
+		spin_unlock_irqrestore(&pgmn_dev->reset_lock, flags);
+		wake_up(&pgmn_dev->reset_wait);
 		if (msm_jpeg_irq_handler)
 			msm_jpeg_irq_handler(
 				MSM_JPEG_HW_MASK_COMP_RESET_ACK,
@@ -203,7 +238,10 @@
 
 	/* Unexpected/unintended HW interrupt */
 	if (msm_jpeg_hw_irq_is_err(jpeg_irq_status)) {
-		data = msm_jpeg_core_err_irq(jpeg_irq_status, context);
+		if (pgmn_dev->decode_flag)
+			msm_jpeg_decode_status(pgmn_dev->base);
+		msm_jpeg_core_return_buffers(pgmn_dev, jpeg_irq_status);
+		data = msm_jpeg_core_err_irq(jpeg_irq_status, pgmn_dev);
 		if (msm_jpeg_irq_handler)
 			msm_jpeg_irq_handler(MSM_JPEG_HW_MASK_COMP_ERR,
 				context, data);
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_core.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_core.h
index b5c725c..212eaff 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_core.h
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_core.h
@@ -15,6 +15,7 @@
 
 #include <linux/interrupt.h>
 #include "msm_jpeg_hw.h"
+#include "msm_jpeg_sync.h"
 
 #define msm_jpeg_core_buf msm_jpeg_hw_buf
 
@@ -23,13 +24,17 @@
 void msm_jpeg_core_irq_install(int (*irq_handler) (int, void *, void *));
 void msm_jpeg_core_irq_remove(void);
 
-int msm_jpeg_core_fe_buf_update(struct msm_jpeg_core_buf *buf);
-int msm_jpeg_core_we_buf_update(struct msm_jpeg_core_buf *buf);
-int msm_jpeg_core_we_buf_reset(struct msm_jpeg_hw_buf *buf);
+int msm_jpeg_core_fe_buf_update(struct msm_jpeg_device *pgmn_dev,
+	struct msm_jpeg_core_buf *buf);
+int msm_jpeg_core_we_buf_update(struct msm_jpeg_device *pgmn_dev,
+	struct msm_jpeg_core_buf *buf);
+int msm_jpeg_core_we_buf_reset(struct msm_jpeg_device *pgmn_dev,
+	struct msm_jpeg_hw_buf *buf);
 
-int msm_jpeg_core_reset(uint8_t op_mode, void *base, int size);
-int msm_jpeg_core_fe_start(void);
+int msm_jpeg_core_reset(struct msm_jpeg_device *pgmn_dev, uint8_t op_mode,
+	void *base, int size);
+int msm_jpeg_core_fe_start(struct msm_jpeg_device *);
 
-void msm_jpeg_core_release(int, int);
-void msm_jpeg_core_init(void);
+void msm_jpeg_core_release(struct msm_jpeg_device *, int);
+void msm_jpeg_core_init(struct msm_jpeg_device *);
 #endif /* MSM_JPEG_CORE_H */
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_dev.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_dev.c
index 45a9a38..0662f54 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_dev.c
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_dev.c
@@ -31,9 +31,7 @@
 #include "msm_jpeg_common.h"
 
 #define MSM_JPEG_NAME "jpeg"
-#define MSM_JPEGE1_NAME "jpege1"
-#define MSM_JPEGD_NAME "jpegd"
-
+#define DEV_NAME_LEN 10
 
 static int msm_jpeg_open(struct inode *inode, struct file *filp)
 {
@@ -146,7 +144,7 @@
 	int rc = -1;
 	struct device *dev;
 	struct msm_jpeg_device *msm_jpeg_device_p;
-	char devname[10];
+	char devname[DEV_NAME_LEN];
 
 	msm_jpeg_device_p = kzalloc(sizeof(struct msm_jpeg_device), GFP_ATOMIC);
 	if (!msm_jpeg_device_p) {
@@ -158,7 +156,7 @@
 
 	if (pdev->dev.of_node)
 		of_property_read_u32((&pdev->dev)->of_node, "cell-index",
-								&pdev->id);
+			&pdev->id);
 
 	snprintf(devname, sizeof(devname), "%s%d", MSM_JPEG_NAME, pdev->id);
 
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.c
index 0bfb6a8..e311e4c 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.c
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.c
@@ -17,11 +17,8 @@
 
 #include <linux/io.h>
 
-static void *jpeg_region_base;
-static uint32_t jpeg_region_size;
-
 int msm_jpeg_hw_pingpong_update(struct msm_jpeg_hw_pingpong *pingpong_hw,
-	struct msm_jpeg_hw_buf *buf)
+	struct msm_jpeg_hw_buf *buf, void *base)
 {
 	int buf_free_index = -1;
 
@@ -41,11 +38,13 @@
 	if (pingpong_hw->is_fe) {
 		/* it is fe */
 		msm_jpeg_hw_fe_buffer_update(
-			&pingpong_hw->buf[buf_free_index], buf_free_index);
+			&pingpong_hw->buf[buf_free_index], buf_free_index,
+			base);
 	} else {
 		/* it is we */
 		msm_jpeg_hw_we_buffer_update(
-			&pingpong_hw->buf[buf_free_index], buf_free_index);
+			&pingpong_hw->buf[buf_free_index], buf_free_index,
+			base);
 	}
 	return 0;
 }
@@ -81,12 +80,10 @@
 		JPEG_IRQ_STATUS_BMSK, {0} },
 };
 
-int msm_jpeg_hw_irq_get_status(void)
+int msm_jpeg_hw_irq_get_status(void *base)
 {
 	uint32_t n_irq_status = 0;
-	rmb();
-	n_irq_status = msm_jpeg_hw_read(&hw_cmd_irq_get_status[0]);
-	rmb();
+	n_irq_status = msm_jpeg_hw_read(&hw_cmd_irq_get_status[0], base);
 	return n_irq_status;
 }
 
@@ -97,11 +94,12 @@
 	JPEG_ENCODE_OUTPUT_SIZE_STATUS_BMSK, {0} } ,
 };
 
-long msm_jpeg_hw_encode_output_size(void)
+long msm_jpeg_hw_encode_output_size(void *base)
 {
 	uint32_t encode_output_size = 0;
 
-	encode_output_size = msm_jpeg_hw_read(&hw_cmd_encode_output_size[0]);
+	encode_output_size = msm_jpeg_hw_read(&hw_cmd_encode_output_size[0],
+		base);
 
 	return encode_output_size;
 }
@@ -112,12 +110,12 @@
 		JPEG_IRQ_CLEAR_BMSK, {JPEG_IRQ_CLEAR_ALL} },
 };
 
-void msm_jpeg_hw_irq_clear(uint32_t mask, uint32_t data)
+void msm_jpeg_hw_irq_clear(uint32_t mask, uint32_t data, void *base)
 {
 	JPEG_DBG("%s:%d] mask %0x data %0x", __func__, __LINE__, mask, data);
 	hw_cmd_irq_clear[0].mask = mask;
 	hw_cmd_irq_clear[0].data = data;
-	msm_jpeg_hw_write(&hw_cmd_irq_clear[0]);
+	msm_jpeg_hw_write(&hw_cmd_irq_clear[0], base);
 }
 
 struct msm_jpeg_hw_cmd hw_cmd_fe_ping_update[] = {
@@ -137,26 +135,26 @@
 };
 
 void msm_jpeg_hw_fe_buffer_update(struct msm_jpeg_hw_buf *p_input,
-	uint8_t pingpong_index)
+	uint8_t pingpong_index, void *base)
 {
 	struct msm_jpeg_hw_cmd *hw_cmd_p;
 
 	if (pingpong_index == 0) {
 		hw_cmd_p = &hw_cmd_fe_ping_update[0];
 		wmb();
-		msm_jpeg_hw_write(hw_cmd_p++);
+		msm_jpeg_hw_write(hw_cmd_p++, base);
 		wmb();
-		msm_jpeg_hw_write(hw_cmd_p++);
+		msm_jpeg_hw_write(hw_cmd_p++, base);
 		wmb();
-		msm_jpeg_hw_write(hw_cmd_p++);
+		msm_jpeg_hw_write(hw_cmd_p++, base);
 		wmb();
 		hw_cmd_p->data = p_input->y_buffer_addr;
-		msm_jpeg_hw_write(hw_cmd_p++);
+		msm_jpeg_hw_write(hw_cmd_p++, base);
 		wmb();
-		msm_jpeg_hw_write(hw_cmd_p++);
+		msm_jpeg_hw_write(hw_cmd_p++, base);
 		wmb();
 		hw_cmd_p->data = p_input->cbcr_buffer_addr;
-		msm_jpeg_hw_write(hw_cmd_p++);
+		msm_jpeg_hw_write(hw_cmd_p++, base);
 		wmb();
 
 	}
@@ -169,9 +167,9 @@
 		JPEG_CMD_BMSK, {JPEG_OFFLINE_CMD_START} },
 };
 
-void msm_jpeg_hw_fe_start(void)
+void msm_jpeg_hw_fe_start(void *base)
 {
-	msm_jpeg_hw_write(&hw_cmd_fe_start[0]);
+	msm_jpeg_hw_write(&hw_cmd_fe_start[0], base);
 
 	return;
 }
@@ -180,20 +178,46 @@
 	/* type, repeat n times, offset, mask, data or pdata */
 	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN0_WR_PNTR_ADDR,
 		JPEG_PLN0_WR_PNTR_BMSK, {0} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN1_WR_PNTR_ADDR,
+		JPEG_PLN0_WR_PNTR_BMSK, {0} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN2_WR_PNTR_ADDR,
+		JPEG_PLN0_WR_PNTR_BMSK, {0} },
 };
 
+void msm_jpeg_decode_status(void *base)
+{
+	uint32_t data;
+	data = readl_relaxed(base + JPEG_DECODE_MCUS_DECODED_STATUS);
+	JPEG_DBG_HIGH("Decode MCUs decode status %u", data);
+	data = readl_relaxed(base + JPEG_DECODE_BITS_CONSUMED_STATUS);
+	JPEG_DBG_HIGH("Decode bits consumed status %u", data);
+	data = readl_relaxed(base + JPEG_DECODE_PRED_Y_STATE);
+	JPEG_DBG_HIGH("Decode prediction Y state %u", data);
+	data = readl_relaxed(base + JPEG_DECODE_PRED_C_STATE);
+	JPEG_DBG_HIGH("Decode prediction C state %u", data);
+	data = readl_relaxed(base + JPEG_DECODE_RSM_STATE);
+	JPEG_DBG_HIGH("Decode prediction RSM state %u", data);
+}
+
+
 void msm_jpeg_hw_we_buffer_update(struct msm_jpeg_hw_buf *p_input,
-	uint8_t pingpong_index)
+	uint8_t pingpong_index, void *base)
 {
 	struct msm_jpeg_hw_cmd *hw_cmd_p;
 
 	if (pingpong_index == 0) {
 		hw_cmd_p = &hw_cmd_we_ping_update[0];
 		hw_cmd_p->data = p_input->y_buffer_addr;
-		JPEG_PR_ERR("%s Output buffer address is %x\n", __func__,
-						p_input->y_buffer_addr);
-		msm_jpeg_hw_write(hw_cmd_p++);
-
+		JPEG_PR_ERR("%s Output pln0 buffer address is %x\n", __func__,
+			p_input->y_buffer_addr);
+		msm_jpeg_hw_write(hw_cmd_p++, base);
+		hw_cmd_p->data = p_input->cbcr_buffer_addr;
+		JPEG_PR_ERR("%s Output pln1 buffer address is %x\n", __func__,
+			p_input->cbcr_buffer_addr);
+		msm_jpeg_hw_write(hw_cmd_p++, base);
+		JPEG_PR_ERR("%s Output pln2 buffer address is %x\n", __func__,
+			p_input->pln2_addr);
+		msm_jpeg_hw_write(hw_cmd_p++, base);
 	}
 	return;
 }
@@ -210,31 +234,26 @@
 		JPEG_RESET_CMD_RMSK, {JPEG_RESET_DEFAULT} },
 };
 
-void msm_jpeg_hw_init(void *base, int size)
-{
-	jpeg_region_base = base;
-	jpeg_region_size = size;
-}
-
 void msm_jpeg_hw_reset(void *base, int size)
 {
 	struct msm_jpeg_hw_cmd *hw_cmd_p;
 
 	hw_cmd_p = &hw_cmd_reset[0];
 	wmb();
-	msm_jpeg_hw_write(hw_cmd_p++);
+	msm_jpeg_hw_write(hw_cmd_p++, base);
 	wmb();
-	msm_jpeg_hw_write(hw_cmd_p++);
+	msm_jpeg_hw_write(hw_cmd_p++, base);
 	wmb();
-	msm_jpeg_hw_write(hw_cmd_p++);
+	msm_jpeg_hw_write(hw_cmd_p++, base);
 	wmb();
-	msm_jpeg_hw_write(hw_cmd_p);
+	msm_jpeg_hw_write(hw_cmd_p, base);
 	wmb();
 
 	return;
 }
 
-uint32_t msm_jpeg_hw_read(struct msm_jpeg_hw_cmd *hw_cmd_p)
+uint32_t msm_jpeg_hw_read(struct msm_jpeg_hw_cmd *hw_cmd_p,
+	 void *jpeg_region_base)
 {
 	uint32_t *paddr;
 	uint32_t data;
@@ -247,7 +266,8 @@
 	return data;
 }
 
-void msm_jpeg_hw_write(struct msm_jpeg_hw_cmd *hw_cmd_p)
+void msm_jpeg_hw_write(struct msm_jpeg_hw_cmd *hw_cmd_p,
+	void *jpeg_region_base)
 {
 	uint32_t *paddr;
 	uint32_t old_data, new_data;
@@ -266,17 +286,18 @@
 	writel_relaxed(new_data, paddr);
 }
 
-int msm_jpeg_hw_wait(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us)
+int msm_jpeg_hw_wait(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us,
+	void *base)
 {
 	int tm = hw_cmd_p->n;
 	uint32_t data;
 	uint32_t wait_data = hw_cmd_p->data & hw_cmd_p->mask;
 
-	data = msm_jpeg_hw_read(hw_cmd_p);
+	data = msm_jpeg_hw_read(hw_cmd_p, base);
 	if (data != wait_data) {
 		while (tm) {
 			udelay(m_us);
-			data = msm_jpeg_hw_read(hw_cmd_p);
+			data = msm_jpeg_hw_read(hw_cmd_p, base);
 			if (data == wait_data)
 				break;
 			tm--;
@@ -295,41 +316,42 @@
 	}
 }
 
-int msm_jpeg_hw_exec_cmds(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_cmds)
+int msm_jpeg_hw_exec_cmds(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_cmds,
+	uint32_t max_size, void *base)
 {
 	int is_copy_to_user = -1;
 	uint32_t data;
 
 	while (m_cmds--) {
-		if (hw_cmd_p->offset > jpeg_region_size) {
+		if (hw_cmd_p->offset > max_size) {
 			JPEG_PR_ERR("%s:%d] %d exceed hw region %d\n", __func__,
-				__LINE__, hw_cmd_p->offset, jpeg_region_size);
+				__LINE__, hw_cmd_p->offset, max_size);
 			return -EFAULT;
 		}
 
 		switch (hw_cmd_p->type) {
 		case MSM_JPEG_HW_CMD_TYPE_READ:
-			hw_cmd_p->data = msm_jpeg_hw_read(hw_cmd_p);
+			hw_cmd_p->data = msm_jpeg_hw_read(hw_cmd_p, base);
 			is_copy_to_user = 1;
 			break;
 
 		case MSM_JPEG_HW_CMD_TYPE_WRITE:
-			msm_jpeg_hw_write(hw_cmd_p);
+			msm_jpeg_hw_write(hw_cmd_p, base);
 			break;
 
 		case MSM_JPEG_HW_CMD_TYPE_WRITE_OR:
-			data = msm_jpeg_hw_read(hw_cmd_p);
+			data = msm_jpeg_hw_read(hw_cmd_p, base);
 			hw_cmd_p->data = (hw_cmd_p->data & hw_cmd_p->mask) |
 				data;
-			msm_jpeg_hw_write(hw_cmd_p);
+			msm_jpeg_hw_write(hw_cmd_p, base);
 			break;
 
 		case MSM_JPEG_HW_CMD_TYPE_UWAIT:
-			msm_jpeg_hw_wait(hw_cmd_p, 1);
+			msm_jpeg_hw_wait(hw_cmd_p, 1, base);
 			break;
 
 		case MSM_JPEG_HW_CMD_TYPE_MWAIT:
-			msm_jpeg_hw_wait(hw_cmd_p, 1000);
+			msm_jpeg_hw_wait(hw_cmd_p, 1000, base);
 			break;
 
 		case MSM_JPEG_HW_CMD_TYPE_UDELAY:
@@ -350,15 +372,14 @@
 	return is_copy_to_user;
 }
 
-void msm_jpeg_io_dump(int size)
+void msm_jpeg_io_dump(void *base, int size)
 {
 	char line_str[128], *p_str;
-	void __iomem *addr = jpeg_region_base;
+	void __iomem *addr = (void __iomem *)base;
 	int i;
 	u32 *p = (u32 *) addr;
 	u32 data;
-	JPEG_PR_ERR("%s: %p %d reg_size %d\n", __func__, addr, size,
-							jpeg_region_size);
+	JPEG_DBG_HIGH("%s:%d] %p %d", __func__, __LINE__, addr, size);
 	line_str[0] = '\0';
 	p_str = line_str;
 	for (i = 0; i < size/4; i++) {
@@ -370,11 +391,12 @@
 		snprintf(p_str, 12, "%08x ", data);
 		p_str += 9;
 		if ((i + 1) % 4 == 0) {
-			JPEG_PR_ERR("%s\n", line_str);
+			JPEG_DBG_HIGH("%s\n", line_str);
 			line_str[0] = '\0';
 			p_str = line_str;
 		}
 	}
 	if (line_str[0] != '\0')
-		JPEG_PR_ERR("%s\n", line_str);
+		JPEG_DBG_HIGH("%s\n", line_str);
 }
+
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.h
index 73a0e27..e90b941 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.h
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.h
@@ -28,6 +28,8 @@
 	uint32_t cbcr_len;
 	uint32_t num_of_mcu_rows;
 	struct ion_handle *handle;
+	uint32_t pln2_addr;
+	uint32_t pln2_offset;
 };
 
 struct msm_jpeg_hw_pingpong {
@@ -38,14 +40,14 @@
 };
 
 int msm_jpeg_hw_pingpong_update(struct msm_jpeg_hw_pingpong *pingpong_hw,
-	struct msm_jpeg_hw_buf *buf);
+	struct msm_jpeg_hw_buf *buf, void *);
 void *msm_jpeg_hw_pingpong_irq(struct msm_jpeg_hw_pingpong *pingpong_hw);
 void *msm_jpeg_hw_pingpong_active_buffer(struct msm_jpeg_hw_pingpong
 	*pingpong_hw);
 
-void msm_jpeg_hw_irq_clear(uint32_t, uint32_t);
-int msm_jpeg_hw_irq_get_status(void);
-long msm_jpeg_hw_encode_output_size(void);
+void msm_jpeg_hw_irq_clear(uint32_t, uint32_t, void *);
+int msm_jpeg_hw_irq_get_status(void *);
+long msm_jpeg_hw_encode_output_size(void *);
 #define MSM_JPEG_HW_MASK_COMP_FRAMEDONE \
 		MSM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK
 #define MSM_JPEG_HW_MASK_COMP_FE \
@@ -56,13 +58,14 @@
 #define MSM_JPEG_HW_MASK_COMP_RESET_ACK \
 		MSM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK
 #define MSM_JPEG_HW_MASK_COMP_ERR \
-		(MSM_JPEG_HW_IRQ_STATUS_FE_RTOVF_MASK | \
-		MSM_JPEG_HW_IRQ_STATUS_FE_VFE_OVERFLOW_MASK | \
-		MSM_JPEG_HW_IRQ_STATUS_WE_Y_BUFFER_OVERFLOW_MASK | \
-		MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_BUFFER_OVERFLOW_MASK | \
-		MSM_JPEG_HW_IRQ_STATUS_WE_CH0_DATAFIFO_OVERFLOW_MASK | \
-		MSM_JPEG_HW_IRQ_STATUS_WE_CH1_DATAFIFO_OVERFLOW_MASK | \
-		MSM_JPEG_HW_IRQ_STATUS_BUS_ERROR_MASK | \
+		(MSM_JPEG_HW_IRQ_STATUS_DCD_UNESCAPED_FF | \
+		MSM_JPEG_HW_IRQ_STATUS_DCD_HUFFMAN_ERROR | \
+		MSM_JPEG_HW_IRQ_STATUS_DCD_COEFFICIENT_ERR | \
+		MSM_JPEG_HW_IRQ_STATUS_DCD_MISSING_BIT_STUFF | \
+		MSM_JPEG_HW_IRQ_STATUS_DCD_SCAN_UNDERFLOW | \
+		MSM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM | \
+		MSM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM_SEQ | \
+		MSM_JPEG_HW_IRQ_STATUS_DCD_MISSING_RSM | \
 		MSM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK)
 
 #define msm_jpeg_hw_irq_is_frame_done(jpeg_irq_status) \
@@ -77,25 +80,26 @@
 	(jpeg_irq_status & MSM_JPEG_HW_MASK_COMP_ERR)
 
 void msm_jpeg_hw_fe_buffer_update(struct msm_jpeg_hw_buf *p_input,
-	uint8_t pingpong_index);
+	uint8_t pingpong_index, void *);
 void msm_jpeg_hw_we_buffer_update(struct msm_jpeg_hw_buf *p_input,
-	uint8_t pingpong_index);
+	uint8_t pingpong_index, void *);
 
 void msm_jpeg_hw_we_buffer_cfg(uint8_t is_realtime);
 
-void msm_jpeg_hw_fe_start(void);
+void msm_jpeg_hw_fe_start(void *);
 void msm_jpeg_hw_clk_cfg(void);
 
 void msm_jpeg_hw_reset(void *base, int size);
 void msm_jpeg_hw_irq_cfg(void);
-void msm_jpeg_hw_init(void *base, int size);
 
-uint32_t msm_jpeg_hw_read(struct msm_jpeg_hw_cmd *hw_cmd_p);
-void msm_jpeg_hw_write(struct msm_jpeg_hw_cmd *hw_cmd_p);
-int msm_jpeg_hw_wait(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us);
-void msm_jpeg_hw_delay(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us);
-int msm_jpeg_hw_exec_cmds(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_cmds);
+uint32_t msm_jpeg_hw_read(struct msm_jpeg_hw_cmd *, void *);
+void msm_jpeg_hw_write(struct msm_jpeg_hw_cmd *, void *);
+int msm_jpeg_hw_wait(struct msm_jpeg_hw_cmd *, int, void *);
+void msm_jpeg_hw_delay(struct msm_jpeg_hw_cmd *, int);
+int msm_jpeg_hw_exec_cmds(struct msm_jpeg_hw_cmd *, int ,
+	uint32_t , void *);
 void msm_jpeg_hw_region_dump(int size);
-void msm_jpeg_io_dump(int size);
+void msm_jpeg_io_dump(void *base, int size);
+void msm_jpeg_decode_status(void *base);
 
 #endif /* MSM_JPEG_HW_H */
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw_reg.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw_reg.h
index ae64c32..928d59e 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw_reg.h
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw_reg.h
@@ -37,30 +37,25 @@
 #define MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_PINGPONG_MASK 0x00000020
 #define MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_PINGPONG_SHIFT 0x00000005
 
-#define MSM_JPEG_HW_IRQ_STATUS_WE_Y_BUFFER_OVERFLOW_MASK 0x00000040
-#define MSM_JPEG_HW_IRQ_STATUS_WE_Y_BUFFER_OVERFLOW_SHIFT 0x00000006
-
-#define MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_BUFFER_OVERFLOW_MASK 0x00000080
-#define MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_BUFFER_OVERFLOW_SHIFT 0x00000007
-
-#define MSM_JPEG_HW_IRQ_STATUS_WE_CH0_DATAFIFO_OVERFLOW_MASK 0x00000100
-#define MSM_JPEG_HW_IRQ_STATUS_WE_CH0_DATAFIFO_OVERFLOW_SHIFT 0x00000008
-
-#define MSM_JPEG_HW_IRQ_STATUS_WE_CH1_DATAFIFO_OVERFLOW_MASK 0x00000200
-#define MSM_JPEG_HW_IRQ_STATUS_WE_CH1_DATAFIFO_OVERFLOW_SHIFT 0x00000009
-
 #define MSM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK 0x10000000
 #define MSM_JPEG_HW_IRQ_STATUS_RESET_ACK_SHIFT 0x0000000a
 
 #define MSM_JPEG_HW_IRQ_STATUS_BUS_ERROR_MASK 0x00000800
 #define MSM_JPEG_HW_IRQ_STATUS_BUS_ERROR_SHIFT 0x0000000b
 
-#define MSM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK 0x00001000
-#define MSM_JPEG_HW_IRQ_STATUS_VIOLATION_SHIFT 0x0000000c
+#define MSM_JPEG_HW_IRQ_STATUS_DCD_UNESCAPED_FF      (0x1<<19)
+#define MSM_JPEG_HW_IRQ_STATUS_DCD_HUFFMAN_ERROR     (0x1<<20)
+#define MSM_JPEG_HW_IRQ_STATUS_DCD_COEFFICIENT_ERR   (0x1<<21)
+#define MSM_JPEG_HW_IRQ_STATUS_DCD_MISSING_BIT_STUFF (0x1<<22)
+#define MSM_JPEG_HW_IRQ_STATUS_DCD_SCAN_UNDERFLOW    (0x1<<23)
+#define MSM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM       (0x1<<24)
+#define MSM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM_SEQ   (0x1<<25)
+#define MSM_JPEG_HW_IRQ_STATUS_DCD_MISSING_RSM       (0x1<<26)
+#define MSM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK        (0x1<<29)
 
 #define JPEG_OFFLINE_CMD_START 0x00000001
 
-#define JPEG_RESET_DEFAULT 0x00000003 /* cfff? */
+#define JPEG_RESET_DEFAULT 0x00020000
 
 #define JPEG_IRQ_DISABLE_ALL 0x00000000
 #define JPEG_IRQ_CLEAR_ALL 0xFFFFFFFF
@@ -87,6 +82,9 @@
 #define JPEG_PLN1_WR_PNTR_ADDR (JPEG_REG_BASE + 0x000000D0)
 #define JPEG_PLN1_WR_PNTR_BMSK 0xFFFFFFFF
 
+#define JPEG_PLN2_WR_PNTR_ADDR (JPEG_REG_BASE + 0x000000D4)
+#define JPEG_PLN2_WR_PNTR_BMSK 0xFFFFFFFF
+
 #define JPEG_IRQ_MASK_ADDR (JPEG_REG_BASE + 0x00000018)
 #define JPEG_IRQ_MASK_BMSK 0xFFFFFFFF
 #define JPEG_IRQ_ALLSOURCES_ENABLE 0xFFFFFFFF
@@ -103,6 +101,11 @@
 #define JPEG_ENCODE_OUTPUT_SIZE_STATUS_ADDR (JPEG_REG_BASE + 0x00000180)
 #define JPEG_ENCODE_OUTPUT_SIZE_STATUS_BMSK 0x1FFFFFFF
 
+#define JPEG_DECODE_MCUS_DECODED_STATUS   (JPEG_REG_BASE + 0x00000258)
+#define JPEG_DECODE_BITS_CONSUMED_STATUS  (JPEG_REG_BASE + 0x0000025C)
+#define JPEG_DECODE_PRED_Y_STATE          (JPEG_REG_BASE + 0x00000260)
+#define JPEG_DECODE_PRED_C_STATE          (JPEG_REG_BASE + 0x00000264)
+#define JPEG_DECODE_RSM_STATE             (JPEG_REG_BASE + 0x00000268)
 
 #define VBIF_BASE_ADDRESS                      0xFDA60000
 #define VBIF_REGION_SIZE                       0xC30
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c
index 981c56c..0370f63 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c
@@ -26,36 +26,32 @@
 #include "msm_jpeg_common.h"
 #include "msm_jpeg_hw.h"
 
-/* AXI rate in KHz */
-struct ion_client *jpeg_client;
-static void *jpeg_vbif;
-
-void msm_jpeg_platform_p2v(struct file  *file,
-				struct ion_handle **ionhandle, int domain_num)
+void msm_jpeg_platform_p2v(struct msm_jpeg_device *pgmn_dev, struct file  *file,
+	struct ion_handle **ionhandle, int domain_num)
 {
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	ion_unmap_iommu(jpeg_client, *ionhandle, domain_num, 0);
-	ion_free(jpeg_client, *ionhandle);
+	ion_unmap_iommu(pgmn_dev->jpeg_client, *ionhandle, domain_num, 0);
+	ion_free(pgmn_dev->jpeg_client, *ionhandle);
 	*ionhandle = NULL;
 #elif CONFIG_ANDROID_PMEM
 	put_pmem_file(file);
 #endif
 }
 
-uint32_t msm_jpeg_platform_v2p(int fd, uint32_t len, struct file **file_p,
-				struct ion_handle **ionhandle, int domain_num)
-{
+uint32_t msm_jpeg_platform_v2p(struct msm_jpeg_device *pgmn_dev, int fd,
+	uint32_t len, struct file **file_p, struct ion_handle **ionhandle,
+	int domain_num) {
 	unsigned long paddr;
 	unsigned long size;
 	int rc;
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	*ionhandle = ion_import_dma_buf(jpeg_client, fd);
+	*ionhandle = ion_import_dma_buf(pgmn_dev->jpeg_client, fd);
 	if (IS_ERR_OR_NULL(*ionhandle))
 		return 0;
 
-	rc = ion_map_iommu(jpeg_client, *ionhandle, domain_num, 0,
-			 SZ_4K, 0, &paddr, (unsigned long *)&size, UNCACHED, 0);
-	JPEG_DBG("%s:%d] addr 0x%x size %ld", __func__, __LINE__,
+	rc = ion_map_iommu(pgmn_dev->jpeg_client, *ionhandle, domain_num, 0,
+		SZ_4K, 0, &paddr, (unsigned long *)&size, UNCACHED,
+0); JPEG_DBG("%s:%d] addr 0x%x size %ld", __func__, __LINE__,
 							(uint32_t)paddr, size);
 
 #elif CONFIG_ANDROID_PMEM
@@ -81,7 +77,7 @@
 	return paddr;
 error1:
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	ion_free(jpeg_client, *ionhandle);
+	ion_free(pgmn_dev->jpeg_client, *ionhandle);
 #endif
 	return 0;
 }
@@ -149,10 +145,10 @@
 	}
 	jpeg_irq = jpeg_irq_res->start;
 	JPEG_DBG("%s base address: 0x%x, jpeg irq number: %d\n", __func__,
-						jpeg_mem->start, jpeg_irq);
+		jpeg_mem->start, jpeg_irq);
 
 	jpeg_io = request_mem_region(jpeg_mem->start,
-					resource_size(jpeg_mem), pdev->name);
+		resource_size(jpeg_mem), pdev->name);
 	if (!jpeg_io) {
 		JPEG_PR_ERR("%s: region already claimed\n", __func__);
 		return -EBUSY;
@@ -165,14 +161,14 @@
 		goto fail1;
 	}
 
-	jpeg_vbif = ioremap(VBIF_BASE_ADDRESS, VBIF_REGION_SIZE);
-	if (!jpeg_vbif) {
+	pgmn_dev->jpeg_vbif = ioremap(VBIF_BASE_ADDRESS, VBIF_REGION_SIZE);
+	if (!pgmn_dev->jpeg_vbif) {
 		rc = -ENOMEM;
 		JPEG_PR_ERR("%s:%d] ioremap failed\n", __func__, __LINE__);
 		goto fail1;
 	}
 	JPEG_DBG("%s:%d] jpeg_vbif 0x%x", __func__, __LINE__,
-						(uint32_t)jpeg_vbif);
+		(uint32_t)pgmn_dev->jpeg_vbif);
 
 	pgmn_dev->jpeg_fs = regulator_get(&pgmn_dev->pdev->dev, "vdd");
 	rc = regulator_enable(pgmn_dev->jpeg_fs);
@@ -202,9 +198,8 @@
 					(uint32_t)pgmn_dev->iommu_ctx_arr[i]);
 	}
 #endif
-	set_vbif_params(jpeg_vbif);
+	set_vbif_params(pgmn_dev->jpeg_vbif);
 
-	msm_jpeg_hw_init(jpeg_base, resource_size(jpeg_mem));
 	rc = request_irq(jpeg_irq, handler, IRQF_TRIGGER_RISING, "jpeg",
 		context);
 	if (rc) {
@@ -218,7 +213,7 @@
 	*irq  = jpeg_irq;
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	jpeg_client = msm_ion_client_create(-1, "camera/jpeg");
+	pgmn_dev->jpeg_client = msm_ion_client_create(-1, "camera/jpeg");
 #endif
 	JPEG_DBG("%s:%d] success\n", __func__, __LINE__);
 
@@ -276,11 +271,11 @@
 		regulator_disable(pgmn_dev->jpeg_fs);
 		pgmn_dev->jpeg_fs = NULL;
 	}
-	iounmap(jpeg_vbif);
+	iounmap(pgmn_dev->jpeg_vbif);
 	iounmap(base);
 	release_mem_region(mem->start, resource_size(mem));
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	ion_client_destroy(jpeg_client);
+	ion_client_destroy(pgmn_dev->jpeg_client);
 #endif
 	JPEG_DBG("%s:%d] success\n", __func__, __LINE__);
 	return result;
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.h
index 8a37cef..cd80d2e 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.h
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.h
@@ -18,12 +18,13 @@
 #include <linux/ion.h>
 #include <linux/iommu.h>
 #include <mach/iommu.h>
+#include "msm_jpeg_sync.h"
 
-
-void msm_jpeg_platform_p2v(struct file  *file,
-				struct ion_handle **ionhandle, int domain_num);
-uint32_t msm_jpeg_platform_v2p(int fd, uint32_t len, struct file **file,
-				struct ion_handle **ionhandle, int domain_num);
+void msm_jpeg_platform_p2v(struct msm_jpeg_device *pgmn_dev, struct file *file,
+	struct ion_handle **ionhandle, int domain_num);
+uint32_t msm_jpeg_platform_v2p(struct msm_jpeg_device *pgmn_dev, int fd,
+	uint32_t len, struct file **file, struct ion_handle **ionhandle,
+	int domain_num);
 
 int msm_jpeg_platform_clk_enable(void);
 int msm_jpeg_platform_clk_disable(void);
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.c
index 6ac4a5e..a0aaf03 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.c
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.c
@@ -22,7 +22,9 @@
 #include "msm_jpeg_platform.h"
 #include "msm_jpeg_common.h"
 
-static int release_buf;
+#define JPEG_REG_SIZE 0x308
+#define JPEG_DEV_CNT 3
+#define JPEG_DEC_ID 2
 
 inline void msm_jpeg_q_init(char const *name, struct msm_jpeg_q *q_p)
 {
@@ -143,15 +145,15 @@
 	return 0;
 }
 
-inline void msm_jpeg_outbuf_q_cleanup(struct msm_jpeg_q *q_p,
-				int domain_num)
+inline void msm_jpeg_outbuf_q_cleanup(struct msm_jpeg_device *pgmn_dev,
+	struct msm_jpeg_q *q_p, int domain_num)
 {
 	struct msm_jpeg_core_buf *buf_p;
 	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
 	do {
 		buf_p = msm_jpeg_q_out(q_p);
 		if (buf_p) {
-			msm_jpeg_platform_p2v(buf_p->file,
+			msm_jpeg_platform_p2v(pgmn_dev, buf_p->file,
 				&buf_p->handle, domain_num);
 			JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
 			kfree(buf_p);
@@ -289,10 +291,10 @@
 	if (buf_out) {
 		JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
 			(int) buf_out->y_buffer_addr, buf_out->y_len);
-		rc = msm_jpeg_core_we_buf_update(buf_out);
+		rc = msm_jpeg_core_we_buf_update(pgmn_dev, buf_out);
 		kfree(buf_out);
 	} else {
-		msm_jpeg_core_we_buf_reset(buf_in);
+		msm_jpeg_core_we_buf_reset(pgmn_dev, buf_in);
 		JPEG_DBG("%s:%d] no output buffer\n", __func__, __LINE__);
 		rc = -2;
 	}
@@ -320,7 +322,7 @@
 	}
 
 	buf_cmd = buf_p->vbuf;
-	msm_jpeg_platform_p2v(buf_p->file, &buf_p->handle,
+	msm_jpeg_platform_p2v(pgmn_dev, buf_p->file, &buf_p->handle,
 		pgmn_dev->domain_num);
 	kfree(buf_p);
 
@@ -347,6 +349,7 @@
 {
 	struct msm_jpeg_buf buf_cmd;
 	struct msm_jpeg_core_buf *buf_p;
+	memset(&buf_cmd, 0x0, sizeof(struct msm_jpeg_buf));
 
 	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
 	if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_jpeg_buf))) {
@@ -364,7 +367,7 @@
 		__func__, __LINE__, (int) buf_cmd.vaddr, buf_cmd.y_len,
 		buf_cmd.fd);
 
-	buf_p->y_buffer_addr = msm_jpeg_platform_v2p(buf_cmd.fd,
+	buf_p->y_buffer_addr = msm_jpeg_platform_v2p(pgmn_dev, buf_cmd.fd,
 		buf_cmd.y_len, &buf_p->file, &buf_p->handle,
 		pgmn_dev->domain_num);
 	if (!buf_p->y_buffer_addr) {
@@ -372,9 +375,18 @@
 		kfree(buf_p);
 		return -EFAULT;
 	}
-	JPEG_DBG("%s:%d]After v2p y_address =0x%08x, handle = %p\n",
-		__func__, __LINE__, buf_p->y_buffer_addr, buf_p->handle);
+
+	if (buf_cmd.cbcr_len)
+		buf_p->cbcr_buffer_addr = buf_p->y_buffer_addr +
+			buf_cmd.y_len;
+	else
+		buf_p->cbcr_buffer_addr = 0x0;
+
+	JPEG_DBG("%s:%d] After v2p pln0_addr =0x%x,pln0_len %d pl1_len %d",
+		__func__, __LINE__, buf_p->y_buffer_addr,
+		buf_cmd.y_len, buf_cmd.cbcr_len);
 	buf_p->y_len = buf_cmd.y_len;
+	buf_p->cbcr_len = buf_cmd.cbcr_len;
 	buf_p->vbuf = buf_cmd;
 
 	msm_jpeg_q_in(&pgmn_dev->output_buf_q, buf_p);
@@ -403,9 +415,9 @@
 	buf_out = msm_jpeg_q_out(&pgmn_dev->input_buf_q);
 
 	if (buf_out) {
-		rc = msm_jpeg_core_fe_buf_update(buf_out);
+		rc = msm_jpeg_core_fe_buf_update(pgmn_dev, buf_out);
 		kfree(buf_out);
-		msm_jpeg_core_fe_start();
+		msm_jpeg_core_fe_start(pgmn_dev);
 	} else {
 		JPEG_DBG("%s:%d] no input buffer\n", __func__, __LINE__);
 		rc = -EFAULT;
@@ -433,8 +445,8 @@
 	}
 
 	buf_cmd = buf_p->vbuf;
-	msm_jpeg_platform_p2v(buf_p->file, &buf_p->handle,
-					pgmn_dev->domain_num);
+	msm_jpeg_platform_p2v(pgmn_dev, buf_p->file, &buf_p->handle,
+		pgmn_dev->domain_num);
 	kfree(buf_p);
 
 	JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
@@ -460,6 +472,7 @@
 {
 	struct msm_jpeg_core_buf *buf_p;
 	struct msm_jpeg_buf buf_cmd;
+	memset(&buf_cmd, 0x0, sizeof(struct msm_jpeg_buf));
 
 	if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_jpeg_buf))) {
 		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
@@ -475,20 +488,26 @@
 	JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
 		(int) buf_cmd.vaddr, buf_cmd.y_len);
 
-	buf_p->y_buffer_addr    = msm_jpeg_platform_v2p(buf_cmd.fd,
+	buf_p->y_buffer_addr    = msm_jpeg_platform_v2p(pgmn_dev, buf_cmd.fd,
 		buf_cmd.y_len + buf_cmd.cbcr_len, &buf_p->file,
 		&buf_p->handle, pgmn_dev->domain_num) + buf_cmd.offset
 		+ buf_cmd.y_off;
 	buf_p->y_len          = buf_cmd.y_len;
-	buf_p->cbcr_buffer_addr = buf_p->y_buffer_addr + buf_cmd.y_len
-						+ buf_cmd.cbcr_off;
 	buf_p->cbcr_len       = buf_cmd.cbcr_len;
 	buf_p->num_of_mcu_rows = buf_cmd.num_of_mcu_rows;
+	buf_p->y_len = buf_cmd.y_len;
+	buf_p->cbcr_len = buf_cmd.cbcr_len;
+	if (buf_cmd.cbcr_len)
+		buf_p->cbcr_buffer_addr = buf_p->y_buffer_addr + buf_cmd.y_len
+			+ buf_cmd.cbcr_off;
+	else
+		buf_p->cbcr_buffer_addr = 0x0;
+
 	JPEG_DBG("%s: y_addr=%x, y_len=%x, cbcr_addr=%x, cbcr_len=%x, fd =%d\n",
 		__func__, buf_p->y_buffer_addr, buf_p->y_len,
 		buf_p->cbcr_buffer_addr, buf_p->cbcr_len, buf_cmd.fd);
 
-	if (!buf_p->y_buffer_addr || !buf_p->cbcr_buffer_addr) {
+	if (!buf_p->y_buffer_addr) {
 		JPEG_PR_ERR("%s:%d] v2p wrong\n", __func__, __LINE__);
 		kfree(buf_p);
 		return -EFAULT;
@@ -559,13 +578,15 @@
 	JPEG_DBG("%s:%d] platform resources - mem %p, base %p, irq %d\n",
 		__func__, __LINE__,
 		pgmn_dev->mem, pgmn_dev->base, pgmn_dev->irq);
+	pgmn_dev->res_size = resource_size(pgmn_dev->mem);
 
 	msm_jpeg_q_cleanup(&pgmn_dev->evt_q);
 	msm_jpeg_q_cleanup(&pgmn_dev->output_rtn_q);
-	msm_jpeg_outbuf_q_cleanup(&pgmn_dev->output_buf_q,
-	pgmn_dev->domain_num); msm_jpeg_q_cleanup(&pgmn_dev->input_rtn_q);
+	msm_jpeg_outbuf_q_cleanup(pgmn_dev, &pgmn_dev->output_buf_q,
+		pgmn_dev->domain_num);
+	msm_jpeg_q_cleanup(&pgmn_dev->input_rtn_q);
 	msm_jpeg_q_cleanup(&pgmn_dev->input_buf_q);
-	msm_jpeg_core_init();
+	msm_jpeg_core_init(pgmn_dev);
 
 	JPEG_DBG("%s:%d] success\n", __func__, __LINE__);
 	return rc;
@@ -583,13 +604,14 @@
 	pgmn_dev->open_count--;
 	mutex_unlock(&pgmn_dev->lock);
 
-	msm_jpeg_core_release(release_buf, pgmn_dev->domain_num);
+	msm_jpeg_core_release(pgmn_dev, pgmn_dev->domain_num);
 	msm_jpeg_q_cleanup(&pgmn_dev->evt_q);
 	msm_jpeg_q_cleanup(&pgmn_dev->output_rtn_q);
-	msm_jpeg_outbuf_q_cleanup(&pgmn_dev->output_buf_q,
-					pgmn_dev->domain_num);
+	msm_jpeg_outbuf_q_cleanup(pgmn_dev, &pgmn_dev->output_buf_q,
+		pgmn_dev->domain_num);
 	msm_jpeg_q_cleanup(&pgmn_dev->input_rtn_q);
-	msm_jpeg_outbuf_q_cleanup(&pgmn_dev->input_buf_q, pgmn_dev->domain_num);
+	msm_jpeg_outbuf_q_cleanup(pgmn_dev, &pgmn_dev->input_buf_q,
+		pgmn_dev->domain_num);
 
 	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
 	if (pgmn_dev->open_count)
@@ -598,6 +620,7 @@
 	msm_jpeg_platform_release(pgmn_dev->mem, pgmn_dev->base,
 		pgmn_dev->irq, pgmn_dev);
 
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
 	return 0;
 }
 
@@ -612,7 +635,8 @@
 		return -EFAULT;
 	}
 
-	is_copy_to_user = msm_jpeg_hw_exec_cmds(&hw_cmd, 1);
+	is_copy_to_user = msm_jpeg_hw_exec_cmds(&hw_cmd, 1,
+		pgmn_dev->res_size, pgmn_dev->base);
 	JPEG_DBG("%s:%d] type %d, n %d, offset %d, mask %x, data %x,pdata %x\n",
 		__func__, __LINE__, hw_cmd.type, hw_cmd.n, hw_cmd.offset,
 		hw_cmd.mask, hw_cmd.data, (int) hw_cmd.pdata);
@@ -657,7 +681,8 @@
 
 	hw_cmd_p = (struct msm_jpeg_hw_cmd *) &(hw_cmds_p->hw_cmd);
 
-	is_copy_to_user = msm_jpeg_hw_exec_cmds(hw_cmd_p, m);
+	is_copy_to_user = msm_jpeg_hw_exec_cmds(hw_cmd_p, m,
+		 pgmn_dev->res_size, pgmn_dev->base);
 
 	if (is_copy_to_user >= 0) {
 		if (copy_to_user(arg, hw_cmds_p, len)) {
@@ -678,12 +703,12 @@
 
 	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
 
-	release_buf = 1;
+	pgmn_dev->release_buf = 1;
 	for (i = 0; i < 2; i++) {
 		buf_out = msm_jpeg_q_out(&pgmn_dev->input_buf_q);
 
 		if (buf_out) {
-			msm_jpeg_core_fe_buf_update(buf_out);
+			msm_jpeg_core_fe_buf_update(pgmn_dev, buf_out);
 			kfree(buf_out);
 		} else {
 			JPEG_DBG("%s:%d] no input buffer\n", __func__,
@@ -696,8 +721,8 @@
 		buf_out_free[i] = msm_jpeg_q_out(&pgmn_dev->output_buf_q);
 
 		if (buf_out_free[i]) {
-			msm_jpeg_core_we_buf_update(buf_out_free[i]);
-			release_buf = 0;
+			msm_jpeg_core_we_buf_update(pgmn_dev, buf_out_free[i]);
+			pgmn_dev->release_buf = 0;
 		} else {
 			JPEG_DBG("%s:%d] no output buffer\n",
 			__func__, __LINE__);
@@ -708,6 +733,7 @@
 	for (i = 0; i < 2; i++)
 		kfree(buf_out_free[i]);
 
+	msm_jpeg_io_dump(pgmn_dev->base, JPEG_REG_SIZE);
 	rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, arg);
 	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
 	return rc;
@@ -727,7 +753,7 @@
 
 	pgmn_dev->op_mode = ctrl_cmd.type;
 
-	rc = msm_jpeg_core_reset(pgmn_dev->op_mode, pgmn_dev->base,
+	rc = msm_jpeg_core_reset(pgmn_dev, pgmn_dev->op_mode, pgmn_dev->base,
 		resource_size(pgmn_dev->mem));
 	return rc;
 }
@@ -736,7 +762,7 @@
 	unsigned long arg)
 {
 	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
-	msm_jpeg_io_dump(arg);
+	msm_jpeg_io_dump(pgmn_dev->base, JPEG_REG_SIZE);
 	return 0;
 }
 
@@ -836,9 +862,10 @@
 
 int __msm_jpeg_init(struct msm_jpeg_device *pgmn_dev)
 {
-	int rc = 0, i = 0;
+	int rc = 0, i = 0, j = 0;
 	int idx = 0;
-	char *iommu_name[3] = {"jpeg_enc0", "jpeg_enc1", "jpeg_dec"};
+	char *iommu_name[JPEG_DEV_CNT] = {"jpeg_enc0", "jpeg_enc1",
+		"jpeg_dec"};
 
 	mutex_init(&pgmn_dev->lock);
 
@@ -847,6 +874,7 @@
 	idx = pgmn_dev->pdev->id;
 	pgmn_dev->idx = idx;
 	pgmn_dev->iommu_cnt = 1;
+	pgmn_dev->decode_flag = (idx == JPEG_DEC_ID);
 
 	msm_jpeg_q_init("evt_q", &pgmn_dev->evt_q);
 	msm_jpeg_q_init("output_rtn_q", &pgmn_dev->output_rtn_q);
@@ -855,21 +883,23 @@
 	msm_jpeg_q_init("input_buf_q", &pgmn_dev->input_buf_q);
 
 #ifdef CONFIG_MSM_IOMMU
-/*get device context for IOMMU*/
+	j = (pgmn_dev->iommu_cnt <= 1) ? idx : 0;
+	/*get device context for IOMMU*/
 	for (i = 0; i < pgmn_dev->iommu_cnt; i++) {
-		pgmn_dev->iommu_ctx_arr[i] = msm_iommu_get_ctx(iommu_name[i]);
-		JPEG_DBG("%s:%d] name %s", __func__, __LINE__, iommu_name[i]);
+		pgmn_dev->iommu_ctx_arr[i] = msm_iommu_get_ctx(iommu_name[j]);
+		JPEG_DBG("%s:%d] name %s", __func__, __LINE__, iommu_name[j]);
 		JPEG_DBG("%s:%d] ctx 0x%x", __func__, __LINE__,
-					(uint32_t)pgmn_dev->iommu_ctx_arr[i]);
+			(uint32_t)pgmn_dev->iommu_ctx_arr[i]);
 		if (!pgmn_dev->iommu_ctx_arr[i]) {
 			JPEG_PR_ERR("%s: No iommu fw context found\n",
 					__func__);
 			goto error;
 		}
+		j++;
 	}
 	pgmn_dev->domain_num = camera_register_domain();
 	JPEG_DBG("%s:%d] dom_num 0x%x", __func__, __LINE__,
-				pgmn_dev->domain_num);
+		pgmn_dev->domain_num);
 	if (pgmn_dev->domain_num < 0) {
 		JPEG_PR_ERR("%s: could not register domain\n", __func__);
 		goto error;
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.h
index 1d82060..1ac4838 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.h
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.h
@@ -21,7 +21,7 @@
 #include <linux/platform_device.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-subdev.h>
-#include "msm_jpeg_core.h"
+#include "msm_jpeg_hw.h"
 
 #define JPEG_7X 0x1
 #define JPEG_8X60 (0x1 << 1)
@@ -88,6 +88,17 @@
 	struct iommu_domain *domain;
 	struct device *iommu_ctx_arr[3];
 	int iommu_cnt;
+	int decode_flag;
+	struct ion_client *jpeg_client;
+	void *jpeg_vbif;
+	int release_buf;
+	struct msm_jpeg_hw_pingpong fe_pingpong_buf;
+	struct msm_jpeg_hw_pingpong we_pingpong_buf;
+	int we_pingpong_index;
+	int reset_done_ack;
+	spinlock_t reset_lock;
+	wait_queue_head_t reset_wait;
+	uint32_t res_size;
 };
 
 int __msm_jpeg_open(struct msm_jpeg_device *pgmn_dev);
diff --git a/include/media/msm_jpeg.h b/include/media/msm_jpeg.h
index 11c3247..56829f1 100644
--- a/include/media/msm_jpeg.h
+++ b/include/media/msm_jpeg.h
@@ -85,6 +85,8 @@
 
 	uint32_t num_of_mcu_rows;
 	uint32_t offset;
+	uint32_t pln2_off;
+	uint32_t pln2_len;
 };
 
 #define MSM_JPEG_HW_CMD_TYPE_READ      0