msm: qdsp5: Add ION framework support for 7x27A & 8x25 targets

Modified adsp driver to support the ION memory framework
for 7x27A and 8x25 targets

Change-Id: I0df75ed3d71575a28fe9f2267117a94c5a224296
Signed-off-by: Saikumar Kondaparthi <saikumar@codeaurora.org>
diff --git a/arch/arm/mach-msm/qdsp5/adsp.c b/arch/arm/mach-msm/qdsp5/adsp.c
index b485058..eee7e37 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.c
+++ b/arch/arm/mach-msm/qdsp5/adsp.c
@@ -1262,7 +1262,7 @@
 			clk_set_rate(mod->clk, adsp_info.module[i].clk_rate);
 		mod->verify_cmd = adsp_info.module[i].verify_cmd;
 		mod->patch_event = adsp_info.module[i].patch_event;
-		INIT_HLIST_HEAD(&mod->pmem_regions);
+		INIT_HLIST_HEAD(&mod->ion_regions);
 		mod->pdev.name = adsp_info.module[i].pdev_name;
 		mod->pdev.id = -1;
 		adsp_info.id_to_module[i] = mod;
diff --git a/arch/arm/mach-msm/qdsp5/adsp.h b/arch/arm/mach-msm/qdsp5/adsp.h
index 0f16111..06e2f22 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.h
+++ b/arch/arm/mach-msm/qdsp5/adsp.h
@@ -20,12 +20,16 @@
 
 #include <linux/types.h>
 #include <linux/msm_adsp.h>
+#include <linux/ion.h>
 #include <mach/msm_rpcrouter.h>
 #include <mach/msm_adsp.h>
 
 int adsp_pmem_fixup(struct msm_adsp_module *module, void **addr,
 		    unsigned long len);
-int adsp_pmem_fixup_kvaddr(struct msm_adsp_module *module, void **addr,
+int adsp_ion_do_cache_op(struct msm_adsp_module *module, void *addr,
+			void *paddr, unsigned long len,
+			unsigned long offset, int cmd);
+int adsp_ion_fixup_kvaddr(struct msm_adsp_module *module, void **addr,
 			   unsigned long *kvaddr, unsigned long len,
 			   struct file **filp, unsigned long *offset);
 int adsp_pmem_paddr_fixup(struct msm_adsp_module *module, void **addr);
@@ -276,8 +280,8 @@
 	struct clk *clk;
 	int open_count;
 
-	struct mutex pmem_regions_lock;
-	struct hlist_head pmem_regions;
+	struct mutex ion_regions_lock;
+	struct hlist_head ion_regions;
 	int (*verify_cmd) (struct msm_adsp_module*, unsigned int, void *,
 			   size_t);
 	int (*patch_event) (struct msm_adsp_module*, struct adsp_event *);
diff --git a/arch/arm/mach-msm/qdsp5/adsp_driver.c b/arch/arm/mach-msm/qdsp5/adsp_driver.c
index 6860d84..9d261ae 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_driver.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_driver.c
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/qdsp5/adsp_driver.c
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009, 2012 Code Aurora Forum. All rights reserved.
  * Author: Iliyan Malchev <ibm@android.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -23,25 +23,27 @@
 #include <linux/uaccess.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-
 #include "adsp.h"
-
 #include <linux/msm_adsp.h>
 #include <linux/android_pmem.h>
 #include <mach/debug_mm.h>
 
-struct adsp_pmem_info {
+struct adsp_ion_info {
 	int fd;
 	void *vaddr;
 };
 
-struct adsp_pmem_region {
+struct adsp_ion_region {
 	struct hlist_node list;
 	void *vaddr;
 	unsigned long paddr;
 	unsigned long kvaddr;
 	unsigned long len;
+	unsigned long ion_flag;
 	struct file *file;
+	struct ion_handle *handle;
+	struct ion_client *client;
+	int fd;
 };
 
 struct adsp_device {
@@ -90,14 +92,14 @@
 	res;							\
 })
 
-static int adsp_pmem_check(struct msm_adsp_module *module,
+static int adsp_ion_check(struct msm_adsp_module *module,
 		void *vaddr, unsigned long len)
 {
-	struct adsp_pmem_region *region_elt;
+	struct adsp_ion_region *region_elt;
 	struct hlist_node *node;
-	struct adsp_pmem_region t = { .vaddr = vaddr, .len = len };
+	struct adsp_ion_region t = { .vaddr = vaddr, .len = len };
 
-	hlist_for_each_entry(region_elt, node, &module->pmem_regions, list) {
+	hlist_for_each_entry(region_elt, node, &module->ion_regions, list) {
 		if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
 		    OVERLAPS(region_elt, &t)) {
 			MM_ERR("module %s:"
@@ -116,58 +118,109 @@
 	return 0;
 }
 
-static int adsp_pmem_add(struct msm_adsp_module *module,
-			 struct adsp_pmem_info *info)
+static int get_ion_region_info(int fd, struct adsp_ion_region *region)
 {
-	unsigned long paddr, kvaddr, len;
-	struct file *file;
-	struct adsp_pmem_region *region;
+	unsigned long ionflag;
+	void *temp_ptr;
 	int rc = -EINVAL;
 
-	mutex_lock(&module->pmem_regions_lock);
-	region = kmalloc(sizeof(*region), GFP_KERNEL);
+	region->client = msm_ion_client_create(UINT_MAX, "Video_Client");
+	if (IS_ERR_OR_NULL(region->client)) {
+		pr_err("Unable to create ION client\n");
+		goto client_error;
+	}
+	region->handle = ion_import_dma_buf(region->client, fd);
+	if (IS_ERR_OR_NULL(region->handle)) {
+		pr_err("%s: could not get handle of the given fd\n", __func__);
+		goto import_error;
+	}
+	rc = ion_handle_get_flags(region->client, region->handle, &ionflag);
+	if (rc) {
+		pr_err("%s: could not get flags for the handle\n", __func__);
+		goto flag_error;
+	}
+	temp_ptr = ion_map_kernel(region->client, region->handle, ionflag);
+	if (IS_ERR_OR_NULL(temp_ptr)) {
+		pr_err("%s: could not get virtual address\n", __func__);
+		goto map_error;
+	}
+	region->kvaddr = (unsigned long) temp_ptr;
+	region->ion_flag = (unsigned long) ionflag;
+
+	rc = ion_phys(region->client, region->handle, &region->paddr,
+					(size_t *)(&region->len));
+	if (rc) {
+		pr_err("%s: could not get physical address\n", __func__);
+		goto ion_error;
+	}
+	return rc;
+ion_error:
+	ion_unmap_kernel(region->client, region->handle);
+map_error:
+	ion_free(region->client, region->handle);
+flag_error:
+import_error:
+	ion_client_destroy(region->client);
+client_error:
+	return -EINVAL;
+}
+
+static void free_ion_region(struct ion_client *client,
+			struct ion_handle *handle)
+{
+	ion_unmap_kernel(client, handle);
+	ion_free(client, handle);
+	ion_client_destroy(client);
+}
+
+static int adsp_ion_add(struct msm_adsp_module *module,
+			 struct adsp_ion_info *info)
+{
+	struct adsp_ion_region *region;
+	int rc = -EINVAL;
+	mutex_lock(&module->ion_regions_lock);
+	region = kmalloc(sizeof(struct adsp_ion_region), GFP_KERNEL);
 	if (!region) {
 		rc = -ENOMEM;
 		goto end;
 	}
 	INIT_HLIST_NODE(&region->list);
-	if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
+	if (get_ion_region_info(info->fd, region)) {
 		kfree(region);
 		goto end;
 	}
 
-	rc = adsp_pmem_check(module, info->vaddr, len);
+	rc = adsp_ion_check(module, info->vaddr, region->len);
 	if (rc < 0) {
-		put_pmem_file(file);
+		free_ion_region(region->client, region->handle);
 		kfree(region);
 		goto end;
 	}
-
 	region->vaddr = info->vaddr;
-	region->paddr = paddr;
-	region->kvaddr = kvaddr;
-	region->len = len;
-	region->file = file;
-
-	hlist_add_head(&region->list, &module->pmem_regions);
+	region->fd = info->fd;
+	region->file = NULL;
+	MM_INFO("adsp_ion_add: module %s: fd %d, vaddr Ox%x, len %d\n",
+			module->name, region->fd, (unsigned int)region->vaddr,
+			(int)region->len);
+	hlist_add_head(&region->list, &module->ion_regions);
 end:
-	mutex_unlock(&module->pmem_regions_lock);
+	mutex_unlock(&module->ion_regions_lock);
 	return rc;
 }
 
-static int adsp_pmem_lookup_vaddr(struct msm_adsp_module *module, void **addr,
-		     unsigned long len, struct adsp_pmem_region **region)
+static int adsp_ion_lookup_vaddr(struct msm_adsp_module *module, void **addr,
+		     unsigned long len, struct adsp_ion_region **region)
 {
 	struct hlist_node *node;
 	void *vaddr = *addr;
-	struct adsp_pmem_region *region_elt;
+	struct adsp_ion_region *region_elt;
 
 	int match_count = 0;
 
 	*region = NULL;
 
 	/* returns physical address or zero */
-	hlist_for_each_entry(region_elt, node, &module->pmem_regions, list) {
+	hlist_for_each_entry(region_elt, node, &module->ion_regions, list) {
 		if (vaddr >= region_elt->vaddr &&
 		    vaddr < region_elt->vaddr + region_elt->len &&
 		    vaddr + len <= region_elt->vaddr + region_elt->len) {
@@ -186,7 +239,7 @@
 			"multiple hits for vaddr %p, len %ld\n",
 			module->name, vaddr, len);
 		hlist_for_each_entry(region_elt, node,
-				&module->pmem_regions, list) {
+				&module->ion_regions, list) {
 			if (vaddr >= region_elt->vaddr &&
 			    vaddr < region_elt->vaddr + region_elt->len &&
 			    vaddr + len <= region_elt->vaddr + region_elt->len)
@@ -200,16 +253,37 @@
 	return *region ? 0 : -1;
 }
 
-int adsp_pmem_fixup_kvaddr(struct msm_adsp_module *module, void **addr,
+int adsp_ion_do_cache_op(struct msm_adsp_module *module,
+				void *addr, void *paddr, unsigned long len,
+				unsigned long offset, int cmd)
+{
+	struct adsp_ion_region   *region;
+	void *vaddr = addr;
+	int ret;
+	ret = adsp_ion_lookup_vaddr(module, &vaddr, len, &region);
+	if (ret) {
+		MM_ERR("not patching %s (paddr & kvaddr)," \
+			" lookup (%p, %ld) failed\n",
+			module->name, vaddr, len);
+		return ret;
+	}
+	if ((region->ion_flag == CACHED) && region->handle) {
+		len = ((((len) + 31) & (~31)) + 32);
+		ret = msm_ion_do_cache_op(region->client, region->handle,
+				(void *)paddr, len, cmd);
+	}
+	return ret;
+}
+int adsp_ion_fixup_kvaddr(struct msm_adsp_module *module, void **addr,
 			   unsigned long *kvaddr, unsigned long len,
 			   struct file **filp, unsigned long *offset)
 {
-	struct adsp_pmem_region *region;
+	struct adsp_ion_region *region;
 	void *vaddr = *addr;
 	unsigned long *paddr = (unsigned long *)addr;
 	int ret;
 
-	ret = adsp_pmem_lookup_vaddr(module, addr, len, &region);
+	ret = adsp_ion_lookup_vaddr(module, addr, len, &region);
 	if (ret) {
 		MM_ERR("not patching %s (paddr & kvaddr),"
 			" lookup (%p, %ld) failed\n",
@@ -228,12 +302,12 @@
 int adsp_pmem_fixup(struct msm_adsp_module *module, void **addr,
 		    unsigned long len)
 {
-	struct adsp_pmem_region *region;
+	struct adsp_ion_region *region;
 	void *vaddr = *addr;
 	unsigned long *paddr = (unsigned long *)addr;
 	int ret;
 
-	ret = adsp_pmem_lookup_vaddr(module, addr, len, &region);
+	ret = adsp_ion_lookup_vaddr(module, addr, len, &region);
 	if (ret) {
 		MM_ERR("not patching %s, lookup (%p, %ld) failed\n",
 			module->name, vaddr, len);
@@ -281,7 +355,7 @@
 		goto end;
 	}
 
-	mutex_lock(&adev->module->pmem_regions_lock);
+	mutex_lock(&adev->module->ion_regions_lock);
 	if (adsp_verify_cmd(adev->module, cmd.queue, cmd_data, cmd.len)) {
 		MM_ERR("module %s: verify failed.\n", adev->module->name);
 		rc = -EINVAL;
@@ -291,7 +365,7 @@
 	wmb();
 	rc = msm_adsp_write(adev->module, cmd.queue, cmd_data, cmd.len);
 end:
-	mutex_unlock(&adev->module->pmem_regions_lock);
+	mutex_unlock(&adev->module->ion_regions_lock);
 
 	if (cmd.len > 256)
 		kfree(cmd_data);
@@ -309,14 +383,14 @@
 	return yes || adev->abort;
 }
 
-static int adsp_pmem_lookup_paddr(struct msm_adsp_module *module, void **addr,
-		     struct adsp_pmem_region **region)
+static int adsp_ion_lookup_paddr(struct msm_adsp_module *module, void **addr,
+		     struct adsp_ion_region **region)
 {
 	struct hlist_node *node;
 	unsigned long paddr = (unsigned long)(*addr);
-	struct adsp_pmem_region *region_elt;
+	struct adsp_ion_region *region_elt;
 
-	hlist_for_each_entry(region_elt, node, &module->pmem_regions, list) {
+	hlist_for_each_entry(region_elt, node, &module->ion_regions, list) {
 		if (paddr >= region_elt->paddr &&
 		    paddr < region_elt->paddr + region_elt->len) {
 			*region = region_elt;
@@ -328,12 +402,12 @@
 
 int adsp_pmem_paddr_fixup(struct msm_adsp_module *module, void **addr)
 {
-	struct adsp_pmem_region *region;
+	struct adsp_ion_region *region;
 	unsigned long paddr = (unsigned long)(*addr);
 	unsigned long *vaddr = (unsigned long *)addr;
 	int ret;
 
-	ret = adsp_pmem_lookup_paddr(module, addr, &region);
+	ret = adsp_ion_lookup_paddr(module, addr, &region);
 	if (ret) {
 		MM_ERR("not patching %s, paddr %p lookup failed\n",
 			module->name, vaddr);
@@ -429,20 +503,23 @@
 	return rc;
 }
 
-static int adsp_pmem_del(struct msm_adsp_module *module)
+static int adsp_ion_del(struct msm_adsp_module *module)
 {
 	struct hlist_node *node, *tmp;
-	struct adsp_pmem_region *region;
+	struct adsp_ion_region *region;
 
-	mutex_lock(&module->pmem_regions_lock);
-	hlist_for_each_safe(node, tmp, &module->pmem_regions) {
-		region = hlist_entry(node, struct adsp_pmem_region, list);
+	mutex_lock(&module->ion_regions_lock);
+	hlist_for_each_safe(node, tmp, &module->ion_regions) {
+		region = hlist_entry(node, struct adsp_ion_region, list);
 		hlist_del(node);
-		put_pmem_file(region->file);
+		MM_INFO("adsp_ion_del: module %s: fd %d, vaddr Ox%x, len %d\n",
+			module->name, region->fd, (unsigned int)region->vaddr,
+			(int)region->len);
+		free_ion_region(region->client, region->handle);
 		kfree(region);
 	}
-	mutex_unlock(&module->pmem_regions_lock);
-	BUG_ON(!hlist_empty(&module->pmem_regions));
+	mutex_unlock(&module->ion_regions_lock);
+	BUG_ON(!hlist_empty(&module->ion_regions));
 
 	return 0;
 }
@@ -479,10 +556,10 @@
 	}
 
 	case ADSP_IOCTL_REGISTER_PMEM: {
-		struct adsp_pmem_info info;
+		struct adsp_ion_info info;
 		if (copy_from_user(&info, (void *) arg, sizeof(info)))
 			return -EFAULT;
-		return adsp_pmem_add(adev->module, &info);
+		return adsp_ion_add(adev->module, &info);
 	}
 
 	case ADSP_IOCTL_ABORT_EVENT_READ:
@@ -491,7 +568,7 @@
 		break;
 
 	case ADSP_IOCTL_UNREGISTER_PMEM:
-		return adsp_pmem_del(adev->module);
+		return adsp_ion_del(adev->module);
 
 	default:
 		break;
@@ -510,7 +587,7 @@
 	/* clear module before putting it to avoid race with open() */
 	adev->module = NULL;
 
-	rc = adsp_pmem_del(module);
+	rc = adsp_ion_del(module);
 
 	msm_adsp_put(module);
 	return rc;
@@ -581,8 +658,8 @@
 	MM_INFO("opened module '%s' adev %p\n", adev->name, adev);
 	filp->private_data = adev;
 	adev->abort = 0;
-	INIT_HLIST_HEAD(&adev->module->pmem_regions);
-	mutex_init(&adev->module->pmem_regions_lock);
+	INIT_HLIST_HEAD(&adev->module->ion_regions);
+	mutex_init(&adev->module->ion_regions_lock);
 
 	return 0;
 }
diff --git a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
index 492fa0e..af259b5 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
@@ -3,7 +3,7 @@
  * Verificion code for aDSP VDEC packets from userspace.
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2010, 2012 Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -55,7 +55,7 @@
 	MM_DBG("virt %x %x\n", (unsigned int)phys_addr,
 			(unsigned int)phys_size);
 	if (phys_addr) {
-		if (adsp_pmem_fixup_kvaddr(module, &phys_addr,
+		if (adsp_ion_fixup_kvaddr(module, &phys_addr,
 			 &kvaddr, phys_size, filp, offset)) {
 			MM_ERR("ah%x al%x sh%x sl%x addr %x size %x\n",
 					*high, *low, size_high,
@@ -77,6 +77,7 @@
 static int verify_vdec_pkt_cmd(struct msm_adsp_module *module,
 			       void *cmd_data, size_t cmd_size)
 {
+	void *phys_addr;
 	unsigned short cmd_id = ((unsigned short *)cmd_data)[0];
 	viddec_cmd_subframe_pkt *pkt;
 	unsigned long subframe_pkt_addr;
@@ -89,7 +90,6 @@
 	unsigned short frame_buffer_size_high, frame_buffer_size_low;
 	struct file *filp = NULL;
 	unsigned long offset = 0;
-	struct pmem_addr pmem_addr;
 	unsigned long Codec_Id = 0;
 
 	MM_DBG("cmd_size %d cmd_id %d cmd_data %x\n", cmd_size, cmd_id,
@@ -102,6 +102,8 @@
 		return -1;
 
 	pkt = (viddec_cmd_subframe_pkt *)cmd_data;
+	phys_addr = high_low_short_to_ptr(pkt->subframe_packet_high,
+				pkt->subframe_packet_low);
 
 	if (pmem_fixup_high_low(&(pkt->subframe_packet_high),
 				&(pkt->subframe_packet_low),
@@ -114,16 +116,12 @@
 		return -1;
 	Codec_Id = pkt->codec_selection_word;
 	/*Invalidate cache before accessing the cached pmem buffer*/
-	if (filp) {
-		pmem_addr.vaddr = subframe_pkt_addr;
-		pmem_addr.length = (((subframe_pkt_size*2) + 31) & (~31)) + 32;
-		pmem_addr.offset = offset;
-		if (pmem_cache_maint (filp, PMEM_INV_CACHES,  &pmem_addr)) {
-			MM_ERR("Cache operation failed for phys addr high %x"
-				" addr low %x\n", pkt->subframe_packet_high,
-				pkt->subframe_packet_low);
-			return -EINVAL;
-		}
+	if (adsp_ion_do_cache_op(module, phys_addr, (void *)subframe_pkt_addr,
+		subframe_pkt_size*2, offset, ION_IOC_INV_CACHES)){
+		MM_ERR("Cache operation failed for" \
+			" phys addr high %x addr low %x\n",
+			pkt->subframe_packet_high, pkt->subframe_packet_low);
+		return -EINVAL;
 	}
 	/* deref those ptrs and check if they are a frame header packet */
 	frame_header_pkt = (unsigned short *)subframe_pkt_addr;
@@ -241,19 +239,14 @@
 			frame_buffer_low += 2;
 		}
 	}
-	/*Flush the cached pmem subframe packet before sending to DSP*/
-	if (filp) {
-		pmem_addr.vaddr = subframe_pkt_addr;
-		pmem_addr.length = MAX_FLUSH_SIZE;
-		pmem_addr.offset = offset;
-		if (pmem_cache_maint(filp, PMEM_CLEAN_CACHES, &pmem_addr)) {
-			MM_ERR("Cache operation failed for phys addr high %x"
-				" addr low %x\n", pkt->subframe_packet_high,
-				pkt->subframe_packet_low);
-			return -1;
-		}
+	/*Flush the cached mem subframe packet before sending to DSP*/
+	if (adsp_ion_do_cache_op(module,  phys_addr, (void *)subframe_pkt_addr,
+		MAX_FLUSH_SIZE, offset, ION_IOC_CLEAN_CACHES)){
+		MM_ERR("Cache operation failed for" \
+			" phys addr high %x addr low %x\n",
+			pkt->subframe_packet_high, pkt->subframe_packet_low);
+		return -EINVAL;
 	}
-
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/qdsp5/adsp_videoenc_verify_cmd.c b/arch/arm/mach-msm/qdsp5/adsp_videoenc_verify_cmd.c
index 936b7af..290a14c 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_videoenc_verify_cmd.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_videoenc_verify_cmd.c
@@ -3,7 +3,7 @@
  * Verificion code for aDSP VENC packets from userspace.
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -53,7 +53,7 @@
 	phys_size = (unsigned long)high_low_short_to_ptr(size_high, size_low);
 	MM_DBG("virt %x %x\n", (unsigned int)phys_addr,
 			(unsigned int)phys_size);
-	if (adsp_pmem_fixup_kvaddr(module, &phys_addr, &kvaddr, phys_size,
+	if (adsp_ion_fixup_kvaddr(module, &phys_addr, &kvaddr, phys_size,
 				NULL, NULL)) {
 		MM_ERR("ah%x al%x sh%x sl%x addr %x size %x\n",
 			*high, *low, size_high,