aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSumit Semwal <sumit.semwal@ti.com>2011-10-24 11:50:18 +0530
committerSumit Semwal <sumit.semwal@ti.com>2011-10-28 17:38:58 +0530
commitd6b78a4758e507c59e418c52337c02c715870bb6 (patch)
treea9a5fcdea6fe093e98c02bd33bc951a32eeabd49
parente91628700b20eb4a3b15a96dcbb4131ec2c2038f (diff)
v4l:vb2: Add dma-contig allocator as dma_buf userv4l2-dmabuf-adaptation
This patch makes changes for adding dma-contig as a dma_buf user. It provides function implementations for the {import, acquire, release, put}_dmabuf() mem_ops of DMABUF memory type. Signed-off-by: Sumit Semwal <sumit.semwal@ti.com>
-rw-r--r--drivers/media/video/videobuf2-dma-contig.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index a790a5f8c06..a70a0f6c2aa 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -13,6 +13,8 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-buf.h>
#include <media/videobuf2-core.h>
#include <media/videobuf2-memops.h>
@@ -27,16 +29,23 @@ struct vb2_dc_buf {
dma_addr_t paddr;
unsigned long size;
struct vm_area_struct *vma;
+ struct dma_buf_attachment *db_attach;
atomic_t refcount;
struct vb2_vmarea_handler handler;
};
+struct vb2_dc_db_attach {
+ struct vb2_dc_buf *buf;
+ struct dma_buf_attachment db_attach;
+};
+
static void vb2_dma_contig_put(void *buf_priv);
static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
{
struct vb2_dc_conf *conf = alloc_ctx;
struct vb2_dc_buf *buf;
+ /* TODO: add db_attach processing while adding DMABUF as exporter */
buf = kzalloc(sizeof *buf, GFP_KERNEL);
if (!buf)
@@ -148,6 +157,118 @@ static void vb2_dma_contig_put_userptr(void *mem_priv)
kfree(buf);
}
+static void *vb2_dma_contig_import_dmabuf(void *alloc_ctx, int fd)
+{
+ struct vb2_dc_conf *conf = alloc_ctx;
+ struct vb2_dc_buf *buf;
+ struct dma_buf *dbuf;
+ struct dma_buf_attachment *dba;
+
+ buf = kzalloc(sizeof *buf, GFP_KERNEL);
+ if (!buf)
+ return ERR_PTR(-ENOMEM);
+
+ /* Get the dmabuf for given fd */
+ dbuf = dma_buf_get(fd);
+ if (IS_ERR(dbuf)) {
+ printk(KERN_ERR "failed to get dmabuf from fd %d\n", fd);
+ kfree(buf);
+ return dbuf;
+ }
+
+ /* create attachment for the dmabuf with the user device */
+ dba = dma_buf_attach(dbuf, conf->dev);
+ if (IS_ERR(dba)) {
+ printk(KERN_ERR "failed to attach dmabuf for fd %d\n", fd);
+ kfree(buf);
+ return dba;
+ }
+
+ buf->conf = conf;
+ buf->size = dba->dmabuf->size;
+ buf->db_attach = dba;
+ buf->paddr = 0; /* paddr is available only after acquire */
+
+ return buf;
+}
+
+static void vb2_dma_contig_put_dmabuf(void *mem_priv)
+{
+ struct vb2_dc_buf *buf = mem_priv;
+ struct dma_buf *dmabuf;
+
+ if (!buf)
+ return;
+ dmabuf = buf->db_attach->dmabuf;
+
+ /* detach this attachment */
+ dma_buf_detach(dmabuf, buf->db_attach);
+ buf->db_attach = NULL;
+
+ /* put the dmabuf reference */
+ dma_buf_put(dmabuf);
+
+ kfree(buf);
+}
+
+static void vb2_dma_contig_acquire_dmabuf(void *mem_priv)
+{
+ struct vb2_dc_buf *buf = mem_priv;
+ struct dma_buf *dmabuf;
+ struct scatterlist *sglist;
+ int nents;
+
+ if (!buf || !buf->db_attach)
+ return;
+
+ dmabuf = buf->db_attach->dmabuf;
+
+ /* get the associated scatterlist for this buffer */
+ sglist = dmabuf->ops->get_scatterlist(buf->db_attach,
+ DMA_BIDIRECTIONAL, &nents);
+ if (!sglist)
+ return;
+
+ /*
+ * convert sglist to paddr:
+ * Assumption: for dma-contig, dmabuf would map to single entry
+ * Will print a warning if it has more than one.
+ */
+ if (nents > 1)
+ printk(KERN_WARNING
+ "dmabuf scatterlist has more than 1 entry\n");
+
+ buf->paddr = sg_dma_address(sglist);
+ buf->size = sg_dma_len(sglist);
+
+ /* save this scatterlist in dmabuf for put_scatterlist */
+ dmabuf->priv = sglist;
+}
+
+static void vb2_dma_contig_release_dmabuf(void *mem_priv)
+{
+ struct vb2_dc_buf *buf = mem_priv;
+ struct dma_buf *dmabuf;
+ struct scatterlist *sglist;
+ int nents = 1;
+
+ if (!buf || !buf->db_attach)
+ return;
+
+ dmabuf = buf->db_attach->dmabuf;
+ sglist = dmabuf->priv;
+
+ /*
+ * Put the scatterlist for this buffer:
+ * Assumption is that for dma-contig, dmabuf would map to single entry
+ * hence nents is 1
+ */
+ dmabuf->ops->put_scatterlist(buf->db_attach, sglist, nents);
+
+ buf->paddr = 0;
+ buf->size = 0;
+}
+
const struct vb2_mem_ops vb2_dma_contig_memops = {
.alloc = vb2_dma_contig_alloc,
.put = vb2_dma_contig_put,
@@ -156,6 +277,10 @@ const struct vb2_mem_ops vb2_dma_contig_memops = {
.mmap = vb2_dma_contig_mmap,
.get_userptr = vb2_dma_contig_get_userptr,
.put_userptr = vb2_dma_contig_put_userptr,
+ .import_dmabuf = vb2_dma_contig_import_dmabuf,
+ .put_dmabuf = vb2_dma_contig_put_dmabuf,
+ .acquire_dmabuf = vb2_dma_contig_acquire_dmabuf,
+ .release_dmabuf = vb2_dma_contig_release_dmabuf,
.num_users = vb2_dma_contig_num_users,
};
EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);