2 * videobuf2-dma-contig.c - DMA contig memory allocator for videobuf2
4 * Copyright (C) 2010 Samsung Electronics
6 * Author: Pawel Osciak <pawel@osciak.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation.
13 #include <linux/module.h>
14 #include <linux/slab.h>
15 #include <linux/dma-mapping.h>
17 #include <media/videobuf2-core.h>
18 #include <media/videobuf2-dma-contig.h>
19 #include <media/videobuf2-memops.h>
32 struct vb2_vmarea_handler handler;
36 struct vm_area_struct *vma;
39 /*********************************************/
40 /* callbacks for all buffers */
41 /*********************************************/
43 static void *vb2_dc_cookie(void *buf_priv)
45 struct vb2_dc_buf *buf = buf_priv;
47 return &buf->dma_addr;
50 static void *vb2_dc_vaddr(void *buf_priv)
52 struct vb2_dc_buf *buf = buf_priv;
57 static unsigned int vb2_dc_num_users(void *buf_priv)
59 struct vb2_dc_buf *buf = buf_priv;
61 return atomic_read(&buf->refcount);
64 /*********************************************/
65 /* callbacks for MMAP buffers */
66 /*********************************************/
68 static void vb2_dc_put(void *buf_priv)
70 struct vb2_dc_buf *buf = buf_priv;
72 if (!atomic_dec_and_test(&buf->refcount))
75 dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
79 static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
81 struct vb2_dc_conf *conf = alloc_ctx;
82 struct device *dev = conf->dev;
83 struct vb2_dc_buf *buf;
85 buf = kzalloc(sizeof *buf, GFP_KERNEL);
87 return ERR_PTR(-ENOMEM);
89 buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
91 dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
93 return ERR_PTR(-ENOMEM);
99 buf->handler.refcount = &buf->refcount;
100 buf->handler.put = vb2_dc_put;
101 buf->handler.arg = buf;
103 atomic_inc(&buf->refcount);
108 static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
110 struct vb2_dc_buf *buf = buf_priv;
113 printk(KERN_ERR "No buffer to map\n");
117 return vb2_mmap_pfn_range(vma, buf->dma_addr, buf->size,
118 &vb2_common_vm_ops, &buf->handler);
121 /*********************************************/
122 /* callbacks for USERPTR buffers */
123 /*********************************************/
125 static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
126 unsigned long size, int write)
128 struct vb2_dc_buf *buf;
129 struct vm_area_struct *vma;
130 dma_addr_t dma_addr = 0;
133 buf = kzalloc(sizeof *buf, GFP_KERNEL);
135 return ERR_PTR(-ENOMEM);
137 ret = vb2_get_contig_userptr(vaddr, size, &vma, &dma_addr);
139 printk(KERN_ERR "Failed acquiring VMA for vaddr 0x%08lx\n",
146 buf->dma_addr = dma_addr;
152 static void vb2_dc_put_userptr(void *mem_priv)
154 struct vb2_dc_buf *buf = mem_priv;
159 vb2_put_vma(buf->vma);
163 /*********************************************/
164 /* DMA CONTIG exported functions */
165 /*********************************************/
167 const struct vb2_mem_ops vb2_dma_contig_memops = {
168 .alloc = vb2_dc_alloc,
170 .cookie = vb2_dc_cookie,
171 .vaddr = vb2_dc_vaddr,
173 .get_userptr = vb2_dc_get_userptr,
174 .put_userptr = vb2_dc_put_userptr,
175 .num_users = vb2_dc_num_users,
177 EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
179 void *vb2_dma_contig_init_ctx(struct device *dev)
181 struct vb2_dc_conf *conf;
183 conf = kzalloc(sizeof *conf, GFP_KERNEL);
185 return ERR_PTR(-ENOMEM);
191 EXPORT_SYMBOL_GPL(vb2_dma_contig_init_ctx);
193 void vb2_dma_contig_cleanup_ctx(void *alloc_ctx)
197 EXPORT_SYMBOL_GPL(vb2_dma_contig_cleanup_ctx);
199 MODULE_DESCRIPTION("DMA-contig memory handling routines for videobuf2");
200 MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>");
201 MODULE_LICENSE("GPL");