summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/Makefile2
-rw-r--r--drivers/staging/android/Kconfig4
-rw-r--r--drivers/staging/android/ion/Kconfig8
-rw-r--r--drivers/staging/android/ion/Makefile2
-rw-r--r--drivers/staging/android/ion/ion.c38
-rw-r--r--drivers/staging/android/ion/ion_priv.h6
-rw-r--r--drivers/staging/android/ion/mxc/Makefile2
-rw-r--r--drivers/staging/android/ion/mxc/mxc_ion.c308
-rw-r--r--drivers/staging/android/uapi/ion.h25
9 files changed, 391 insertions, 4 deletions
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 2fa9745db614..27a8ba7ee973 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -22,7 +22,7 @@ obj-$(CONFIG_FB_XGI) += xgifb/
obj-$(CONFIG_USB_EMXX) += emxx_udc/
obj-$(CONFIG_SPEAKUP) += speakup/
obj-$(CONFIG_MFD_NVEC) += nvec/
-obj-$(CONFIG_ANDROID) += android/
+obj-y += android/
obj-$(CONFIG_STAGING_BOARD) += board/
obj-$(CONFIG_LTE_GDM724X) += gdm724x/
obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 6c00d6f765c6..6b2b942ebfc3 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -24,8 +24,8 @@ config ANDROID_LOW_MEMORY_KILLER
scripts (/init.rc), and it defines priority values with minimum free memory size
for each priority.
-source "drivers/staging/android/ion/Kconfig"
-
endif # if ANDROID
+source "drivers/staging/android/ion/Kconfig"
+
endmenu
diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig
index c8fb4134c55d..22ab23074c16 100644
--- a/drivers/staging/android/ion/Kconfig
+++ b/drivers/staging/android/ion/Kconfig
@@ -42,6 +42,13 @@ config ION_HISI
source "drivers/staging/android/ion/hisilicon/Kconfig"
+config ION_MXC
+ tristate "Ion for imx platform"
+ depends on ION
+ select VIDEOBUF2_DMA_CONTIG
+ help
+ Choose this option if you wish to use ion on imx platform.
+
config ION_OF
bool "Devicetree support for Ion"
depends on ION && OF_ADDRESS
@@ -52,3 +59,4 @@ config ION_OF
extensions
If using Ion and devicetree, you should say Y here
+
diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile
index 5d630a088381..724f014cb005 100644
--- a/drivers/staging/android/ion/Makefile
+++ b/drivers/staging/android/ion/Makefile
@@ -9,5 +9,5 @@ endif
obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o
obj-$(CONFIG_ION_TEGRA) += tegra/
obj-$(CONFIG_ION_HISI) += hisilicon/
+obj-$(CONFIG_ION_MXC) += mxc/
obj-$(CONFIG_ION_OF) += ion_of.o
-
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 6f9974cb0e15..d280d14a95e0 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -3,6 +3,7 @@
* drivers/staging/android/ion/ion.c
*
* Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -364,6 +365,26 @@ struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
return handle;
}
+/* for used in mxc_ion.c */
+int ion_handle_put_wrap(struct ion_handle *handle)
+{
+ return ion_handle_put(handle);
+}
+
+struct ion_handle *ion_handle_get_by_id_wrap(struct ion_client *client,
+ int id)
+{
+ return ion_handle_get_by_id(client, id);
+}
+
+struct device *ion_device_get_by_client(struct ion_client *client)
+{
+ if (client)
+ return client->dev->dev.this_device;
+ else
+ return NULL;
+}
+
static bool ion_handle_validate(struct ion_client *client,
struct ion_handle *handle)
{
@@ -1016,6 +1037,21 @@ static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
return 0;
}
+static void *ion_dma_buf_vmap(struct dma_buf *dmabuf)
+{
+ struct ion_buffer *buffer = dmabuf->priv;
+
+ if (ion_dma_buf_begin_cpu_access(dmabuf, DMA_NONE) != 0)
+ return NULL;
+
+ return buffer->vaddr;
+}
+
+static void ion_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
+{
+ ion_dma_buf_end_cpu_access(dmabuf, DMA_NONE);
+}
+
static struct dma_buf_ops dma_buf_ops = {
.map_dma_buf = ion_map_dma_buf,
.unmap_dma_buf = ion_unmap_dma_buf,
@@ -1027,6 +1063,8 @@ static struct dma_buf_ops dma_buf_ops = {
.kunmap_atomic = ion_dma_buf_kunmap,
.kmap = ion_dma_buf_kmap,
.kunmap = ion_dma_buf_kunmap,
+ .vmap = ion_dma_buf_vmap,
+ .vunmap = ion_dma_buf_vunmap,
};
struct dma_buf *ion_share_dma_buf(struct ion_client *client,
diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h
index 3c3b3245275d..2d4ef0d93d99 100644
--- a/drivers/staging/android/ion/ion_priv.h
+++ b/drivers/staging/android/ion/ion_priv.h
@@ -2,6 +2,7 @@
* drivers/staging/android/ion/ion_priv.h
*
* Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -470,4 +471,9 @@ int ion_handle_put(struct ion_handle *handle);
int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query);
+int ion_handle_put_wrap(struct ion_handle *handle);
+struct ion_handle *ion_handle_get_by_id_wrap(struct ion_client *client,
+ int id);
+struct device *ion_device_get_by_client(struct ion_client *client);
+
#endif /* _ION_PRIV_H */
diff --git a/drivers/staging/android/ion/mxc/Makefile b/drivers/staging/android/ion/mxc/Makefile
new file mode 100644
index 000000000000..df308e51837a
--- /dev/null
+++ b/drivers/staging/android/ion/mxc/Makefile
@@ -0,0 +1,2 @@
+ccflags-y += -I../
+obj-y += mxc_ion.o
diff --git a/drivers/staging/android/ion/mxc/mxc_ion.c b/drivers/staging/android/ion/mxc/mxc_ion.c
new file mode 100644
index 000000000000..14ae747a5385
--- /dev/null
+++ b/drivers/staging/android/ion/mxc/mxc_ion.c
@@ -0,0 +1,308 @@
+/*
+ * drivers/gpu/mxc/mxc_ion.c
+ *
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2012-2016 Freescale Semiconductor, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/uaccess.h>
+#include <media/videobuf2-dma-contig.h>
+#include <linux/dma-buf.h>
+
+#include "../ion_priv.h"
+
+static struct ion_device *idev;
+static int num_heaps = 1;
+static struct ion_heap **heaps;
+static int cacheable;
+
+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;
+
+ pdata = kzalloc(sizeof(struct ion_platform_data), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ heap = kzalloc(sizeof(struct ion_platform_heap), GFP_KERNEL);
+ if (!heap) {
+ kfree(pdata);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ heap->type = ION_HEAP_TYPE_DMA;
+ heap->priv = &pdev->dev;
+ heap->name = "mxc_ion";
+
+ pdata->heaps = heap;
+ pdata->nr = num_heaps;
+
+ ret = of_property_read_u32(node, "fsl,heap-cacheable", &val);
+ if (!ret)
+ cacheable = 1;
+
+ val = 0;
+ ret = of_property_read_u32(node, "fsl,heap-id", &val);
+ if (!ret)
+ heap->id = val;
+ else
+ heap->id = 0;
+
+ return pdata;
+}
+
+static long
+mxc_custom_ioctl(struct ion_client *client, unsigned int cmd, unsigned long arg)
+{
+ switch (cmd) {
+ case ION_IOC_PHYS:
+ {
+ struct ion_handle *handle;
+ struct ion_phys_data data;
+ struct device *dev;
+ void *vaddr;
+
+ if (copy_from_user(&data, (void __user *) arg,
+ sizeof(struct ion_phys_data)))
+ return -EFAULT;
+ handle = ion_handle_get_by_id_wrap(client, data.handle);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ vaddr = ion_map_kernel(client, handle);
+ ion_handle_put_wrap(handle);
+
+ if (IS_ERR(vaddr))
+ return PTR_ERR(vaddr);
+
+ dev = ion_device_get_by_client(client);
+ data.phys = virt_to_dma(dev, vaddr);
+
+ if (copy_to_user((void __user *) arg, &data,
+ sizeof(struct ion_phys_data)))
+ return -EFAULT;
+ return 0;
+ }
+ case ION_IOC_PHYS_DMA:
+ {
+ int ret = 0;
+ struct device *dev = NULL;
+ struct dma_buf *dmabuf = NULL;
+ unsigned long phys = 0;
+ u64 dma_mask = DMA_BIT_MASK(32);
+ size_t len = 0;
+ struct ion_phys_dma_data data;
+ const struct vb2_mem_ops *mem_ops =
+ &vb2_dma_contig_memops;
+ dma_addr_t *addr;
+ void *mem_priv;
+
+ if (copy_from_user(&data, (void __user *) arg,
+ sizeof(struct ion_phys_dma_data)))
+ return -EFAULT;
+
+ /* Get physical address from dmafd */
+ dmabuf = dma_buf_get(data.dmafd);
+ if (!dmabuf)
+ return -1;
+
+ dev = ion_device_get_by_client(client);
+ dev->dma_mask = &dma_mask;
+
+ mem_priv = mem_ops->attach_dmabuf(dev,
+ dmabuf, dmabuf->size,
+ DMA_BIDIRECTIONAL);
+ if (IS_ERR(mem_priv))
+ goto err1;
+ ret = mem_ops->map_dmabuf(mem_priv);
+ if (ret)
+ goto err0;
+
+ addr = mem_ops->cookie(mem_priv);
+ phys = *addr;
+ len = dmabuf->size;
+
+ data.phys = phys;
+ data.size = len;
+ if (copy_to_user((void __user *) arg, &data,
+ sizeof(struct ion_phys_dma_data))) {
+ ret = -EFAULT;
+ }
+
+ /* unmap and detach */
+ mem_ops->unmap_dmabuf(mem_priv);
+err0:
+ mem_ops->detach_dmabuf(mem_priv);
+err1:
+ dma_buf_put(dmabuf);
+
+ if (ret < 0)
+ return ret;
+ return 0;
+ }
+ case ION_IOC_PHYS_VIRT:
+ {
+ struct device *dev = NULL;
+ u64 dma_mask = DMA_BIT_MASK(32);
+ struct ion_phys_virt_data data;
+ const struct vb2_mem_ops *mem_ops =
+ &vb2_dma_contig_memops;
+ dma_addr_t *addr;
+ void *mem_priv;
+
+ if (copy_from_user(&data, (void __user *) arg,
+ sizeof(struct ion_phys_virt_data)))
+ return -EFAULT;
+
+ /* Get physical address from virtual address */
+ if (!data.virt)
+ return -1;
+
+ dev = ion_device_get_by_client(client);
+ dev->dma_mask = &dma_mask;
+
+ mem_priv = mem_ops->get_userptr(dev,
+ data.virt, data.size,
+ DMA_BIDIRECTIONAL);
+ if (IS_ERR(mem_priv))
+ return -1;
+
+ addr = mem_ops->cookie(mem_priv);
+ mem_ops->put_userptr(mem_priv);
+
+ data.phys = *addr;
+ if (copy_to_user((void __user *) arg, &data,
+ sizeof(struct ion_phys_virt_data)))
+ return -EFAULT;
+ return 0;
+ }
+ default:
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+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) {
+ pdata = mxc_ion_parse_of(pdev);
+ pdata_is_created = 1;
+ } 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);
+
+ idev = ion_device_create(mxc_custom_ioctl);
+ if (IS_ERR_OR_NULL(idev)) {
+ err = PTR_ERR(idev);
+ goto err;
+ }
+
+ /* 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);
+ if (IS_ERR_OR_NULL(heaps[i])) {
+ err = PTR_ERR(heaps[i]);
+ heaps[i] = NULL;
+ goto err;
+ }
+ ion_device_add_heap(idev, heaps[i]);
+ }
+ platform_set_drvdata(pdev, idev);
+ return 0;
+err:
+ for (i = 0; i < num_heaps; i++) {
+ if (heaps[i])
+ ion_heap_destroy(heaps[i]);
+ }
+ kfree(heaps);
+ if (pdata_is_created) {
+ kfree(pdata->heaps);
+ kfree(pdata);
+ }
+ return err;
+}
+
+int
+mxc_ion_remove(struct platform_device *pdev)
+{
+ struct ion_device *idev = platform_get_drvdata(pdev);
+ int i;
+
+ ion_device_destroy(idev);
+ for (i = 0; i < num_heaps; i++)
+ ion_heap_destroy(heaps[i]);
+ kfree(heaps);
+ return 0;
+}
+
+static struct of_device_id ion_match_table[] = {
+ {.compatible = "fsl,mxc-ion"},
+ {},
+};
+
+static struct platform_driver ion_driver = {
+ .probe = mxc_ion_probe,
+ .remove = mxc_ion_remove,
+ .driver = {
+ .name = "ion-mxc",
+ .of_match_table = ion_match_table,
+ },
+};
+
+static int __init
+ion_init(void)
+{
+ return platform_driver_register(&ion_driver);
+}
+
+static void __exit
+ion_exit(void)
+{
+ platform_driver_unregister(&ion_driver);
+}
+
+module_init(ion_init);
+module_exit(ion_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC ion allocator driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("fb");
diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h
index 14cd8738ecfc..401d59edcd0f 100644
--- a/drivers/staging/android/uapi/ion.h
+++ b/drivers/staging/android/uapi/ion.h
@@ -2,6 +2,7 @@
* drivers/staging/android/uapi/ion.h
*
* Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -46,6 +47,7 @@ enum ion_heap_type {
*/
};
+#define ION_CMA_HEAP_ID 0
#define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8)
/**
@@ -158,6 +160,23 @@ struct ion_heap_query {
__u32 reserved2;
};
+struct ion_phys_data {
+ ion_user_handle_t handle;
+ unsigned long phys;
+};
+
+struct ion_phys_dma_data {
+ unsigned long phys;
+ size_t size;
+ int dmafd;
+};
+
+struct ion_phys_virt_data {
+ unsigned long virt;
+ unsigned long phys;
+ size_t size;
+};
+
#define ION_IOC_MAGIC 'I'
/**
@@ -233,4 +252,10 @@ struct ion_heap_query {
#define ION_IOC_HEAP_QUERY _IOWR(ION_IOC_MAGIC, 8, \
struct ion_heap_query)
+#define ION_IOC_PHYS _IOWR(ION_IOC_MAGIC, 8, struct ion_phys_data)
+
+#define ION_IOC_PHYS_DMA _IOWR(ION_IOC_MAGIC, 9, struct ion_phys_dma_data)
+
+#define ION_IOC_PHYS_VIRT _IOWR(ION_IOC_MAGIC, 10, struct ion_phys_virt_data)
+
#endif /* _UAPI_LINUX_ION_H */