V4L/DVB (11731): buf-dma-contig: remove sync operation
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / media / video / videobuf-dma-contig.c
blob08d3e17c450a322e3a57cd2fc8a1877bea599d4c
1 /*
2 * helper functions for physically contiguous capture buffers
4 * The functions support hardware lacking scatter gather support
5 * (i.e. the buffers must be linear in physical memory)
7 * Copyright (c) 2008 Magnus Damm
9 * Based on videobuf-vmalloc.c,
10 * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2
17 #include <linux/init.h>
18 #include <linux/module.h>
19 #include <linux/mm.h>
20 #include <linux/dma-mapping.h>
21 #include <media/videobuf-dma-contig.h>
23 struct videobuf_dma_contig_memory {
24 u32 magic;
25 void *vaddr;
26 dma_addr_t dma_handle;
27 unsigned long size;
30 #define MAGIC_DC_MEM 0x0733ac61
31 #define MAGIC_CHECK(is, should) \
32 if (unlikely((is) != (should))) { \
33 pr_err("magic mismatch: %x expected %x\n", (is), (should)); \
34 BUG(); \
37 static void
38 videobuf_vm_open(struct vm_area_struct *vma)
40 struct videobuf_mapping *map = vma->vm_private_data;
42 dev_dbg(map->q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n",
43 map, map->count, vma->vm_start, vma->vm_end);
45 map->count++;
48 static void videobuf_vm_close(struct vm_area_struct *vma)
50 struct videobuf_mapping *map = vma->vm_private_data;
51 struct videobuf_queue *q = map->q;
52 int i;
54 dev_dbg(map->q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n",
55 map, map->count, vma->vm_start, vma->vm_end);
57 map->count--;
58 if (0 == map->count) {
59 struct videobuf_dma_contig_memory *mem;
61 dev_dbg(map->q->dev, "munmap %p q=%p\n", map, q);
62 mutex_lock(&q->vb_lock);
64 /* We need first to cancel streams, before unmapping */
65 if (q->streaming)
66 videobuf_queue_cancel(q);
68 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
69 if (NULL == q->bufs[i])
70 continue;
72 if (q->bufs[i]->map != map)
73 continue;
75 mem = q->bufs[i]->priv;
76 if (mem) {
77 /* This callback is called only if kernel has
78 allocated memory and this memory is mmapped.
79 In this case, memory should be freed,
80 in order to do memory unmap.
83 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
85 /* vfree is not atomic - can't be
86 called with IRQ's disabled
88 dev_dbg(map->q->dev, "buf[%d] freeing %p\n",
89 i, mem->vaddr);
91 dma_free_coherent(q->dev, mem->size,
92 mem->vaddr, mem->dma_handle);
93 mem->vaddr = NULL;
96 q->bufs[i]->map = NULL;
97 q->bufs[i]->baddr = 0;
100 kfree(map);
102 mutex_unlock(&q->vb_lock);
106 static struct vm_operations_struct videobuf_vm_ops = {
107 .open = videobuf_vm_open,
108 .close = videobuf_vm_close,
111 static void *__videobuf_alloc(size_t size)
113 struct videobuf_dma_contig_memory *mem;
114 struct videobuf_buffer *vb;
116 vb = kzalloc(size + sizeof(*mem), GFP_KERNEL);
117 if (vb) {
118 mem = vb->priv = ((char *)vb) + size;
119 mem->magic = MAGIC_DC_MEM;
122 return vb;
125 static void *__videobuf_to_vmalloc(struct videobuf_buffer *buf)
127 struct videobuf_dma_contig_memory *mem = buf->priv;
129 BUG_ON(!mem);
130 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
132 return mem->vaddr;
135 static int __videobuf_iolock(struct videobuf_queue *q,
136 struct videobuf_buffer *vb,
137 struct v4l2_framebuffer *fbuf)
139 struct videobuf_dma_contig_memory *mem = vb->priv;
141 BUG_ON(!mem);
142 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
144 switch (vb->memory) {
145 case V4L2_MEMORY_MMAP:
146 dev_dbg(q->dev, "%s memory method MMAP\n", __func__);
148 /* All handling should be done by __videobuf_mmap_mapper() */
149 if (!mem->vaddr) {
150 dev_err(q->dev, "memory is not alloced/mmapped.\n");
151 return -EINVAL;
153 break;
154 case V4L2_MEMORY_USERPTR:
155 dev_dbg(q->dev, "%s memory method USERPTR\n", __func__);
157 /* The only USERPTR currently supported is the one needed for
158 read() method.
160 if (vb->baddr)
161 return -EINVAL;
163 mem->size = PAGE_ALIGN(vb->size);
164 mem->vaddr = dma_alloc_coherent(q->dev, mem->size,
165 &mem->dma_handle, GFP_KERNEL);
166 if (!mem->vaddr) {
167 dev_err(q->dev, "dma_alloc_coherent %ld failed\n",
168 mem->size);
169 return -ENOMEM;
172 dev_dbg(q->dev, "dma_alloc_coherent data is at %p (%ld)\n",
173 mem->vaddr, mem->size);
174 break;
175 case V4L2_MEMORY_OVERLAY:
176 default:
177 dev_dbg(q->dev, "%s memory method OVERLAY/unknown\n",
178 __func__);
179 return -EINVAL;
182 return 0;
185 static int __videobuf_mmap_free(struct videobuf_queue *q)
187 unsigned int i;
189 dev_dbg(q->dev, "%s\n", __func__);
190 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
191 if (q->bufs[i] && q->bufs[i]->map)
192 return -EBUSY;
195 return 0;
198 static int __videobuf_mmap_mapper(struct videobuf_queue *q,
199 struct vm_area_struct *vma)
201 struct videobuf_dma_contig_memory *mem;
202 struct videobuf_mapping *map;
203 unsigned int first;
204 int retval;
205 unsigned long size, offset = vma->vm_pgoff << PAGE_SHIFT;
207 dev_dbg(q->dev, "%s\n", __func__);
208 if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
209 return -EINVAL;
211 /* look for first buffer to map */
212 for (first = 0; first < VIDEO_MAX_FRAME; first++) {
213 if (!q->bufs[first])
214 continue;
216 if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
217 continue;
218 if (q->bufs[first]->boff == offset)
219 break;
221 if (VIDEO_MAX_FRAME == first) {
222 dev_dbg(q->dev, "invalid user space offset [offset=0x%lx]\n",
223 offset);
224 return -EINVAL;
227 /* create mapping + update buffer list */
228 map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
229 if (!map)
230 return -ENOMEM;
232 q->bufs[first]->map = map;
233 map->start = vma->vm_start;
234 map->end = vma->vm_end;
235 map->q = q;
237 q->bufs[first]->baddr = vma->vm_start;
239 mem = q->bufs[first]->priv;
240 BUG_ON(!mem);
241 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
243 mem->size = PAGE_ALIGN(q->bufs[first]->bsize);
244 mem->vaddr = dma_alloc_coherent(q->dev, mem->size,
245 &mem->dma_handle, GFP_KERNEL);
246 if (!mem->vaddr) {
247 dev_err(q->dev, "dma_alloc_coherent size %ld failed\n",
248 mem->size);
249 goto error;
251 dev_dbg(q->dev, "dma_alloc_coherent data is at addr %p (size %ld)\n",
252 mem->vaddr, mem->size);
254 /* Try to remap memory */
256 size = vma->vm_end - vma->vm_start;
257 size = (size < mem->size) ? size : mem->size;
259 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
260 retval = remap_pfn_range(vma, vma->vm_start,
261 mem->dma_handle >> PAGE_SHIFT,
262 size, vma->vm_page_prot);
263 if (retval) {
264 dev_err(q->dev, "mmap: remap failed with error %d. ", retval);
265 dma_free_coherent(q->dev, mem->size,
266 mem->vaddr, mem->dma_handle);
267 goto error;
270 vma->vm_ops = &videobuf_vm_ops;
271 vma->vm_flags |= VM_DONTEXPAND;
272 vma->vm_private_data = map;
274 dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
275 map, q, vma->vm_start, vma->vm_end,
276 (long int) q->bufs[first]->bsize,
277 vma->vm_pgoff, first);
279 videobuf_vm_open(vma);
281 return 0;
283 error:
284 kfree(map);
285 return -ENOMEM;
288 static int __videobuf_copy_to_user(struct videobuf_queue *q,
289 char __user *data, size_t count,
290 int nonblocking)
292 struct videobuf_dma_contig_memory *mem = q->read_buf->priv;
293 void *vaddr;
295 BUG_ON(!mem);
296 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
297 BUG_ON(!mem->vaddr);
299 /* copy to userspace */
300 if (count > q->read_buf->size - q->read_off)
301 count = q->read_buf->size - q->read_off;
303 vaddr = mem->vaddr;
305 if (copy_to_user(data, vaddr + q->read_off, count))
306 return -EFAULT;
308 return count;
311 static int __videobuf_copy_stream(struct videobuf_queue *q,
312 char __user *data, size_t count, size_t pos,
313 int vbihack, int nonblocking)
315 unsigned int *fc;
316 struct videobuf_dma_contig_memory *mem = q->read_buf->priv;
318 BUG_ON(!mem);
319 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
321 if (vbihack) {
322 /* dirty, undocumented hack -- pass the frame counter
323 * within the last four bytes of each vbi data block.
324 * We need that one to maintain backward compatibility
325 * to all vbi decoding software out there ... */
326 fc = (unsigned int *)mem->vaddr;
327 fc += (q->read_buf->size >> 2) - 1;
328 *fc = q->read_buf->field_count >> 1;
329 dev_dbg(q->dev, "vbihack: %d\n", *fc);
332 /* copy stuff using the common method */
333 count = __videobuf_copy_to_user(q, data, count, nonblocking);
335 if ((count == -EFAULT) && (pos == 0))
336 return -EFAULT;
338 return count;
341 static struct videobuf_qtype_ops qops = {
342 .magic = MAGIC_QTYPE_OPS,
344 .alloc = __videobuf_alloc,
345 .iolock = __videobuf_iolock,
346 .mmap_free = __videobuf_mmap_free,
347 .mmap_mapper = __videobuf_mmap_mapper,
348 .video_copy_to_user = __videobuf_copy_to_user,
349 .copy_stream = __videobuf_copy_stream,
350 .vmalloc = __videobuf_to_vmalloc,
353 void videobuf_queue_dma_contig_init(struct videobuf_queue *q,
354 struct videobuf_queue_ops *ops,
355 struct device *dev,
356 spinlock_t *irqlock,
357 enum v4l2_buf_type type,
358 enum v4l2_field field,
359 unsigned int msize,
360 void *priv)
362 videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
363 priv, &qops);
365 EXPORT_SYMBOL_GPL(videobuf_queue_dma_contig_init);
367 dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf)
369 struct videobuf_dma_contig_memory *mem = buf->priv;
371 BUG_ON(!mem);
372 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
374 return mem->dma_handle;
376 EXPORT_SYMBOL_GPL(videobuf_to_dma_contig);
378 void videobuf_dma_contig_free(struct videobuf_queue *q,
379 struct videobuf_buffer *buf)
381 struct videobuf_dma_contig_memory *mem = buf->priv;
383 /* mmapped memory can't be freed here, otherwise mmapped region
384 would be released, while still needed. In this case, the memory
385 release should happen inside videobuf_vm_close().
386 So, it should free memory only if the memory were allocated for
387 read() operation.
389 if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr)
390 return;
392 if (!mem)
393 return;
395 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
397 dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle);
398 mem->vaddr = NULL;
400 EXPORT_SYMBOL_GPL(videobuf_dma_contig_free);
402 MODULE_DESCRIPTION("helper module to manage video4linux dma contig buffers");
403 MODULE_AUTHOR("Magnus Damm");
404 MODULE_LICENSE("GPL");