aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2007-08-23 15:26:14 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-10-09 21:14:55 -0400
commit7a7d9a89d0307b1743d782197e2c5fc5ddf183f3 (patch)
treef5b1b220672128d089b5a6c469608e90482a6f60
parent7c596fa964806acb3b5ababb7ec4e1da35b140b3 (diff)
V4L/DVB (6251): Replace video-buf to a more generic approach
video-buf currently does two different tasks: - Manages video buffers with a common code that allows implementing all the V4L2 different modes of buffering; - Controls memory allocations While the first task is generic, the second were written to support PCI DMA Scatter/Gather needs. The original approach can't even work for those video capture hardware that don't support scatter/gather. I did one approach to make it more generic. While the approach worked fine for vivi driver, it were not generic enough to handle USB needs. This patch creates two different modules, one containing the generic video buffer handling (videobuf-core) and another with PCI DMA S/G. After this patch, it would be simpler to write an USB video-buf and a non-SG DMA module. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org> http://thread.gmane.org/gmane.comp.video.video4linux/34978/focus=34981 Reviewed-by: Ricardo Cerqueira <v4l@cerqueira.org>
-rw-r--r--drivers/media/video/videobuf-core.c976
-rw-r--r--drivers/media/video/videobuf-dma-sg.c772
-rw-r--r--include/media/videobuf-core.h236
-rw-r--r--include/media/videobuf-dma-sg.h142
4 files changed, 2126 insertions, 0 deletions
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c
new file mode 100644
index 000000000000..256501384af7
--- /dev/null
+++ b/drivers/media/video/videobuf-core.c
@@ -0,0 +1,976 @@
1/*
2 * generic helper functions for handling video4linux capture buffers
3 *
4 * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org>
5 *
6 * Highly based on video-buf written originally by:
7 * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
8 * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org>
9 * (c) 2006 Ted Walther and John Sokol
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2
14 */
15
16#include <linux/init.h>
17#include <linux/module.h>
18#include <linux/moduleparam.h>
19#include <linux/slab.h>
20#include <linux/interrupt.h>
21
22#include <media/videobuf-core.h>
23
24#define MAGIC_BUFFER 0x20070728
25#define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \
26 { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
27
28static int debug = 0;
29module_param(debug, int, 0644);
30
31MODULE_DESCRIPTION("helper module to manage video4linux buffers");
32MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
33MODULE_LICENSE("GPL");
34
35#define dprintk(level, fmt, arg...) if (debug >= level) \
36 printk(KERN_DEBUG "vbuf: " fmt , ## arg)
37
38/* --------------------------------------------------------------------- */
39
40#define CALL(q, f, arg...) \
41 ( (q->int_ops->f)? q->int_ops->f(arg) : 0)
42
43void* videobuf_alloc(struct videobuf_queue* q)
44{
45 struct videobuf_buffer *vb;
46
47 BUG_ON (q->msize<sizeof(*vb));
48
49 if (!q->int_ops || !q->int_ops->alloc) {
50 printk(KERN_ERR "No specific ops defined!\n");
51 BUG();
52 }
53
54 vb = q->int_ops->alloc(q->msize);
55
56 if (NULL != vb) {
57 init_waitqueue_head(&vb->done);
58 vb->magic = MAGIC_BUFFER;
59 }
60
61 return vb;
62}
63
64int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr)
65{
66 int retval = 0;
67 DECLARE_WAITQUEUE(wait, current);
68
69 MAGIC_CHECK(vb->magic,MAGIC_BUFFER);
70 add_wait_queue(&vb->done, &wait);
71 while (vb->state == STATE_ACTIVE || vb->state == STATE_QUEUED) {
72 if (non_blocking) {
73 retval = -EAGAIN;
74 break;
75 }
76 set_current_state(intr ? TASK_INTERRUPTIBLE
77 : TASK_UNINTERRUPTIBLE);
78 if (vb->state == STATE_ACTIVE || vb->state == STATE_QUEUED)
79 schedule();
80 set_current_state(TASK_RUNNING);
81 if (intr && signal_pending(current)) {
82 dprintk(1,"buffer waiton: -EINTR\n");
83 retval = -EINTR;
84 break;
85 }
86 }
87 remove_wait_queue(&vb->done, &wait);
88 return retval;
89}
90
91int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
92 struct v4l2_framebuffer *fbuf)
93{
94 MAGIC_CHECK(vb->magic,MAGIC_BUFFER);
95 MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
96
97 return CALL(q,iolock,q,vb,fbuf);
98}
99
100/* --------------------------------------------------------------------- */
101
102
103void videobuf_queue_init(struct videobuf_queue* q,
104 struct videobuf_queue_ops *ops,
105 void *dev,
106 spinlock_t *irqlock,
107 enum v4l2_buf_type type,
108 enum v4l2_field field,
109 unsigned int msize,
110 void *priv)
111{
112 memset(q,0,sizeof(*q));
113 q->irqlock = irqlock;
114 q->dev = dev;
115 q->type = type;
116 q->field = field;
117 q->msize = msize;
118 q->ops = ops;
119 q->priv_data = priv;
120
121 /* All buffer operations are mandatory */
122 BUG_ON (!q->ops->buf_setup);
123 BUG_ON (!q->ops->buf_prepare);
124 BUG_ON (!q->ops->buf_queue);
125 BUG_ON (!q->ops->buf_release);
126
127 mutex_init(&q->lock);
128 INIT_LIST_HEAD(&q->stream);
129}
130
131int videobuf_queue_is_busy(struct videobuf_queue *q)
132{
133 int i;
134
135 MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
136
137 if (q->streaming) {
138 dprintk(1,"busy: streaming active\n");
139 return 1;
140 }
141 if (q->reading) {
142 dprintk(1,"busy: pending read #1\n");
143 return 1;
144 }
145 if (q->read_buf) {
146 dprintk(1,"busy: pending read #2\n");
147 return 1;
148 }
149 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
150 if (NULL == q->bufs[i])
151 continue;
152 if (CALL(q,is_mmapped,q->bufs[i])) {
153 dprintk(1,"busy: buffer #%d mapped\n",i);
154 return 1;
155 }
156 if (q->bufs[i]->state == STATE_QUEUED) {
157 dprintk(1,"busy: buffer #%d queued\n",i);
158 return 1;
159 }
160 if (q->bufs[i]->state == STATE_ACTIVE) {
161 dprintk(1,"busy: buffer #%d avtive\n",i);
162 return 1;
163 }
164 }
165 return 0;
166}
167
168void videobuf_queue_cancel(struct videobuf_queue *q)
169{
170 unsigned long flags=0;
171 int i;
172
173 /* remove queued buffers from list */
174 if (q->irqlock)
175 spin_lock_irqsave(q->irqlock,flags);
176 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
177 if (NULL == q->bufs[i])
178 continue;
179 if (q->bufs[i]->state == STATE_QUEUED) {
180 list_del(&q->bufs[i]->queue);
181 q->bufs[i]->state = STATE_ERROR;
182 }
183 }
184 if (q->irqlock)
185 spin_unlock_irqrestore(q->irqlock,flags);
186
187 /* free all buffers + clear queue */
188 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
189 if (NULL == q->bufs[i])
190 continue;
191 q->ops->buf_release(q,q->bufs[i]);
192 }
193 INIT_LIST_HEAD(&q->stream);
194}
195
196/* --------------------------------------------------------------------- */
197
198enum v4l2_field videobuf_next_field(struct videobuf_queue *q)
199{
200 enum v4l2_field field = q->field;
201
202 BUG_ON(V4L2_FIELD_ANY == field);
203
204 if (V4L2_FIELD_ALTERNATE == field) {
205 if (V4L2_FIELD_TOP == q->last) {
206 field = V4L2_FIELD_BOTTOM;
207 q->last = V4L2_FIELD_BOTTOM;
208 } else {
209 field = V4L2_FIELD_TOP;
210 q->last = V4L2_FIELD_TOP;
211 }
212 }
213 return field;
214}
215
216static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b,
217 struct videobuf_buffer *vb, enum v4l2_buf_type type)
218{
219 MAGIC_CHECK(vb->magic,MAGIC_BUFFER);
220 MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
221
222 b->index = vb->i;
223 b->type = type;
224
225 b->memory = vb->memory;
226 switch (b->memory) {
227 case V4L2_MEMORY_MMAP:
228 b->m.offset = vb->boff;
229 b->length = vb->bsize;
230 break;
231 case V4L2_MEMORY_USERPTR:
232 b->m.userptr = vb->baddr;
233 b->length = vb->bsize;
234 break;
235 case V4L2_MEMORY_OVERLAY:
236 b->m.offset = vb->boff;
237 break;
238 }
239
240 b->flags = 0;
241 if (CALL(q,is_mmapped,vb))
242 b->flags |= V4L2_BUF_FLAG_MAPPED;
243
244 switch (vb->state) {
245 case STATE_PREPARED:
246 case STATE_QUEUED:
247 case STATE_ACTIVE:
248 b->flags |= V4L2_BUF_FLAG_QUEUED;
249 break;
250 case STATE_DONE:
251 case STATE_ERROR:
252 b->flags |= V4L2_BUF_FLAG_DONE;
253 break;
254 case STATE_NEEDS_INIT:
255 case STATE_IDLE:
256 /* nothing */
257 break;
258 }
259
260 if (vb->input != UNSET) {
261 b->flags |= V4L2_BUF_FLAG_INPUT;
262 b->input = vb->input;
263 }
264
265 b->field = vb->field;
266 b->timestamp = vb->ts;
267 b->bytesused = vb->size;
268 b->sequence = vb->field_count >> 1;
269}
270
271int videobuf_reqbufs(struct videobuf_queue *q,
272 struct v4l2_requestbuffers *req)
273{
274 unsigned int size,count;
275 int retval;
276
277 if (req->type != q->type) {
278 dprintk(1,"reqbufs: queue type invalid\n");
279 return -EINVAL;
280 }
281 if (req->count < 1) {
282 dprintk(1,"reqbufs: count invalid (%d)\n",req->count);
283 return -EINVAL;
284 }
285 if (req->memory != V4L2_MEMORY_MMAP &&
286 req->memory != V4L2_MEMORY_USERPTR &&
287 req->memory != V4L2_MEMORY_OVERLAY) {
288 dprintk(1,"reqbufs: memory type invalid\n");
289 return -EINVAL;
290 }
291
292 if (q->streaming) {
293 dprintk(1,"reqbufs: streaming already exists\n");
294 return -EBUSY;
295 }
296 if (!list_empty(&q->stream)) {
297 dprintk(1,"reqbufs: stream running\n");
298 return -EBUSY;
299 }
300
301 mutex_lock(&q->lock);
302 count = req->count;
303 if (count > VIDEO_MAX_FRAME)
304 count = VIDEO_MAX_FRAME;
305 size = 0;
306 q->ops->buf_setup(q,&count,&size);
307 size = PAGE_ALIGN(size);
308 dprintk(1,"reqbufs: bufs=%d, size=0x%x [%d pages total]\n",
309 count, size, (count*size)>>PAGE_SHIFT);
310
311 retval = videobuf_mmap_setup(q,count,size,req->memory);
312 if (retval < 0) {
313 dprintk(1,"reqbufs: mmap setup returned %d\n",retval);
314 goto done;
315 }
316
317 req->count = count;
318
319 done:
320 mutex_unlock(&q->lock);
321 return retval;
322}
323
324int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b)
325{
326 if (unlikely(b->type != q->type)) {
327 dprintk(1,"querybuf: Wrong type.\n");
328 return -EINVAL;
329 }
330 if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) {
331 dprintk(1,"querybuf: index out of range.\n");
332 return -EINVAL;
333 }
334 if (unlikely(NULL == q->bufs[b->index])) {
335 dprintk(1,"querybuf: buffer is null.\n");
336 return -EINVAL;
337 }
338 videobuf_status(q,b,q->bufs[b->index],q->type);
339 return 0;
340}
341
342int videobuf_qbuf(struct videobuf_queue *q,
343 struct v4l2_buffer *b)
344{
345 struct videobuf_buffer *buf;
346 enum v4l2_field field;
347 unsigned long flags=0;
348 int retval;
349
350 MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
351
352 mutex_lock(&q->lock);
353 retval = -EBUSY;
354 if (q->reading) {
355 dprintk(1,"qbuf: Reading running...\n");
356 goto done;
357 }
358 retval = -EINVAL;
359 if (b->type != q->type) {
360 dprintk(1,"qbuf: Wrong type.\n");
361 goto done;
362 }
363 if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) {
364 dprintk(1,"qbuf: index out of range.\n");
365 goto done;
366 }
367 buf = q->bufs[b->index];
368 if (NULL == buf) {
369 dprintk(1,"qbuf: buffer is null.\n");
370 goto done;
371 }
372 MAGIC_CHECK(buf->magic,MAGIC_BUFFER);
373 if (buf->memory != b->memory) {
374 dprintk(1,"qbuf: memory type is wrong.\n");
375 goto done;
376 }
377 if (buf->state != STATE_NEEDS_INIT && buf->state != STATE_IDLE) {
378 dprintk(1,"qbuf: buffer is already queued or active.\n");
379 goto done;
380 }
381
382 if (b->flags & V4L2_BUF_FLAG_INPUT) {
383 if (b->input >= q->inputs) {
384 dprintk(1,"qbuf: wrong input.\n");
385 goto done;
386 }
387 buf->input = b->input;
388 } else {
389 buf->input = UNSET;
390 }
391
392 switch (b->memory) {
393 case V4L2_MEMORY_MMAP:
394 if (0 == buf->baddr) {
395 dprintk(1,"qbuf: mmap requested but buffer addr is zero!\n");
396 goto done;
397 }
398 break;
399 case V4L2_MEMORY_USERPTR:
400 if (b->length < buf->bsize) {
401 dprintk(1,"qbuf: buffer length is not enough\n");
402 goto done;
403 }
404 if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr)
405 q->ops->buf_release(q,buf);
406 buf->baddr = b->m.userptr;
407 break;
408 case V4L2_MEMORY_OVERLAY:
409 buf->boff = b->m.offset;
410 break;
411 default:
412 dprintk(1,"qbuf: wrong memory type\n");
413 goto done;
414 }
415
416 dprintk(1,"qbuf: requesting next field\n");
417 field = videobuf_next_field(q);
418 retval = q->ops->buf_prepare(q,buf,field);
419 if (0 != retval) {
420 dprintk(1,"qbuf: buffer_prepare returned %d\n",retval);
421 goto done;
422 }
423
424 list_add_tail(&buf->stream,&q->stream);
425 if (q->streaming) {
426 if (q->irqlock)
427 spin_lock_irqsave(q->irqlock,flags);
428 q->ops->buf_queue(q,buf);
429 if (q->irqlock)
430 spin_unlock_irqrestore(q->irqlock,flags);
431 }
432 dprintk(1,"qbuf: succeded\n");
433 retval = 0;
434
435 done:
436 mutex_unlock(&q->lock);
437 return retval;
438}
439
440int videobuf_dqbuf(struct videobuf_queue *q,
441 struct v4l2_buffer *b, int nonblocking)
442{
443 struct videobuf_buffer *buf;
444 int retval;
445
446 MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
447
448 mutex_lock(&q->lock);
449 retval = -EBUSY;
450 if (q->reading) {
451 dprintk(1,"dqbuf: Reading running...\n");
452 goto done;
453 }
454 retval = -EINVAL;
455 if (b->type != q->type) {
456 dprintk(1,"dqbuf: Wrong type.\n");
457 goto done;
458 }
459 if (list_empty(&q->stream)) {
460 dprintk(1,"dqbuf: stream running\n");
461 goto done;
462 }
463 buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
464 retval = videobuf_waiton(buf, nonblocking, 1);
465 if (retval < 0) {
466 dprintk(1,"dqbuf: waiton returned %d\n",retval);
467 goto done;
468 }
469 switch (buf->state) {
470 case STATE_ERROR:
471 dprintk(1,"dqbuf: state is error\n");
472 retval = -EIO;
473 CALL(q,sync,q, buf);
474 buf->state = STATE_IDLE;
475 break;
476 case STATE_DONE:
477 dprintk(1,"dqbuf: state is done\n");
478 CALL(q,sync,q, buf);
479 buf->state = STATE_IDLE;
480 break;
481 default:
482 dprintk(1,"dqbuf: state invalid\n");
483 retval = -EINVAL;
484 goto done;
485 }
486 list_del(&buf->stream);
487 memset(b,0,sizeof(*b));
488 videobuf_status(q,b,buf,q->type);
489
490 done:
491 mutex_unlock(&q->lock);
492 return retval;
493}
494
495int videobuf_streamon(struct videobuf_queue *q)
496{
497 struct videobuf_buffer *buf;
498 struct list_head *list;
499 unsigned long flags=0;
500 int retval;
501
502 mutex_lock(&q->lock);
503 retval = -EBUSY;
504 if (q->reading)
505 goto done;
506 retval = 0;
507 if (q->streaming)
508 goto done;
509 q->streaming = 1;
510 if (q->irqlock)
511 spin_lock_irqsave(q->irqlock,flags);
512 list_for_each(list,&q->stream) {
513 buf = list_entry(list, struct videobuf_buffer, stream);
514 if (buf->state == STATE_PREPARED)
515 q->ops->buf_queue(q,buf);
516 }
517 if (q->irqlock)
518 spin_unlock_irqrestore(q->irqlock,flags);
519
520 done:
521 mutex_unlock(&q->lock);
522 return retval;
523}
524
525int videobuf_streamoff(struct videobuf_queue *q)
526{
527 int retval = -EINVAL;
528
529 mutex_lock(&q->lock);
530 if (!q->streaming)
531 goto done;
532 videobuf_queue_cancel(q);
533 q->streaming = 0;
534 retval = 0;
535
536 done:
537 mutex_unlock(&q->lock);
538 return retval;
539}
540
541static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q,
542 char __user *data,
543 size_t count, loff_t *ppos)
544{
545 enum v4l2_field field;
546 unsigned long flags=0;
547 int retval;
548
549 MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
550
551 /* setup stuff */
552 q->read_buf = videobuf_alloc(q);
553 if (NULL == q->read_buf)
554 return -ENOMEM;
555
556 q->read_buf->memory = V4L2_MEMORY_USERPTR;
557 q->read_buf->baddr = (unsigned long)data;
558 q->read_buf->bsize = count;
559
560 field = videobuf_next_field(q);
561 retval = q->ops->buf_prepare(q,q->read_buf,field);
562 if (0 != retval)
563 goto done;
564
565 /* start capture & wait */
566 if (q->irqlock)
567 spin_lock_irqsave(q->irqlock,flags);
568 q->ops->buf_queue(q,q->read_buf);
569 if (q->irqlock)
570 spin_unlock_irqrestore(q->irqlock,flags);
571 retval = videobuf_waiton(q->read_buf,0,0);
572 if (0 == retval) {
573 CALL(q,sync,q,q->read_buf);
574 if (STATE_ERROR == q->read_buf->state)
575 retval = -EIO;
576 else
577 retval = q->read_buf->size;
578 }
579
580 done:
581 /* cleanup */
582 q->ops->buf_release(q,q->read_buf);
583 kfree(q->read_buf);
584 q->read_buf = NULL;
585 return retval;
586}
587
588ssize_t videobuf_read_one(struct videobuf_queue *q,
589 char __user *data, size_t count, loff_t *ppos,
590 int nonblocking)
591{
592 enum v4l2_field field;
593 unsigned long flags=0;
594 unsigned size, nbufs;
595 int retval;
596
597 MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
598
599 mutex_lock(&q->lock);
600
601 nbufs = 1; size = 0;
602 q->ops->buf_setup(q,&nbufs,&size);
603
604 if (NULL == q->read_buf &&
605 count >= size &&
606 !nonblocking) {
607 retval = videobuf_read_zerocopy(q,data,count,ppos);
608 if (retval >= 0 || retval == -EIO)
609 /* ok, all done */
610 goto done;
611 /* fallback to kernel bounce buffer on failures */
612 }
613
614 if (NULL == q->read_buf) {
615 /* need to capture a new frame */
616 retval = -ENOMEM;
617 q->read_buf = videobuf_alloc(q);
618
619 dprintk(1,"video alloc=0x%p\n", q->read_buf);
620 if (NULL == q->read_buf)
621 goto done;
622 q->read_buf->memory = V4L2_MEMORY_USERPTR;
623 q->read_buf->bsize = count; /* preferred size */
624 field = videobuf_next_field(q);
625 retval = q->ops->buf_prepare(q,q->read_buf,field);
626
627 if (0 != retval) {
628 kfree (q->read_buf);
629 q->read_buf = NULL;
630 goto done;
631 }
632 if (q->irqlock)
633 spin_lock_irqsave(q->irqlock,flags);
634
635 q->ops->buf_queue(q,q->read_buf);
636 if (q->irqlock)
637 spin_unlock_irqrestore(q->irqlock,flags);
638 q->read_off = 0;
639 }
640
641 /* wait until capture is done */
642 retval = videobuf_waiton(q->read_buf, nonblocking, 1);
643 if (0 != retval)
644 goto done;
645
646 CALL(q,sync,q,q->read_buf);
647
648 if (STATE_ERROR == q->read_buf->state) {
649 /* catch I/O errors */
650 q->ops->buf_release(q,q->read_buf);
651 kfree(q->read_buf);
652 q->read_buf = NULL;
653 retval = -EIO;
654 goto done;
655 }
656
657 /* Copy to userspace */
658 retval=CALL(q,copy_to_user,q,data,count,nonblocking);
659 if (retval<0)
660 goto done;
661
662 q->read_off += retval;
663 if (q->read_off == q->read_buf->size) {
664 /* all data copied, cleanup */
665 q->ops->buf_release(q,q->read_buf);
666 kfree(q->read_buf);
667 q->read_buf = NULL;
668 }
669
670 done:
671 mutex_unlock(&q->lock);
672 return retval;
673}
674
675int videobuf_read_start(struct videobuf_queue *q)
676{
677 enum v4l2_field field;
678 unsigned long flags=0;
679 int count = 0, size = 0;
680 int err, i;
681
682 q->ops->buf_setup(q,&count,&size);
683 if (count < 2)
684 count = 2;
685 if (count > VIDEO_MAX_FRAME)
686 count = VIDEO_MAX_FRAME;
687 size = PAGE_ALIGN(size);
688
689 err = videobuf_mmap_setup(q, count, size, V4L2_MEMORY_USERPTR);
690 if (err)
691 return err;
692
693 for (i = 0; i < count; i++) {
694 field = videobuf_next_field(q);
695 err = q->ops->buf_prepare(q,q->bufs[i],field);
696 if (err)
697 return err;
698 list_add_tail(&q->bufs[i]->stream, &q->stream);
699 }
700 if (q->irqlock)
701 spin_lock_irqsave(q->irqlock,flags);
702 for (i = 0; i < count; i++)
703 q->ops->buf_queue(q,q->bufs[i]);
704 if (q->irqlock)
705 spin_unlock_irqrestore(q->irqlock,flags);
706 q->reading = 1;
707 return 0;
708}
709
710void videobuf_read_stop(struct videobuf_queue *q)
711{
712 int i;
713
714 videobuf_queue_cancel(q);
715 videobuf_mmap_free(q);
716 INIT_LIST_HEAD(&q->stream);
717 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
718 if (NULL == q->bufs[i])
719 continue;
720 kfree(q->bufs[i]);
721 q->bufs[i] = NULL;
722 }
723 q->read_buf = NULL;
724 q->reading = 0;
725}
726
727ssize_t videobuf_read_stream(struct videobuf_queue *q,
728 char __user *data, size_t count, loff_t *ppos,
729 int vbihack, int nonblocking)
730{
731 int rc, retval;
732 unsigned long flags=0;
733
734 MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
735
736 dprintk(2,"%s\n",__FUNCTION__);
737 mutex_lock(&q->lock);
738 retval = -EBUSY;
739 if (q->streaming)
740 goto done;
741 if (!q->reading) {
742 retval = videobuf_read_start(q);
743 if (retval < 0)
744 goto done;
745 }
746
747 retval = 0;
748 while (count > 0) {
749 /* get / wait for data */
750 if (NULL == q->read_buf) {
751 q->read_buf = list_entry(q->stream.next,
752 struct videobuf_buffer,
753 stream);
754 list_del(&q->read_buf->stream);
755 q->read_off = 0;
756 }
757 rc = videobuf_waiton(q->read_buf, nonblocking, 1);
758 if (rc < 0) {
759 if (0 == retval)
760 retval = rc;
761 break;
762 }
763
764 if (q->read_buf->state == STATE_DONE) {
765 rc = CALL (q,copy_stream, q, data, count,
766 retval, vbihack, nonblocking);
767 if (rc < 0) {
768 retval = rc;
769 break;
770 }
771 retval += rc;
772 count -= rc;
773 q->read_off += rc;
774 } else {
775 /* some error */
776 q->read_off = q->read_buf->size;
777 if (0 == retval)
778 retval = -EIO;
779 }
780
781 /* requeue buffer when done with copying */
782 if (q->read_off == q->read_buf->size) {
783 list_add_tail(&q->read_buf->stream,
784 &q->stream);
785 if (q->irqlock)
786 spin_lock_irqsave(q->irqlock,flags);
787 q->ops->buf_queue(q,q->read_buf);
788 if (q->irqlock)
789 spin_unlock_irqrestore(q->irqlock,flags);
790 q->read_buf = NULL;
791 }
792 if (retval < 0)
793 break;
794 }
795
796 done:
797 mutex_unlock(&q->lock);
798 return retval;
799}
800
801unsigned int videobuf_poll_stream(struct file *file,
802 struct videobuf_queue *q,
803 poll_table *wait)
804{
805 struct videobuf_buffer *buf = NULL;
806 unsigned int rc = 0;
807
808 mutex_lock(&q->lock);
809 if (q->streaming) {
810 if (!list_empty(&q->stream))
811 buf = list_entry(q->stream.next,
812 struct videobuf_buffer, stream);
813 } else {
814 if (!q->reading)
815 videobuf_read_start(q);
816 if (!q->reading) {
817 rc = POLLERR;
818 } else if (NULL == q->read_buf) {
819 q->read_buf = list_entry(q->stream.next,
820 struct videobuf_buffer,
821 stream);
822 list_del(&q->read_buf->stream);
823 q->read_off = 0;
824 }
825 buf = q->read_buf;
826 }
827 if (!buf)
828 rc = POLLERR;
829
830 if (0 == rc) {
831 poll_wait(file, &buf->done, wait);
832 if (buf->state == STATE_DONE ||
833 buf->state == STATE_ERROR)
834 rc = POLLIN|POLLRDNORM;
835 }
836 mutex_unlock(&q->lock);
837 return rc;
838}
839
840int videobuf_mmap_setup(struct videobuf_queue *q,
841 unsigned int bcount, unsigned int bsize,
842 enum v4l2_memory memory)
843{
844 unsigned int i;
845 int err;
846
847 MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
848
849 err = videobuf_mmap_free(q);
850 if (0 != err)
851 return err;
852
853 /* Allocate and initialize buffers */
854 for (i = 0; i < bcount; i++) {
855 q->bufs[i] = videobuf_alloc(q);
856
857 q->bufs[i]->i = i;
858 q->bufs[i]->input = UNSET;
859 q->bufs[i]->memory = memory;
860 q->bufs[i]->bsize = bsize;
861 switch (memory) {
862 case V4L2_MEMORY_MMAP:
863 q->bufs[i]->boff = bsize * i;
864 break;
865 case V4L2_MEMORY_USERPTR:
866 case V4L2_MEMORY_OVERLAY:
867 /* nothing */
868 break;
869 }
870 }
871
872 dprintk(1,"mmap setup: %d buffers, %d bytes each\n",
873 bcount,bsize);
874
875 return 0;
876}
877
878int videobuf_mmap_free(struct videobuf_queue *q)
879{
880 int i;
881 int rc;
882
883 MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
884
885 rc = CALL(q,mmap_free,q);
886 if (rc<0)
887 return rc;
888
889 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
890 if (NULL == q->bufs[i])
891 continue;
892 q->ops->buf_release(q,q->bufs[i]);
893 kfree(q->bufs[i]);
894 q->bufs[i] = NULL;
895 }
896
897 return rc;
898}
899
900int videobuf_mmap_mapper(struct videobuf_queue *q,
901 struct vm_area_struct *vma)
902{
903 int retval;
904
905 MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
906
907 mutex_lock(&q->lock);
908 retval=CALL(q,mmap_mapper,q,vma);
909 mutex_unlock(&q->lock);
910
911 return retval;
912}
913
914#ifdef CONFIG_VIDEO_V4L1_COMPAT
915int videobuf_cgmbuf(struct videobuf_queue *q,
916 struct video_mbuf *mbuf, int count)
917{
918 struct v4l2_requestbuffers req;
919 int rc,i;
920
921 MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
922
923 memset(&req,0,sizeof(req));
924 req.type = q->type;
925 req.count = count;
926 req.memory = V4L2_MEMORY_MMAP;
927 rc = videobuf_reqbufs(q,&req);
928 if (rc < 0)
929 return rc;
930
931 mbuf->frames = req.count;
932 mbuf->size = 0;
933 for (i = 0; i < mbuf->frames; i++) {
934 mbuf->offsets[i] = q->bufs[i]->boff;
935 mbuf->size += q->bufs[i]->bsize;
936 }
937
938 return 0;
939}
940#endif
941
942/* --------------------------------------------------------------------- */
943
944EXPORT_SYMBOL_GPL(videobuf_waiton);
945EXPORT_SYMBOL_GPL(videobuf_iolock);
946
947EXPORT_SYMBOL_GPL(videobuf_alloc);
948
949EXPORT_SYMBOL_GPL(videobuf_queue_init);
950EXPORT_SYMBOL_GPL(videobuf_queue_cancel);
951EXPORT_SYMBOL_GPL(videobuf_queue_is_busy);
952
953EXPORT_SYMBOL_GPL(videobuf_next_field);
954EXPORT_SYMBOL_GPL(videobuf_reqbufs);
955EXPORT_SYMBOL_GPL(videobuf_querybuf);
956EXPORT_SYMBOL_GPL(videobuf_qbuf);
957EXPORT_SYMBOL_GPL(videobuf_dqbuf);
958EXPORT_SYMBOL_GPL(videobuf_cgmbuf);
959EXPORT_SYMBOL_GPL(videobuf_streamon);
960EXPORT_SYMBOL_GPL(videobuf_streamoff);
961
962EXPORT_SYMBOL_GPL(videobuf_read_start);
963EXPORT_SYMBOL_GPL(videobuf_read_stop);
964EXPORT_SYMBOL_GPL(videobuf_read_stream);
965EXPORT_SYMBOL_GPL(videobuf_read_one);
966EXPORT_SYMBOL_GPL(videobuf_poll_stream);
967
968EXPORT_SYMBOL_GPL(videobuf_mmap_setup);
969EXPORT_SYMBOL_GPL(videobuf_mmap_free);
970EXPORT_SYMBOL_GPL(videobuf_mmap_mapper);
971
972/*
973 * Local variables:
974 * c-basic-offset: 8
975 * End:
976 */
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c
new file mode 100644
index 000000000000..3345877c47d4
--- /dev/null
+++ b/drivers/media/video/videobuf-dma-sg.c
@@ -0,0 +1,772 @@
1/*
2 * helper functions for PCI DMA video4linux capture buffers
3 *
4 * The functions expect the hardware being able to scatter gatter
5 * (i.e. the buffers are not linear in physical memory, but fragmented
6 * into PAGE_SIZE chunks). They also assume the driver does not need
7 * to touch the video data.
8 *
9 * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org>
10 *
11 * Highly based on video-buf written originally by:
12 * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
13 * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org>
14 * (c) 2006 Ted Walther and John Sokol
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2
19 */
20
21#include <linux/init.h>
22#include <linux/module.h>
23#include <linux/moduleparam.h>
24#include <linux/slab.h>
25#include <linux/interrupt.h>
26
27#include <linux/pci.h>
28#include <linux/vmalloc.h>
29#include <linux/pagemap.h>
30#include <asm/page.h>
31#include <asm/pgtable.h>
32
33#include <media/videobuf-dma-sg.h>
34
35#define MAGIC_DMABUF 0x19721112
36#define MAGIC_SG_MEM 0x17890714
37
38#define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \
39 { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
40
41static int debug = 0;
42module_param(debug, int, 0644);
43
44MODULE_DESCRIPTION("helper module to manage video4linux pci dma sg buffers");
45MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
46MODULE_LICENSE("GPL");
47
48#define dprintk(level, fmt, arg...) if (debug >= level) \
49 printk(KERN_DEBUG "vbuf-sg: " fmt , ## arg)
50
51/* --------------------------------------------------------------------- */
52
53struct scatterlist*
54videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages)
55{
56 struct scatterlist *sglist;
57 struct page *pg;
58 int i;
59
60 sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
61 if (NULL == sglist)
62 return NULL;
63 for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
64 pg = vmalloc_to_page(virt);
65 if (NULL == pg)
66 goto err;
67 BUG_ON(PageHighMem(pg));
68 sglist[i].page = pg;
69 sglist[i].length = PAGE_SIZE;
70 }
71 return sglist;
72
73 err:
74 kfree(sglist);
75 return NULL;
76}
77
78struct scatterlist*
79videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
80{
81 struct scatterlist *sglist;
82 int i = 0;
83
84 if (NULL == pages[0])
85 return NULL;
86 sglist = kcalloc(nr_pages, sizeof(*sglist), GFP_KERNEL);
87 if (NULL == sglist)
88 return NULL;
89
90 if (NULL == pages[0])
91 goto nopage;
92 if (PageHighMem(pages[0]))
93 /* DMA to highmem pages might not work */
94 goto highmem;
95 sglist[0].page = pages[0];
96 sglist[0].offset = offset;
97 sglist[0].length = PAGE_SIZE - offset;
98 for (i = 1; i < nr_pages; i++) {
99 if (NULL == pages[i])
100 goto nopage;
101 if (PageHighMem(pages[i]))
102 goto highmem;
103 sglist[i].page = pages[i];
104 sglist[i].length = PAGE_SIZE;
105 }
106 return sglist;
107
108 nopage:
109 dprintk(2,"sgl: oops - no page\n");
110 kfree(sglist);
111 return NULL;
112
113 highmem:
114 dprintk(2,"sgl: oops - highmem page\n");
115 kfree(sglist);
116 return NULL;
117}
118
119/* --------------------------------------------------------------------- */
120
121struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf)
122{
123 struct videbuf_pci_sg_memory *mem=buf->priv;
124 BUG_ON (!mem);
125
126 MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
127
128 return &mem->dma;
129}
130
131void videobuf_dma_init(struct videobuf_dmabuf *dma)
132{
133 memset(dma,0,sizeof(*dma));
134 dma->magic = MAGIC_DMABUF;
135}
136
137int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
138 unsigned long data, unsigned long size)
139{
140 unsigned long first,last;
141 int err, rw = 0;
142
143 dma->direction = direction;
144 switch (dma->direction) {
145 case PCI_DMA_FROMDEVICE: rw = READ; break;
146 case PCI_DMA_TODEVICE: rw = WRITE; break;
147 default: BUG();
148 }
149
150 first = (data & PAGE_MASK) >> PAGE_SHIFT;
151 last = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT;
152 dma->offset = data & ~PAGE_MASK;
153 dma->nr_pages = last-first+1;
154 dma->pages = kmalloc(dma->nr_pages * sizeof(struct page*),
155 GFP_KERNEL);
156 if (NULL == dma->pages)
157 return -ENOMEM;
158 dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n",
159 data,size,dma->nr_pages);
160
161 dma->varea = (void *) data;
162
163 down_read(&current->mm->mmap_sem);
164 err = get_user_pages(current,current->mm,
165 data & PAGE_MASK, dma->nr_pages,
166 rw == READ, 1, /* force */
167 dma->pages, NULL);
168 up_read(&current->mm->mmap_sem);
169 if (err != dma->nr_pages) {
170 dma->nr_pages = (err >= 0) ? err : 0;
171 dprintk(1,"get_user_pages: err=%d [%d]\n",err,dma->nr_pages);
172 return err < 0 ? err : -EINVAL;
173 }
174 return 0;
175}
176
177int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
178 int nr_pages)
179{
180 dprintk(1,"init kernel [%d pages]\n",nr_pages);
181 dma->direction = direction;
182 dma->vmalloc = vmalloc_32(nr_pages << PAGE_SHIFT);
183 if (NULL == dma->vmalloc) {
184 dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages);
185 return -ENOMEM;
186 }
187 dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n",
188 (unsigned long)dma->vmalloc,
189 nr_pages << PAGE_SHIFT);
190 memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT);
191 dma->nr_pages = nr_pages;
192 return 0;
193}
194
195int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
196 dma_addr_t addr, int nr_pages)
197{
198 dprintk(1,"init overlay [%d pages @ bus 0x%lx]\n",
199 nr_pages,(unsigned long)addr);
200 dma->direction = direction;
201 if (0 == addr)
202 return -EINVAL;
203
204 dma->bus_addr = addr;
205 dma->nr_pages = nr_pages;
206 return 0;
207}
208
209int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
210{
211 void *dev=q->dev;
212 struct videobuf_dma_sg_ops *ops=q->priv_ops;
213
214 MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
215 BUG_ON(0 == dma->nr_pages);
216
217 if (dma->pages) {
218 dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages,
219 dma->offset);
220 }
221 if (dma->vmalloc) {
222 dma->sglist = videobuf_vmalloc_to_sg
223 (dma->vmalloc,dma->nr_pages);
224 }
225 if (dma->bus_addr) {
226 dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL);
227 if (NULL != dma->sglist) {
228 dma->sglen = 1;
229 sg_dma_address(&dma->sglist[0]) = dma->bus_addr & PAGE_MASK;
230 dma->sglist[0].offset = dma->bus_addr & ~PAGE_MASK;
231 sg_dma_len(&dma->sglist[0]) = dma->nr_pages * PAGE_SIZE;
232 }
233 }
234 if (NULL == dma->sglist) {
235 dprintk(1,"scatterlist is NULL\n");
236 return -ENOMEM;
237 }
238 if (!dma->bus_addr) {
239 if (ops && ops->vb_map_sg) {
240 dma->sglen = ops->vb_map_sg(dev,dma->sglist,
241 dma->nr_pages, dma->direction);
242 }
243 if (0 == dma->sglen) {
244 printk(KERN_WARNING
245 "%s: videobuf_map_sg failed\n",__FUNCTION__);
246 kfree(dma->sglist);
247 dma->sglist = NULL;
248 dma->sglen = 0;
249 return -EIO;
250 }
251 }
252 return 0;
253}
254
255int videobuf_dma_sync(struct videobuf_queue *q,struct videobuf_dmabuf *dma)
256{
257 void *dev=q->dev;
258 struct videobuf_dma_sg_ops *ops=q->priv_ops;
259
260 MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
261 BUG_ON(!dma->sglen);
262
263 if (!dma->bus_addr && ops && ops->vb_dma_sync_sg)
264 ops->vb_dma_sync_sg(dev,dma->sglist,dma->nr_pages,
265 dma->direction);
266
267 return 0;
268}
269
270int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
271{
272 void *dev=q->dev;
273 struct videobuf_dma_sg_ops *ops=q->priv_ops;
274
275 MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
276 if (!dma->sglen)
277 return 0;
278
279 if (!dma->bus_addr && ops && ops->vb_unmap_sg)
280 ops->vb_unmap_sg(dev,dma->sglist,dma->nr_pages,
281 dma->direction);
282 kfree(dma->sglist);
283 dma->sglist = NULL;
284 dma->sglen = 0;
285 return 0;
286}
287
288int videobuf_dma_free(struct videobuf_dmabuf *dma)
289{
290 MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
291 BUG_ON(dma->sglen);
292
293 if (dma->pages) {
294 int i;
295 for (i=0; i < dma->nr_pages; i++)
296 page_cache_release(dma->pages[i]);
297 kfree(dma->pages);
298 dma->pages = NULL;
299 }
300
301 vfree(dma->vmalloc);
302 dma->vmalloc = NULL;
303 dma->varea = NULL;
304
305 if (dma->bus_addr) {
306 dma->bus_addr = 0;
307 }
308 dma->direction = PCI_DMA_NONE;
309 return 0;
310}
311
312/* --------------------------------------------------------------------- */
313
314int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma)
315{
316 struct videobuf_queue q;
317 struct videobuf_dma_sg_ops qops;
318
319 q.dev=pci;
320 qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg;
321 qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
322 q.priv_ops = &qops;
323
324 return (videobuf_dma_map(&q,dma));
325}
326
327int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma)
328{
329 struct videobuf_queue q;
330 struct videobuf_dma_sg_ops qops;
331
332 q.dev=pci;
333 qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg;
334 qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
335 q.priv_ops = &qops;
336
337 return (videobuf_dma_unmap(&q,dma));
338}
339
340/* --------------------------------------------------------------------- */
341
342static void
343videobuf_vm_open(struct vm_area_struct *vma)
344{
345 struct videobuf_mapping *map = vma->vm_private_data;
346
347 dprintk(2,"vm_open %p [count=%d,vma=%08lx-%08lx]\n",map,
348 map->count,vma->vm_start,vma->vm_end);
349 map->count++;
350}
351
352static void
353videobuf_vm_close(struct vm_area_struct *vma)
354{
355 struct videobuf_mapping *map = vma->vm_private_data;
356 struct videobuf_queue *q = map->q;
357 struct videbuf_pci_sg_memory *mem;
358 int i;
359
360 dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map,
361 map->count,vma->vm_start,vma->vm_end);
362
363 map->count--;
364 if (0 == map->count) {
365 dprintk(1,"munmap %p q=%p\n",map,q);
366 mutex_lock(&q->lock);
367 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
368 if (NULL == q->bufs[i])
369 continue;
370 mem=q->bufs[i]->priv;
371
372 if (!mem)
373 continue;
374
375 MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
376
377 if (mem->map != map)
378 continue;
379 mem->map = NULL;
380 q->bufs[i]->baddr = 0;
381 q->ops->buf_release(q,q->bufs[i]);
382 }
383 mutex_unlock(&q->lock);
384 kfree(map);
385 }
386 return;
387}
388
389/*
390 * Get a anonymous page for the mapping. Make sure we can DMA to that
391 * memory location with 32bit PCI devices (i.e. don't use highmem for
392 * now ...). Bounce buffers don't work very well for the data rates
393 * video capture has.
394 */
395static struct page*
396videobuf_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr,
397 int *type)
398{
399 struct page *page;
400
401 dprintk(3,"nopage: fault @ %08lx [vma %08lx-%08lx]\n",
402 vaddr,vma->vm_start,vma->vm_end);
403 if (vaddr > vma->vm_end)
404 return NOPAGE_SIGBUS;
405 page = alloc_page(GFP_USER | __GFP_DMA32);
406 if (!page)
407 return NOPAGE_OOM;
408 clear_user_page(page_address(page), vaddr, page);
409 if (type)
410 *type = VM_FAULT_MINOR;
411 return page;
412}
413
414static struct vm_operations_struct videobuf_vm_ops =
415{
416 .open = videobuf_vm_open,
417 .close = videobuf_vm_close,
418 .nopage = videobuf_vm_nopage,
419};
420
421/* ---------------------------------------------------------------------
422 * PCI handlers for the generic methods
423 */
424
425/* Allocated area consists on 3 parts:
426 struct video_buffer
427 struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
428 struct videobuf_pci_sg_memory
429 */
430
431static void *__videobuf_alloc(size_t size)
432{
433 struct videbuf_pci_sg_memory *mem;
434 struct videobuf_buffer *vb;
435
436 vb = kzalloc(size+sizeof(*mem),GFP_KERNEL);
437
438 mem = vb->priv = ((char *)vb)+size;
439 mem->magic=MAGIC_SG_MEM;
440
441 videobuf_dma_init(&mem->dma);
442
443 dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
444 __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
445 mem,(long)sizeof(*mem));
446
447 return vb;
448}
449
450static int __videobuf_iolock (struct videobuf_queue* q,
451 struct videobuf_buffer *vb,
452 struct v4l2_framebuffer *fbuf)
453{
454 int err,pages;
455 dma_addr_t bus;
456 struct videbuf_pci_sg_memory *mem=vb->priv;
457 BUG_ON(!mem);
458
459 MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
460
461 switch (vb->memory) {
462 case V4L2_MEMORY_MMAP:
463 case V4L2_MEMORY_USERPTR:
464 if (0 == vb->baddr) {
465 /* no userspace addr -- kernel bounce buffer */
466 pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
467 err = videobuf_dma_init_kernel( &mem->dma,
468 PCI_DMA_FROMDEVICE,
469 pages );
470 if (0 != err)
471 return err;
472 } else {
473 /* dma directly to userspace */
474 err = videobuf_dma_init_user( &mem->dma,
475 PCI_DMA_FROMDEVICE,
476 vb->baddr,vb->bsize );
477 if (0 != err)
478 return err;
479 }
480 break;
481 case V4L2_MEMORY_OVERLAY:
482 if (NULL == fbuf)
483 return -EINVAL;
484 /* FIXME: need sanity checks for vb->boff */
485 /*
486 * Using a double cast to avoid compiler warnings when
487 * building for PAE. Compiler doesn't like direct casting
488 * of a 32 bit ptr to 64 bit integer.
489 */
490 bus = (dma_addr_t)(unsigned long)fbuf->base + vb->boff;
491 pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
492 err = videobuf_dma_init_overlay(&mem->dma,PCI_DMA_FROMDEVICE,
493 bus, pages);
494 if (0 != err)
495 return err;
496 break;
497 default:
498 BUG();
499 }
500 err = videobuf_dma_map(q,&mem->dma);
501 if (0 != err)
502 return err;
503
504 return 0;
505}
506
507static int __videobuf_sync(struct videobuf_queue *q,
508 struct videobuf_buffer *buf)
509{
510 struct videbuf_pci_sg_memory *mem=buf->priv;
511 BUG_ON (!mem);
512 MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
513
514 return videobuf_dma_sync(q,&mem->dma);
515}
516
517static int __videobuf_mmap_free(struct videobuf_queue *q)
518{
519 int i;
520
521 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
522 if (q->bufs[i]) {
523 struct videbuf_pci_sg_memory *mem=q->bufs[i]->priv;
524 if (mem && mem->map)
525 return -EBUSY;
526 }
527 }
528
529 return 0;
530}
531
532static int __videobuf_mmap_mapper(struct videobuf_queue *q,
533 struct vm_area_struct *vma)
534{
535 struct videbuf_pci_sg_memory *mem;
536 struct videobuf_mapping *map;
537 unsigned int first,last,size,i;
538 int retval;
539
540 retval = -EINVAL;
541 if (!(vma->vm_flags & VM_WRITE)) {
542 dprintk(1,"mmap app bug: PROT_WRITE please\n");
543 goto done;
544 }
545 if (!(vma->vm_flags & VM_SHARED)) {
546 dprintk(1,"mmap app bug: MAP_SHARED please\n");
547 goto done;
548 }
549
550 /* look for first buffer to map */
551 for (first = 0; first < VIDEO_MAX_FRAME; first++) {
552 if (NULL == q->bufs[first])
553 continue;
554 mem=q->bufs[first]->priv;
555 BUG_ON (!mem);
556 MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
557
558 if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
559 continue;
560 if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT))
561 break;
562 }
563 if (VIDEO_MAX_FRAME == first) {
564 dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n",
565 (vma->vm_pgoff << PAGE_SHIFT));
566 goto done;
567 }
568
569 /* look for last buffer to map */
570 for (size = 0, last = first; last < VIDEO_MAX_FRAME; last++) {
571 if (NULL == q->bufs[last])
572 continue;
573 if (V4L2_MEMORY_MMAP != q->bufs[last]->memory)
574 continue;
575 mem=q->bufs[last]->priv;
576 if (mem->map) {
577 retval = -EBUSY;
578 goto done;
579 }
580 size += q->bufs[last]->bsize;
581 if (size == (vma->vm_end - vma->vm_start))
582 break;
583 }
584 if (VIDEO_MAX_FRAME == last) {
585 dprintk(1,"mmap app bug: size invalid [size=0x%lx]\n",
586 (vma->vm_end - vma->vm_start));
587 goto done;
588 }
589
590 /* create mapping + update buffer list */
591 retval = -ENOMEM;
592 map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
593 if (NULL == map)
594 goto done;
595 for (size = 0, i = first; i <= last; size += q->bufs[i++]->bsize) {
596 mem=q->bufs[i]->priv;
597 mem->map = map;
598 q->bufs[i]->baddr = vma->vm_start + size;
599 }
600 map->count = 1;
601 map->start = vma->vm_start;
602 map->end = vma->vm_end;
603 map->q = q;
604 vma->vm_ops = &videobuf_vm_ops;
605 vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
606 vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
607 vma->vm_private_data = map;
608 dprintk(1,"mmap %p: q=%p %08lx-%08lx pgoff %08lx bufs %d-%d\n",
609 map,q,vma->vm_start,vma->vm_end,vma->vm_pgoff,first,last);
610 retval = 0;
611
612 done:
613 return retval;
614}
615
616static int __videobuf_is_mmapped (struct videobuf_buffer *buf)
617{
618 struct videbuf_pci_sg_memory *mem=buf->priv;
619
620 BUG_ON (!mem);
621 MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
622
623 return (mem->map)?1:0;
624}
625
626static int __videobuf_copy_to_user ( struct videobuf_queue *q,
627 char __user *data, size_t count,
628 int nonblocking )
629{
630 struct videbuf_pci_sg_memory *mem=q->read_buf->priv;
631 BUG_ON (!mem);
632 MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
633
634 /* copy to userspace */
635 if (count > q->read_buf->size - q->read_off)
636 count = q->read_buf->size - q->read_off;
637
638 if (copy_to_user(data, mem->dma.vmalloc+q->read_off, count))
639 return -EFAULT;
640
641 return count;
642}
643
644static int __videobuf_copy_stream ( struct videobuf_queue *q,
645 char __user *data, size_t count, size_t pos,
646 int vbihack, int nonblocking )
647{
648 unsigned int *fc;
649 struct videbuf_pci_sg_memory *mem=q->read_buf->priv;
650 BUG_ON (!mem);
651 MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
652
653 if (vbihack) {
654 /* dirty, undocumented hack -- pass the frame counter
655 * within the last four bytes of each vbi data block.
656 * We need that one to maintain backward compatibility
657 * to all vbi decoding software out there ... */
658 fc = (unsigned int*)mem->dma.vmalloc;
659 fc += (q->read_buf->size>>2) -1;
660 *fc = q->read_buf->field_count >> 1;
661 dprintk(1,"vbihack: %d\n",*fc);
662 }
663
664 /* copy stuff using the common method */
665 count = __videobuf_copy_to_user (q,data,count,nonblocking);
666
667 if ( (count==-EFAULT) && (0 == pos) )
668 return -EFAULT;
669
670 return count;
671}
672
673static struct videobuf_qtype_ops pci_ops = {
674 .magic = MAGIC_QTYPE_OPS,
675
676 .alloc = __videobuf_alloc,
677 .iolock = __videobuf_iolock,
678 .sync = __videobuf_sync,
679 .mmap_free = __videobuf_mmap_free,
680 .mmap_mapper = __videobuf_mmap_mapper,
681 .is_mmapped = __videobuf_is_mmapped,
682 .copy_to_user = __videobuf_copy_to_user,
683 .copy_stream = __videobuf_copy_stream,
684};
685
686void *videobuf_pci_alloc (size_t size)
687{
688 struct videobuf_queue q;
689
690 /* Required to make generic handler to call __videobuf_alloc */
691 q.int_ops=&pci_ops;
692
693 q.msize=size;
694
695 return videobuf_alloc (&q);
696}
697
698void videobuf_queue_pci_init(struct videobuf_queue* q,
699 struct videobuf_queue_ops *ops,
700 void *dev,
701 spinlock_t *irqlock,
702 enum v4l2_buf_type type,
703 enum v4l2_field field,
704 unsigned int msize,
705 void *priv)
706{
707 struct videobuf_dma_sg_ops *priv_ops;
708
709 videobuf_queue_init(q, ops, dev, irqlock, type, field, msize, priv);
710 q->int_ops=&pci_ops;
711
712 /* FIXME: the code bellow should be removed after having a proper
713 * memory allocation method for vivi and tm6000
714 */
715 q->priv_ops= kzalloc(sizeof(struct videobuf_dma_sg_ops), GFP_KERNEL);
716 BUG_ON (!q->priv_ops);
717
718 priv_ops=q->priv_ops;
719
720 /* Sets default methods for handling Scatter Gather mapping */
721 priv_ops->vb_map_sg=(vb_map_sg_t *)pci_map_sg;
722 priv_ops->vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
723 priv_ops->vb_dma_sync_sg=(vb_map_sg_t *)pci_dma_sync_sg_for_cpu;
724}
725
726void videobuf_set_pci_ops (struct videobuf_queue* q,
727 struct videobuf_dma_sg_ops *ops)
728{
729 kfree (q->priv_ops);
730
731 q->priv_ops=ops;
732
733 if (!ops)
734 return;
735
736 /* If not specified, defaults to PCI map sg */
737 if (!ops->vb_map_sg)
738 ops->vb_map_sg=(vb_map_sg_t *)pci_map_sg;
739
740 if (!ops->vb_dma_sync_sg)
741 ops->vb_dma_sync_sg=(vb_map_sg_t *)pci_dma_sync_sg_for_cpu;
742 if (!ops->vb_unmap_sg)
743 ops->vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
744}
745
746
747/* --------------------------------------------------------------------- */
748
749EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg);
750
751EXPORT_SYMBOL_GPL(videobuf_to_dma);
752EXPORT_SYMBOL_GPL(videobuf_dma_init);
753EXPORT_SYMBOL_GPL(videobuf_dma_init_user);
754EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel);
755EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay);
756EXPORT_SYMBOL_GPL(videobuf_dma_map);
757EXPORT_SYMBOL_GPL(videobuf_dma_sync);
758EXPORT_SYMBOL_GPL(videobuf_dma_unmap);
759EXPORT_SYMBOL_GPL(videobuf_dma_free);
760
761EXPORT_SYMBOL_GPL(videobuf_pci_dma_map);
762EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap);
763EXPORT_SYMBOL_GPL(videobuf_pci_alloc);
764
765EXPORT_SYMBOL_GPL(videobuf_queue_pci_init);
766EXPORT_SYMBOL_GPL(videobuf_set_pci_ops);
767
768/*
769 * Local variables:
770 * c-basic-offset: 8
771 * End:
772 */
diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h
new file mode 100644
index 000000000000..0ac21ae44f69
--- /dev/null
+++ b/include/media/videobuf-core.h
@@ -0,0 +1,236 @@
1/*
2 * generic helper functions for handling video4linux capture buffers
3 *
4 * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org>
5 *
6 * Highly based on video-buf written originally by:
7 * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
8 * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org>
9 * (c) 2006 Ted Walther and John Sokol
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2
14 */
15
16#include <linux/poll.h>
17#ifdef CONFIG_VIDEO_V4L1_COMPAT
18#include <linux/videodev.h>
19#endif
20#include <linux/videodev2.h>
21
22#define UNSET (-1U)
23
24
25struct videobuf_buffer;
26struct videobuf_queue;
27
28/* --------------------------------------------------------------------- */
29
30/*
31 * A small set of helper functions to manage video4linux buffers.
32 *
33 * struct videobuf_buffer holds the data structures used by the helper
34 * functions, additionally some commonly used fields for v4l buffers
35 * (width, height, lists, waitqueue) are in there. That struct should
36 * be used as first element in the drivers buffer struct.
37 *
38 * about the mmap helpers (videobuf_mmap_*):
39 *
40 * The mmaper function allows to map any subset of contingous buffers.
41 * This includes one mmap() call for all buffers (which the original
42 * video4linux API uses) as well as one mmap() for every single buffer
43 * (which v4l2 uses).
44 *
45 * If there is a valid mapping for a buffer, buffer->baddr/bsize holds
46 * userspace address + size which can be feeded into the
47 * videobuf_dma_init_user function listed above.
48 *
49 */
50
51struct videobuf_mapping {
52 unsigned int count;
53 unsigned long start;
54 unsigned long end;
55 struct videobuf_queue *q;
56};
57
58enum videobuf_state {
59 STATE_NEEDS_INIT = 0,
60 STATE_PREPARED = 1,
61 STATE_QUEUED = 2,
62 STATE_ACTIVE = 3,
63 STATE_DONE = 4,
64 STATE_ERROR = 5,
65 STATE_IDLE = 6,
66};
67
68struct videobuf_buffer {
69 unsigned int i;
70 u32 magic;
71
72 /* info about the buffer */
73 unsigned int width;
74 unsigned int height;
75 unsigned int bytesperline; /* use only if != 0 */
76 unsigned long size;
77 unsigned int input;
78 enum v4l2_field field;
79 enum videobuf_state state;
80 struct list_head stream; /* QBUF/DQBUF list */
81
82 /* touched by irq handler */
83 struct list_head queue;
84 wait_queue_head_t done;
85 unsigned int field_count;
86 struct timeval ts;
87
88 /* Memory type */
89 enum v4l2_memory memory;
90
91 /* buffer size */
92 size_t bsize;
93
94 /* buffer offset (mmap + overlay) */
95 size_t boff;
96
97 /* buffer addr (userland ptr!) */
98 unsigned long baddr;
99
100 /* Private pointer to allow specific methods to store their data */
101 int privsize;
102 void *priv;
103};
104
105struct videobuf_queue_ops {
106 int (*buf_setup)(struct videobuf_queue *q,
107 unsigned int *count, unsigned int *size);
108 int (*buf_prepare)(struct videobuf_queue *q,
109 struct videobuf_buffer *vb,
110 enum v4l2_field field);
111 void (*buf_queue)(struct videobuf_queue *q,
112 struct videobuf_buffer *vb);
113 void (*buf_release)(struct videobuf_queue *q,
114 struct videobuf_buffer *vb);
115};
116
117#define MAGIC_QTYPE_OPS 0x12261003
118
119/* Helper operations - device type dependent */
120struct videobuf_qtype_ops {
121 u32 magic;
122
123 void* (*alloc) (size_t size);
124 int (*iolock) (struct videobuf_queue* q,
125 struct videobuf_buffer *vb,
126 struct v4l2_framebuffer *fbuf);
127 int (*mmap) (struct videobuf_queue *q,
128 unsigned int *count,
129 unsigned int *size,
130 enum v4l2_memory memory);
131 int (*sync) (struct videobuf_queue* q,
132 struct videobuf_buffer *buf);
133 int (*copy_to_user) (struct videobuf_queue *q,
134 char __user *data,
135 size_t count,
136 int nonblocking);
137 int (*copy_stream) (struct videobuf_queue *q,
138 char __user *data,
139 size_t count,
140 size_t pos,
141 int vbihack,
142 int nonblocking);
143 int (*mmap_free) (struct videobuf_queue *q);
144 int (*mmap_mapper) (struct videobuf_queue *q,
145 struct vm_area_struct *vma);
146 int (*is_mmapped) (struct videobuf_buffer *buf);
147};
148
149struct videobuf_queue {
150 struct mutex lock;
151 spinlock_t *irqlock;
152 void *dev; /* on pci, points to struct pci_dev */
153
154 enum v4l2_buf_type type;
155 unsigned int inputs; /* for V4L2_BUF_FLAG_INPUT */
156 unsigned int msize;
157 enum v4l2_field field;
158 enum v4l2_field last; /* for field=V4L2_FIELD_ALTERNATE */
159 struct videobuf_buffer *bufs[VIDEO_MAX_FRAME];
160 struct videobuf_queue_ops *ops;
161 struct videobuf_qtype_ops *int_ops;
162
163 /* capture via mmap() + ioctl(QBUF/DQBUF) */
164 unsigned int streaming;
165 struct list_head stream;
166
167 /* capture via read() */
168 unsigned int reading;
169 unsigned int read_off;
170 struct videobuf_buffer *read_buf;
171
172 /* driver private data */
173 void *priv_data;
174
175 /*FIXME: should be removed after completing the vb conversion */
176 void *priv_ops;
177};
178
179int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr);
180int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
181 struct v4l2_framebuffer *fbuf);
182
183void *videobuf_alloc(struct videobuf_queue* q);
184
185void videobuf_queue_init(struct videobuf_queue *q,
186 struct videobuf_queue_ops *ops,
187 void *dev,
188 spinlock_t *irqlock,
189 enum v4l2_buf_type type,
190 enum v4l2_field field,
191 unsigned int msize,
192 void *priv);
193int videobuf_queue_is_busy(struct videobuf_queue *q);
194void videobuf_queue_cancel(struct videobuf_queue *q);
195
196enum v4l2_field videobuf_next_field(struct videobuf_queue *q);
197int videobuf_reqbufs(struct videobuf_queue *q,
198 struct v4l2_requestbuffers *req);
199int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b);
200int videobuf_qbuf(struct videobuf_queue *q,
201 struct v4l2_buffer *b);
202int videobuf_dqbuf(struct videobuf_queue *q,
203 struct v4l2_buffer *b, int nonblocking);
204#ifdef CONFIG_VIDEO_V4L1_COMPAT
205int videobuf_cgmbuf(struct videobuf_queue *q,
206 struct video_mbuf *mbuf, int count);
207#endif
208int videobuf_streamon(struct videobuf_queue *q);
209int videobuf_streamoff(struct videobuf_queue *q);
210
211int videobuf_read_start(struct videobuf_queue *q);
212void videobuf_read_stop(struct videobuf_queue *q);
213ssize_t videobuf_read_stream(struct videobuf_queue *q,
214 char __user *data, size_t count, loff_t *ppos,
215 int vbihack, int nonblocking);
216ssize_t videobuf_read_one(struct videobuf_queue *q,
217 char __user *data, size_t count, loff_t *ppos,
218 int nonblocking);
219unsigned int videobuf_poll_stream(struct file *file,
220 struct videobuf_queue *q,
221 poll_table *wait);
222
223int videobuf_mmap_setup(struct videobuf_queue *q,
224 unsigned int bcount, unsigned int bsize,
225 enum v4l2_memory memory);
226int videobuf_mmap_free(struct videobuf_queue *q);
227int videobuf_mmap_mapper(struct videobuf_queue *q,
228 struct vm_area_struct *vma);
229
230/* --------------------------------------------------------------------- */
231
232/*
233 * Local variables:
234 * c-basic-offset: 8
235 * End:
236 */
diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h
new file mode 100644
index 000000000000..62a3709905f3
--- /dev/null
+++ b/include/media/videobuf-dma-sg.h
@@ -0,0 +1,142 @@
1/*
2 * helper functions for PCI DMA video4linux capture buffers
3 *
4 * The functions expect the hardware being able to scatter gatter
5 * (i.e. the buffers are not linear in physical memory, but fragmented
6 * into PAGE_SIZE chunks). They also assume the driver does not need
7 * to touch the video data.
8 *
9 * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org>
10 *
11 * Highly based on video-buf written originally by:
12 * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
13 * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org>
14 * (c) 2006 Ted Walther and John Sokol
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2
19 */
20
21#include <media/videobuf-core.h>
22
23/* --------------------------------------------------------------------- */
24
25/*
26 * Return a scatterlist for some page-aligned vmalloc()'ed memory
27 * block (NULL on errors). Memory for the scatterlist is allocated
28 * using kmalloc. The caller must free the memory.
29 */
30struct scatterlist* videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages);
31
32/*
33 * Return a scatterlist for a an array of userpages (NULL on errors).
34 * Memory for the scatterlist is allocated using kmalloc. The caller
35 * must free the memory.
36 */
37struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages,
38 int offset);
39
40/* --------------------------------------------------------------------- */
41
42/*
43 * A small set of helper functions to manage buffers (both userland
44 * and kernel) for DMA.
45 *
46 * videobuf_dma_init_*()
47 * creates a buffer. The userland version takes a userspace
48 * pointer + length. The kernel version just wants the size and
49 * does memory allocation too using vmalloc_32().
50 *
51 * videobuf_dma_*()
52 * see Documentation/DMA-mapping.txt, these functions to
53 * basically the same. The map function does also build a
54 * scatterlist for the buffer (and unmap frees it ...)
55 *
56 * videobuf_dma_free()
57 * no comment ...
58 *
59 */
60
61struct videobuf_dmabuf {
62 u32 magic;
63
64 /* for userland buffer */
65 int offset;
66 struct page **pages;
67
68 /* for kernel buffers */
69 void *vmalloc;
70
71 /* Stores the userspace pointer to vmalloc area */
72 void *varea;
73
74 /* for overlay buffers (pci-pci dma) */
75 dma_addr_t bus_addr;
76
77 /* common */
78 struct scatterlist *sglist;
79 int sglen;
80 int nr_pages;
81 int direction;
82};
83
84struct videbuf_pci_sg_memory
85{
86 u32 magic;
87
88 /* for mmap'ed buffers */
89 struct videobuf_mapping *map;
90 struct videobuf_dmabuf dma;
91};
92
93/* FIXME: To be removed soon */
94typedef int (vb_map_sg_t)(void *dev, struct scatterlist *sglist, int nr_pages,
95 int direction);
96
97/* FIXME: To be removed soon */
98struct videobuf_dma_sg_ops
99{
100 vb_map_sg_t *vb_map_sg;
101 vb_map_sg_t *vb_dma_sync_sg;
102 vb_map_sg_t *vb_unmap_sg;
103
104};
105
106void videobuf_dma_init(struct videobuf_dmabuf *dma);
107int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
108 unsigned long data, unsigned long size);
109int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
110 int nr_pages);
111int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
112 dma_addr_t addr, int nr_pages);
113int videobuf_dma_free(struct videobuf_dmabuf *dma);
114
115int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
116int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
117int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
118struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf);
119
120void *videobuf_pci_alloc (size_t size);
121
122void videobuf_queue_pci_init(struct videobuf_queue* q,
123 struct videobuf_queue_ops *ops,
124 void *dev,
125 spinlock_t *irqlock,
126 enum v4l2_buf_type type,
127 enum v4l2_field field,
128 unsigned int msize,
129 void *priv);
130
131 /*FIXME: these variants are used only on *-alsa code, where videobuf is
132 * used without queue
133 */
134int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma);
135int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma);
136
137/* FIXME: temporary routine for vivi and tm6000, while lacking implementation
138 * of videobuf-vmalloc
139 */
140void videobuf_set_pci_ops (struct videobuf_queue* q,
141 struct videobuf_dma_sg_ops *ops);
142