MMIOT-6-2 android: ion: add carveouts for Freescale i.MX8MQ DCSS and VPU

Signed-off-by: Hervé Fache <herve.fache@nxp.com>
Signed-off-by: Antoine Bouyer <antoine.bouyer@nxp.com>

MMIOT-6-2 android: ion: Minor changes for readability

Signed-off-by: Alexandre Jutras <alexandre.jutras@nxp.com>
(cherry picked from commit 627f870847ab5f2763dc1a84f06d39a50ad514e5)
diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig
index 83be0a8..21d3bca 100644
--- a/drivers/staging/android/ion/Kconfig
+++ b/drivers/staging/android/ion/Kconfig
@@ -46,6 +46,7 @@
 	tristate "Ion for imx platform"
 	depends on ION
 	select VIDEOBUF2_DMA_CONTIG
+	select ION_OF
 	help
 	  Choose this option if you wish to use ion on imx platform.
 
diff --git a/drivers/staging/android/ion/mxc/mxc_ion.c b/drivers/staging/android/ion/mxc/mxc_ion.c
index 4f5f225..b86c1f8 100644
--- a/drivers/staging/android/ion/mxc/mxc_ion.c
+++ b/drivers/staging/android/ion/mxc/mxc_ion.c
@@ -23,11 +23,13 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/of_reserved_mem.h>
 #include <linux/uaccess.h>
 #include <media/videobuf2-dma-contig.h>
 #include <linux/dma-buf.h>
 
 #include "../ion_priv.h"
+#include "../ion_of.h"
 
 #ifdef CONFIG_COMPAT
 #include <linux/compat.h>
@@ -37,30 +39,88 @@
 static struct ion_heap **heaps;
 static int cacheable;
 
+static struct ion_of_heap mxc_heaps[] = {
+	PLATFORM_HEAP("fsl,user-heap", 0, ION_HEAP_TYPE_DMA, "user"),
+	PLATFORM_HEAP("fsl,display-heap", 1, ION_HEAP_TYPE_UNMAPPED, "display"),
+	PLATFORM_HEAP("fsl,vpu-heap", 2, ION_HEAP_TYPE_UNMAPPED, "vpu"),
+	{}
+};
+
+static int rmem_imx_device_init(struct reserved_mem *rmem, struct device *dev)
+{
+	dev_set_drvdata(dev, rmem);
+	return 0;
+}
+
+static const struct reserved_mem_ops rmem_dma_ops = {
+	.device_init	= rmem_imx_device_init,
+};
+
+static int __init rmem_imx_ion_setup(struct reserved_mem *rmem)
+{
+	rmem->ops = &rmem_dma_ops;
+	pr_info("Reserved memory: created ION memory pool at %pa, size %ld MiB\n",
+		&rmem->base, (unsigned long)rmem->size / SZ_1M);
+	return 0;
+}
+
+RESERVEDMEM_OF_DECLARE(cma, "imx-ion-pool", rmem_imx_ion_setup);
+
+/* Note: original code could be adapted so we just call ion_parse_dt() */
 struct ion_platform_data *mxc_ion_parse_of(struct platform_device *pdev)
 {
 	struct ion_platform_data *pdata = 0;
 	const struct device_node *node = pdev->dev.of_node;
 	int ret = 0;
 	unsigned int val = 0;
-	struct ion_platform_heap *heap = NULL;
+	struct ion_platform_heap *heaps = NULL;
+	struct ion_platform_heap *user_heap;
 
-	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
-	if (!pdata)
-		return ERR_PTR(-ENOMEM);
+	pdata = ion_parse_dt(pdev, mxc_heaps);
+	if (IS_ERR(pdata)) {
+		if (PTR_ERR(pdata) != -EINVAL)
+			return pdata;
 
-	heap = kzalloc(sizeof(*heap), GFP_KERNEL);
-	if (!heap) {
-		kfree(pdata);
+		/* Even if DT has no heap, we still want the user one */
+		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+		if (!pdata)
+			return ERR_PTR(-ENOMEM);
+	} else {
+		/* Get rmem info into heap */
+		int i;
+
+		for (i = 0; i < pdata->nr; i++) {
+			struct ion_platform_heap *heap = &pdata->heaps[i];
+			struct reserved_mem *rmem = dev_get_drvdata(heap->priv);
+
+			heap->base = rmem->base;
+			heap->size = rmem->size;
+		}
+	}
+
+	/* Add user heap for legacy + copy device tree ones */
+	heaps = devm_kzalloc(&pdev->dev,
+			     sizeof(struct ion_platform_heap) * (pdata->nr + 1),
+			     GFP_KERNEL);
+	if (!heaps) {
+		ion_destroy_platform_data(pdata);
 		return ERR_PTR(-ENOMEM);
 	}
 
-	heap->type = ION_HEAP_TYPE_DMA;
-	heap->priv = &pdev->dev;
-	heap->name = "mxc_ion";
+	if (pdata->heaps) {
+		memcpy(heaps, pdata->heaps,
+		       sizeof(struct ion_platform_heap) * pdata->nr);
+		devm_kfree(&pdev->dev, pdata->heaps);
+	}
 
-	pdata->heaps = heap;
-	pdata->nr = num_heaps;
+	pdata->heaps = heaps;
+
+	/* Add the VPU heap */
+	user_heap = &heaps[pdata->nr];
+	user_heap->type = ION_HEAP_TYPE_DMA;
+	user_heap->priv = &pdev->dev;
+	user_heap->name = "mxc_ion";
+	pdata->nr++;
 
 	ret = of_property_read_u32(node, "fsl,heap-cacheable", &val);
 	if (!ret)
@@ -69,9 +129,9 @@
 	val = 0;
 	ret = of_property_read_u32(node, "fsl,heap-id", &val);
 	if (!ret)
-		heap->id = val;
+		user_heap->id = val;
 	else
-		heap->id = 0;
+		user_heap->id = 0;
 
 	return pdata;
 }
@@ -374,23 +434,21 @@
 int mxc_ion_probe(struct platform_device *pdev)
 {
 	struct ion_platform_data *pdata = NULL;
-	int pdata_is_created = 0;
 	int err;
 	int i;
 
-	if (pdev->dev.of_node) {
+	if (pdev->dev.of_node)
 		pdata = mxc_ion_parse_of(pdev);
-		pdata_is_created = 1;
-	} else {
+	else
 		pdata = pdev->dev.platform_data;
-	}
 
 	if (IS_ERR_OR_NULL(pdata))
 		return PTR_ERR(pdata);
 
 	num_heaps = pdata->nr;
 
-	heaps = kzalloc(sizeof(struct ion_heap *) * pdata->nr, GFP_KERNEL);
+	heaps = devm_kzalloc(&pdev->dev, sizeof(struct ion_heap *) * pdata->nr,
+			     GFP_KERNEL);
 
 #ifdef CONFIG_COMPAT
 	idev = ion_device_create(mxc_custom_compat_ioctl);
@@ -405,10 +463,8 @@
 	of_dma_configure(idev->dev.this_device, pdev->dev.of_node);
 
 	/* create the heaps as specified in the board file */
-	for (i = 0; i < num_heaps; i++) {
-		struct ion_platform_heap *heap_data = &pdata->heaps[i];
-
-		heaps[i] = ion_heap_create(heap_data);
+	for (i = 0; i < pdata->nr; i++) {
+		heaps[i] = ion_heap_create(&pdata->heaps[i]);
 		if (IS_ERR_OR_NULL(heaps[i])) {
 			err = PTR_ERR(heaps[i]);
 			heaps[i] = NULL;
@@ -419,15 +475,14 @@
 	platform_set_drvdata(pdev, idev);
 	return 0;
 err:
-	for (i = 0; i < num_heaps; i++) {
+	for (i = 0; i < pdata->nr; i++)
 		if (heaps[i])
 			ion_heap_destroy(heaps[i]);
-	}
-	kfree(heaps);
-	if (pdata_is_created) {
-		kfree(pdata->heaps);
-		kfree(pdata);
-	}
+
+	devm_kfree(&pdev->dev, heaps);
+	if (pdev->dev.of_node)
+		ion_destroy_platform_data(pdata);
+
 	return err;
 }
 
@@ -439,7 +494,8 @@
 	ion_device_destroy(idev);
 	for (i = 0; i < num_heaps; i++)
 		ion_heap_destroy(heaps[i]);
-	kfree(heaps);
+
+	devm_kfree(&pdev->dev, heaps);
 	return 0;
 }