msm-camera: add SMMU code for use with videobuf2 framework

Signed-off-by: Ankit Premrajka <ankitp@codeaurora.org>
Signed-off-by: Mingcheng Zhu <mingchen@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index c7ec849..434f95c 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -23,6 +23,7 @@
 
 #include <mach/board.h>
 #include <media/msm_camera.h>
+#include <mach/msm_subsystem_map.h>
 
 #define CONFIG_MSM_CAMERA_DEBUG
 #ifdef CONFIG_MSM_CAMERA_DEBUG
@@ -454,6 +455,8 @@
 	unsigned long len;
 	struct file *file;
 	struct msm_pmem_info info;
+	struct msm_mapped_buffer *msm_buffer;
+	int subsys_id;
 };
 
 struct axidata {
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index b887f1e..8ce0f40 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -26,6 +26,7 @@
 #include <media/v4l2-device.h>
 
 #include <linux/android_pmem.h>
+#include <mach/msm_subsystem_map.h>
 
 #include "msm.h"
 #include "msm_vfe31.h"
@@ -128,6 +129,7 @@
 {
 	struct file *file;
 	unsigned long paddr;
+	unsigned int flags;
 #ifdef CONFIG_ANDROID_PMEM
 	unsigned long kvstart;
 	int rc;
@@ -167,8 +169,17 @@
 		return -ENOMEM;
 
 	INIT_HLIST_NODE(&region->list);
-
-	region->paddr = paddr;
+	flags = MSM_SUBSYSTEM_MAP_IOVA;
+	region->subsys_id = MSM_SUBSYSTEM_CAMERA;
+	region->msm_buffer = msm_subsystem_map_buffer(paddr, len,
+					flags, &(region->subsys_id), 1);
+	if (IS_ERR((void *)region->msm_buffer)) {
+		pr_err("%s: msm_subsystem_map_buffer failed\n", __func__);
+		kfree(region);
+		put_pmem_file(file);
+		return PTR_ERR((void *)region->msm_buffer);
+	}
+	region->paddr = region->msm_buffer->iova[0];
 	region->len = len;
 	region->file = file;
 	memcpy(&region->info, info, sizeof(region->info));
@@ -221,6 +232,11 @@
 			if (pinfo->type == region->info.type &&
 				pinfo->vaddr == region->info.vaddr &&
 				pinfo->fd == region->info.fd) {
+				if (msm_subsystem_unmap_buffer
+					(region->msm_buffer) < 0)
+					pr_err(
+					"%s: unmapped stat memory\n",
+					__func__);
 				hlist_del(node);
 #ifdef CONFIG_ANDROID_PMEM
 				put_pmem_file(region->file);
@@ -316,7 +332,7 @@
 				pr_err("%s mem is null. Return ", __func__);
 				break;
 			}
-			reg->paddr = mem->phyaddr;
+			reg->paddr = mem->msm_buffer->iova[0];
 			D("%s paddr for buf %d is 0x%p\n", __func__,
 							i,
 							(void *)reg->paddr);
diff --git a/drivers/media/video/videobuf2-msm-mem.c b/drivers/media/video/videobuf2-msm-mem.c
index 13fbd1f..3b460ef 100644
--- a/drivers/media/video/videobuf2-msm-mem.c
+++ b/drivers/media/video/videobuf2-msm-mem.c
@@ -29,7 +29,7 @@
 #include <media/videobuf2-msm-mem.h>
 #include <media/msm_camera.h>
 #include <mach/memory.h>
-
+#include <mach/msm_subsystem_map.h>
 #include <media/videobuf2-core.h>
 
 #define MAGIC_PMEM 0x0733ac64
@@ -82,6 +82,8 @@
 static void *msm_vb2_mem_ops_alloc(void *alloc_ctx, unsigned long size)
 {
 	struct videobuf2_contig_pmem *mem;
+	unsigned int flags = 0;
+	long rc;
 	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
 	if (!mem)
 		return ERR_PTR(-ENOMEM);
@@ -96,13 +98,28 @@
 		kfree(mem);
 		return ERR_PTR(-ENOMEM);
 	}
+	flags = MSM_SUBSYSTEM_MAP_IOVA;
+	mem->subsys_id = MSM_SUBSYSTEM_CAMERA;
+	mem->msm_buffer = msm_subsystem_map_buffer(mem->phyaddr, mem->size,
+					flags, &(mem->subsys_id), 1);
+	if (IS_ERR((void *)mem->msm_buffer)) {
+		pr_err("%s: msm_subsystem_map_buffer failed\n", __func__);
+		rc = PTR_ERR((void *)mem->msm_buffer);
+		msm_mem_free(mem->phyaddr);
+		kfree(mem);
+		return ERR_PTR(-ENOMEM);
+	}
 	return mem;
 }
 static void msm_vb2_mem_ops_put(void *buf_priv)
 {
 	struct videobuf2_contig_pmem *mem = buf_priv;
-	if (!mem->is_userptr)
+	if (!mem->is_userptr) {
+		D("%s Freeing memory ", __func__);
+		if (msm_subsystem_unmap_buffer(mem->msm_buffer) < 0)
+			D("%s unmapped memory\n", __func__);
 		msm_mem_free(mem->phyaddr);
+	}
 	kfree(mem);
 }
 int videobuf2_pmem_contig_mmap_get(struct videobuf2_contig_pmem *mem,
@@ -133,6 +150,7 @@
 	unsigned long kvstart;
 	unsigned long len;
 	int rc;
+	unsigned int flags = 0;
 
 	if (mem->phyaddr != 0)
 		return 0;
@@ -148,12 +166,23 @@
 	mem->y_off = yoffset;
 	mem->cbcr_off = cbcroffset;
 	mem->buffer_type = path;
+	flags = MSM_SUBSYSTEM_MAP_IOVA;
+	mem->subsys_id = MSM_SUBSYSTEM_CAMERA;
+	mem->msm_buffer = msm_subsystem_map_buffer(mem->phyaddr, mem->size,
+					flags, &(mem->subsys_id), 1);
+	if (IS_ERR((void *)mem->msm_buffer)) {
+		pr_err("%s: msm_subsystem_map_buffer failed\n", __func__);
+		put_pmem_file(mem->file);
+		return PTR_ERR((void *)mem->msm_buffer);
+	}
 	return rc;
 }
 EXPORT_SYMBOL_GPL(videobuf2_pmem_contig_user_get);
 
 void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem)
 {
+	if (msm_subsystem_unmap_buffer(mem->msm_buffer) < 0)
+		D("%s unmapped memory\n", __func__);
 	if (mem->is_userptr)
 		put_pmem_file(mem->file);
 	mem->is_userptr = 0;
@@ -206,7 +235,6 @@
 	D("mem = 0x%x\n", (u32)mem);
 	BUG_ON(!mem);
 	MAGIC_CHECK(mem->magic, MAGIC_PMEM);
-
 	/* Try to remap memory */
 	size = vma->vm_end - vma->vm_start;
 	size = (size < mem->size) ? size : mem->size;
@@ -261,13 +289,14 @@
 }
 EXPORT_SYMBOL_GPL(videobuf2_queue_pmem_contig_init);
 
-int videobuf2_to_pmem_contig(struct vb2_buffer *vb, unsigned int plane_no)
+unsigned long videobuf2_to_pmem_contig(struct vb2_buffer *vb,
+				unsigned int plane_no)
 {
 	struct videobuf2_contig_pmem *mem;
 	mem = vb2_plane_cookie(vb, plane_no);
 	BUG_ON(!mem);
 	MAGIC_CHECK(mem->magic, MAGIC_PMEM);
-	return mem->phyaddr;
+	return mem->msm_buffer->iova[0];
 }
 EXPORT_SYMBOL_GPL(videobuf2_to_pmem_contig);
 
diff --git a/include/media/videobuf2-msm-mem.h b/include/media/videobuf2-msm-mem.h
index 047d20f..24eaf13 100644
--- a/include/media/videobuf2-msm-mem.h
+++ b/include/media/videobuf2-msm-mem.h
@@ -16,6 +16,7 @@
 #define _VIDEOBUF2_PMEM_CONTIG_H
 
 #include <media/videobuf2-core.h>
+#include <mach/msm_subsystem_map.h>
 
 struct videobuf2_mapping {
 	unsigned int count;
@@ -35,6 +36,8 @@
 	int dirty;
 	unsigned int count;
 	void *alloc_ctx;
+	struct msm_mapped_buffer *msm_buffer;
+	int subsys_id;
 };
 void videobuf2_queue_pmem_contig_init(struct vb2_queue *q,
 					enum v4l2_buf_type type,
@@ -48,6 +51,7 @@
 					uint32_t yoffset, uint32_t cbcroffset,
 					uint32_t addr_offset, int path);
 void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem);
-int videobuf2_to_pmem_contig(struct vb2_buffer *buf, unsigned int plane_no);
+unsigned long videobuf2_to_pmem_contig(struct vb2_buffer *buf,
+					unsigned int plane_no);
 
 #endif /* _VIDEOBUF2_PMEM_CONTIG_H */