V4L/DVB: videobuf: add ext_lock argument to the queue init functions
[linux-2.6-block.git] / drivers / media / video / videobuf-core.c
CommitLineData
7a7d9a89
MCC
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>
27ac792c 19#include <linux/mm.h>
d43c36dc 20#include <linux/sched.h>
7a7d9a89
MCC
21#include <linux/slab.h>
22#include <linux/interrupt.h>
23
24#include <media/videobuf-core.h>
25
26#define MAGIC_BUFFER 0x20070728
7a02264c
PO
27#define MAGIC_CHECK(is, should) \
28 do { \
29 if (unlikely((is) != (should))) { \
30 printk(KERN_ERR \
31 "magic mismatch: %x (expected %x)\n", \
32 is, should); \
33 BUG(); \
34 } \
35 } while (0)
7a7d9a89 36
e2c77314 37static int debug;
7a7d9a89
MCC
38module_param(debug, int, 0644);
39
40MODULE_DESCRIPTION("helper module to manage video4linux buffers");
41MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
42MODULE_LICENSE("GPL");
43
7a02264c
PO
44#define dprintk(level, fmt, arg...) \
45 do { \
46 if (debug >= level) \
47 printk(KERN_DEBUG "vbuf: " fmt, ## arg); \
48 } while (0)
7a7d9a89
MCC
49
50/* --------------------------------------------------------------------- */
51
52#define CALL(q, f, arg...) \
e2c77314 53 ((q->int_ops->f) ? q->int_ops->f(arg) : 0)
7a7d9a89 54
33c38283 55struct videobuf_buffer *videobuf_alloc_vb(struct videobuf_queue *q)
7a7d9a89
MCC
56{
57 struct videobuf_buffer *vb;
58
e2c77314 59 BUG_ON(q->msize < sizeof(*vb));
7a7d9a89 60
33c38283 61 if (!q->int_ops || !q->int_ops->alloc_vb) {
7a7d9a89
MCC
62 printk(KERN_ERR "No specific ops defined!\n");
63 BUG();
64 }
65
33c38283 66 vb = q->int_ops->alloc_vb(q->msize);
7a7d9a89
MCC
67 if (NULL != vb) {
68 init_waitqueue_head(&vb->done);
7a02264c 69 vb->magic = MAGIC_BUFFER;
7a7d9a89
MCC
70 }
71
72 return vb;
73}
33c38283 74EXPORT_SYMBOL_GPL(videobuf_alloc_vb);
7a7d9a89 75
009a9059
BP
76#define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\
77 vb->state != VIDEOBUF_QUEUED)
7a7d9a89
MCC
78int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr)
79{
e2c77314 80 MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
009a9059
BP
81
82 if (non_blocking) {
83 if (WAITON_CONDITION)
84 return 0;
85 else
86 return -EAGAIN;
7a7d9a89 87 }
009a9059
BP
88
89 if (intr)
90 return wait_event_interruptible(vb->done, WAITON_CONDITION);
91 else
92 wait_event(vb->done, WAITON_CONDITION);
93
94 return 0;
7a7d9a89 95}
7a02264c 96EXPORT_SYMBOL_GPL(videobuf_waiton);
7a7d9a89 97
e2c77314 98int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb,
7a7d9a89
MCC
99 struct v4l2_framebuffer *fbuf)
100{
e2c77314
MCC
101 MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
102 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
7a7d9a89 103
e2c77314 104 return CALL(q, iolock, q, vb, fbuf);
7a7d9a89 105}
7a02264c 106EXPORT_SYMBOL_GPL(videobuf_iolock);
7a7d9a89 107
f4fce60e
HV
108void *videobuf_queue_to_vaddr(struct videobuf_queue *q,
109 struct videobuf_buffer *buf)
59d34489 110{
037c75eb
HV
111 if (q->int_ops->vaddr)
112 return q->int_ops->vaddr(buf);
f4fce60e 113 return NULL;
59d34489 114}
f4fce60e 115EXPORT_SYMBOL_GPL(videobuf_queue_to_vaddr);
59d34489 116
7a7d9a89
MCC
117/* --------------------------------------------------------------------- */
118
119
e2c77314 120void videobuf_queue_core_init(struct videobuf_queue *q,
38a54f35 121 const struct videobuf_queue_ops *ops,
e9bcf667 122 struct device *dev,
7a7d9a89
MCC
123 spinlock_t *irqlock,
124 enum v4l2_buf_type type,
125 enum v4l2_field field,
126 unsigned int msize,
d4cae5a5 127 void *priv,
08bff03e
HV
128 struct videobuf_qtype_ops *int_ops,
129 struct mutex *ext_lock)
7a7d9a89 130{
96ceea27 131 BUG_ON(!q);
e2c77314 132 memset(q, 0, sizeof(*q));
d4cae5a5 133 q->irqlock = irqlock;
08bff03e 134 q->ext_lock = ext_lock;
d4cae5a5
MCC
135 q->dev = dev;
136 q->type = type;
137 q->field = field;
138 q->msize = msize;
139 q->ops = ops;
7a7d9a89 140 q->priv_data = priv;
d4cae5a5 141 q->int_ops = int_ops;
7a7d9a89
MCC
142
143 /* All buffer operations are mandatory */
e2c77314
MCC
144 BUG_ON(!q->ops->buf_setup);
145 BUG_ON(!q->ops->buf_prepare);
146 BUG_ON(!q->ops->buf_queue);
147 BUG_ON(!q->ops->buf_release);
7a7d9a89 148
0cf4daee
BP
149 /* Lock is mandatory for queue_cancel to work */
150 BUG_ON(!irqlock);
151
d4cae5a5 152 /* Having implementations for abstract methods are mandatory */
e2c77314 153 BUG_ON(!q->int_ops);
d4cae5a5 154
64f9477f 155 mutex_init(&q->vb_lock);
137d1cb1 156 init_waitqueue_head(&q->wait);
7a7d9a89
MCC
157 INIT_LIST_HEAD(&q->stream);
158}
7a02264c 159EXPORT_SYMBOL_GPL(videobuf_queue_core_init);
7a7d9a89 160
19bc5133 161/* Locking: Only usage in bttv unsafe find way to remove */
7a7d9a89
MCC
162int videobuf_queue_is_busy(struct videobuf_queue *q)
163{
164 int i;
165
e2c77314 166 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
7a7d9a89
MCC
167
168 if (q->streaming) {
e2c77314 169 dprintk(1, "busy: streaming active\n");
7a7d9a89
MCC
170 return 1;
171 }
172 if (q->reading) {
e2c77314 173 dprintk(1, "busy: pending read #1\n");
7a7d9a89
MCC
174 return 1;
175 }
176 if (q->read_buf) {
e2c77314 177 dprintk(1, "busy: pending read #2\n");
7a7d9a89
MCC
178 return 1;
179 }
180 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
181 if (NULL == q->bufs[i])
182 continue;
851c0c96 183 if (q->bufs[i]->map) {
e2c77314 184 dprintk(1, "busy: buffer #%d mapped\n", i);
7a7d9a89
MCC
185 return 1;
186 }
0fc0686e 187 if (q->bufs[i]->state == VIDEOBUF_QUEUED) {
e2c77314 188 dprintk(1, "busy: buffer #%d queued\n", i);
7a7d9a89
MCC
189 return 1;
190 }
0fc0686e 191 if (q->bufs[i]->state == VIDEOBUF_ACTIVE) {
e2c77314 192 dprintk(1, "busy: buffer #%d avtive\n", i);
7a7d9a89
MCC
193 return 1;
194 }
195 }
196 return 0;
197}
7a02264c 198EXPORT_SYMBOL_GPL(videobuf_queue_is_busy);
7a7d9a89 199
a438d6da
PO
200/**
201 * __videobuf_free() - free all the buffers and their control structures
202 *
203 * This function can only be called if streaming/reading is off, i.e. no buffers
204 * are under control of the driver.
205 */
206/* Locking: Caller holds q->vb_lock */
207static int __videobuf_free(struct videobuf_queue *q)
208{
209 int i;
210
211 dprintk(1, "%s\n", __func__);
212 if (!q)
213 return 0;
214
215 if (q->streaming || q->reading) {
216 dprintk(1, "Cannot free buffers when streaming or reading\n");
217 return -EBUSY;
218 }
219
220 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
221
222 for (i = 0; i < VIDEO_MAX_FRAME; i++)
223 if (q->bufs[i] && q->bufs[i]->map) {
224 dprintk(1, "Cannot free mmapped buffers\n");
225 return -EBUSY;
226 }
227
228 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
229 if (NULL == q->bufs[i])
230 continue;
231 q->ops->buf_release(q, q->bufs[i]);
232 kfree(q->bufs[i]);
233 q->bufs[i] = NULL;
234 }
235
236 return 0;
237}
238
64f9477f 239/* Locking: Caller holds q->vb_lock */
7a7d9a89
MCC
240void videobuf_queue_cancel(struct videobuf_queue *q)
241{
e2c77314 242 unsigned long flags = 0;
7a7d9a89
MCC
243 int i;
244
137d1cb1
BP
245 q->streaming = 0;
246 q->reading = 0;
247 wake_up_interruptible_sync(&q->wait);
248
7a7d9a89 249 /* remove queued buffers from list */
0cf4daee 250 spin_lock_irqsave(q->irqlock, flags);
7a7d9a89
MCC
251 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
252 if (NULL == q->bufs[i])
253 continue;
0fc0686e 254 if (q->bufs[i]->state == VIDEOBUF_QUEUED) {
7a7d9a89 255 list_del(&q->bufs[i]->queue);
0fc0686e 256 q->bufs[i]->state = VIDEOBUF_ERROR;
b608f432 257 wake_up_all(&q->bufs[i]->done);
7a7d9a89
MCC
258 }
259 }
0cf4daee 260 spin_unlock_irqrestore(q->irqlock, flags);
7a7d9a89
MCC
261
262 /* free all buffers + clear queue */
263 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
264 if (NULL == q->bufs[i])
265 continue;
e2c77314 266 q->ops->buf_release(q, q->bufs[i]);
7a7d9a89
MCC
267 }
268 INIT_LIST_HEAD(&q->stream);
269}
7a02264c 270EXPORT_SYMBOL_GPL(videobuf_queue_cancel);
7a7d9a89
MCC
271
272/* --------------------------------------------------------------------- */
273
64f9477f 274/* Locking: Caller holds q->vb_lock */
7a7d9a89
MCC
275enum v4l2_field videobuf_next_field(struct videobuf_queue *q)
276{
277 enum v4l2_field field = q->field;
278
279 BUG_ON(V4L2_FIELD_ANY == field);
280
281 if (V4L2_FIELD_ALTERNATE == field) {
282 if (V4L2_FIELD_TOP == q->last) {
283 field = V4L2_FIELD_BOTTOM;
284 q->last = V4L2_FIELD_BOTTOM;
285 } else {
286 field = V4L2_FIELD_TOP;
287 q->last = V4L2_FIELD_TOP;
288 }
289 }
290 return field;
291}
7a02264c 292EXPORT_SYMBOL_GPL(videobuf_next_field);
7a7d9a89 293
64f9477f 294/* Locking: Caller holds q->vb_lock */
7a7d9a89
MCC
295static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b,
296 struct videobuf_buffer *vb, enum v4l2_buf_type type)
297{
e2c77314
MCC
298 MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
299 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
7a7d9a89
MCC
300
301 b->index = vb->i;
302 b->type = type;
303
304 b->memory = vb->memory;
305 switch (b->memory) {
306 case V4L2_MEMORY_MMAP:
307 b->m.offset = vb->boff;
308 b->length = vb->bsize;
309 break;
310 case V4L2_MEMORY_USERPTR:
311 b->m.userptr = vb->baddr;
312 b->length = vb->bsize;
313 break;
314 case V4L2_MEMORY_OVERLAY:
315 b->m.offset = vb->boff;
316 break;
317 }
318
319 b->flags = 0;
851c0c96 320 if (vb->map)
7a7d9a89
MCC
321 b->flags |= V4L2_BUF_FLAG_MAPPED;
322
323 switch (vb->state) {
0fc0686e
BP
324 case VIDEOBUF_PREPARED:
325 case VIDEOBUF_QUEUED:
326 case VIDEOBUF_ACTIVE:
7a7d9a89
MCC
327 b->flags |= V4L2_BUF_FLAG_QUEUED;
328 break;
0fc0686e 329 case VIDEOBUF_ERROR:
b2dfd1a4
HV
330 b->flags |= V4L2_BUF_FLAG_ERROR;
331 /* fall through */
332 case VIDEOBUF_DONE:
7a7d9a89
MCC
333 b->flags |= V4L2_BUF_FLAG_DONE;
334 break;
0fc0686e
BP
335 case VIDEOBUF_NEEDS_INIT:
336 case VIDEOBUF_IDLE:
7a7d9a89
MCC
337 /* nothing */
338 break;
339 }
340
341 if (vb->input != UNSET) {
342 b->flags |= V4L2_BUF_FLAG_INPUT;
343 b->input = vb->input;
344 }
345
346 b->field = vb->field;
347 b->timestamp = vb->ts;
348 b->bytesused = vb->size;
349 b->sequence = vb->field_count >> 1;
350}
351
19bc5133
BP
352int videobuf_mmap_free(struct videobuf_queue *q)
353{
354 int ret;
97397687 355 videobuf_queue_lock(q);
a438d6da 356 ret = __videobuf_free(q);
97397687 357 videobuf_queue_unlock(q);
19bc5133
BP
358 return ret;
359}
7a02264c 360EXPORT_SYMBOL_GPL(videobuf_mmap_free);
19bc5133 361
64f9477f 362/* Locking: Caller holds q->vb_lock */
81b2dbca 363int __videobuf_mmap_setup(struct videobuf_queue *q,
19bc5133
BP
364 unsigned int bcount, unsigned int bsize,
365 enum v4l2_memory memory)
366{
367 unsigned int i;
368 int err;
369
e2c77314 370 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
19bc5133 371
a438d6da 372 err = __videobuf_free(q);
19bc5133
BP
373 if (0 != err)
374 return err;
375
376 /* Allocate and initialize buffers */
377 for (i = 0; i < bcount; i++) {
33c38283 378 q->bufs[i] = videobuf_alloc_vb(q);
19bc5133 379
7a02264c 380 if (NULL == q->bufs[i])
19bc5133
BP
381 break;
382
383 q->bufs[i]->i = i;
384 q->bufs[i]->input = UNSET;
385 q->bufs[i]->memory = memory;
386 q->bufs[i]->bsize = bsize;
387 switch (memory) {
388 case V4L2_MEMORY_MMAP:
7cbefad0 389 q->bufs[i]->boff = PAGE_ALIGN(bsize) * i;
19bc5133
BP
390 break;
391 case V4L2_MEMORY_USERPTR:
392 case V4L2_MEMORY_OVERLAY:
393 /* nothing */
394 break;
395 }
396 }
397
398 if (!i)
399 return -ENOMEM;
400
7a02264c 401 dprintk(1, "mmap setup: %d buffers, %d bytes each\n", i, bsize);
19bc5133
BP
402
403 return i;
404}
7a02264c 405EXPORT_SYMBOL_GPL(__videobuf_mmap_setup);
19bc5133
BP
406
407int videobuf_mmap_setup(struct videobuf_queue *q,
408 unsigned int bcount, unsigned int bsize,
409 enum v4l2_memory memory)
410{
411 int ret;
97397687 412 videobuf_queue_lock(q);
19bc5133 413 ret = __videobuf_mmap_setup(q, bcount, bsize, memory);
97397687 414 videobuf_queue_unlock(q);
19bc5133
BP
415 return ret;
416}
7a02264c 417EXPORT_SYMBOL_GPL(videobuf_mmap_setup);
19bc5133 418
7a7d9a89
MCC
419int videobuf_reqbufs(struct videobuf_queue *q,
420 struct v4l2_requestbuffers *req)
421{
e2c77314 422 unsigned int size, count;
7a7d9a89
MCC
423 int retval;
424
7a7d9a89 425 if (req->count < 1) {
e2c77314 426 dprintk(1, "reqbufs: count invalid (%d)\n", req->count);
7a7d9a89
MCC
427 return -EINVAL;
428 }
19bc5133 429
7a7d9a89
MCC
430 if (req->memory != V4L2_MEMORY_MMAP &&
431 req->memory != V4L2_MEMORY_USERPTR &&
432 req->memory != V4L2_MEMORY_OVERLAY) {
e2c77314 433 dprintk(1, "reqbufs: memory type invalid\n");
7a7d9a89
MCC
434 return -EINVAL;
435 }
436
97397687 437 videobuf_queue_lock(q);
19bc5133 438 if (req->type != q->type) {
e2c77314 439 dprintk(1, "reqbufs: queue type invalid\n");
19bc5133
BP
440 retval = -EINVAL;
441 goto done;
442 }
443
7a7d9a89 444 if (q->streaming) {
e2c77314 445 dprintk(1, "reqbufs: streaming already exists\n");
00f98d08
BP
446 retval = -EBUSY;
447 goto done;
7a7d9a89
MCC
448 }
449 if (!list_empty(&q->stream)) {
e2c77314 450 dprintk(1, "reqbufs: stream running\n");
00f98d08
BP
451 retval = -EBUSY;
452 goto done;
7a7d9a89
MCC
453 }
454
7a7d9a89
MCC
455 count = req->count;
456 if (count > VIDEO_MAX_FRAME)
457 count = VIDEO_MAX_FRAME;
458 size = 0;
e2c77314 459 q->ops->buf_setup(q, &count, &size);
296372e3
MN
460 dprintk(1, "reqbufs: bufs=%d, size=0x%x [%u pages total]\n",
461 count, size,
7a02264c 462 (unsigned int)((count * PAGE_ALIGN(size)) >> PAGE_SHIFT));
7a7d9a89 463
e2c77314 464 retval = __videobuf_mmap_setup(q, count, size, req->memory);
7a7d9a89 465 if (retval < 0) {
e2c77314 466 dprintk(1, "reqbufs: mmap setup returned %d\n", retval);
7a7d9a89
MCC
467 goto done;
468 }
469
49ee718e 470 req->count = retval;
925d74ae 471 retval = 0;
7a7d9a89
MCC
472
473 done:
97397687 474 videobuf_queue_unlock(q);
7a7d9a89
MCC
475 return retval;
476}
7a02264c 477EXPORT_SYMBOL_GPL(videobuf_reqbufs);
7a7d9a89
MCC
478
479int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b)
480{
19bc5133
BP
481 int ret = -EINVAL;
482
97397687 483 videobuf_queue_lock(q);
7a7d9a89 484 if (unlikely(b->type != q->type)) {
e2c77314 485 dprintk(1, "querybuf: Wrong type.\n");
19bc5133 486 goto done;
7a7d9a89 487 }
223ffe5f 488 if (unlikely(b->index >= VIDEO_MAX_FRAME)) {
e2c77314 489 dprintk(1, "querybuf: index out of range.\n");
19bc5133 490 goto done;
7a7d9a89
MCC
491 }
492 if (unlikely(NULL == q->bufs[b->index])) {
e2c77314 493 dprintk(1, "querybuf: buffer is null.\n");
19bc5133 494 goto done;
7a7d9a89 495 }
19bc5133 496
e2c77314 497 videobuf_status(q, b, q->bufs[b->index], q->type);
19bc5133
BP
498
499 ret = 0;
500done:
97397687 501 videobuf_queue_unlock(q);
19bc5133 502 return ret;
7a7d9a89 503}
7a02264c 504EXPORT_SYMBOL_GPL(videobuf_querybuf);
7a7d9a89 505
7a02264c 506int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b)
7a7d9a89
MCC
507{
508 struct videobuf_buffer *buf;
509 enum v4l2_field field;
e2c77314 510 unsigned long flags = 0;
7a7d9a89
MCC
511 int retval;
512
e2c77314 513 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
7a7d9a89 514
9900132f
ML
515 if (b->memory == V4L2_MEMORY_MMAP)
516 down_read(&current->mm->mmap_sem);
517
97397687 518 videobuf_queue_lock(q);
7a7d9a89
MCC
519 retval = -EBUSY;
520 if (q->reading) {
e2c77314 521 dprintk(1, "qbuf: Reading running...\n");
7a7d9a89
MCC
522 goto done;
523 }
524 retval = -EINVAL;
525 if (b->type != q->type) {
e2c77314 526 dprintk(1, "qbuf: Wrong type.\n");
7a7d9a89
MCC
527 goto done;
528 }
223ffe5f 529 if (b->index >= VIDEO_MAX_FRAME) {
e2c77314 530 dprintk(1, "qbuf: index out of range.\n");
7a7d9a89
MCC
531 goto done;
532 }
533 buf = q->bufs[b->index];
534 if (NULL == buf) {
e2c77314 535 dprintk(1, "qbuf: buffer is null.\n");
7a7d9a89
MCC
536 goto done;
537 }
e2c77314 538 MAGIC_CHECK(buf->magic, MAGIC_BUFFER);
7a7d9a89 539 if (buf->memory != b->memory) {
e2c77314 540 dprintk(1, "qbuf: memory type is wrong.\n");
7a7d9a89
MCC
541 goto done;
542 }
0fc0686e 543 if (buf->state != VIDEOBUF_NEEDS_INIT && buf->state != VIDEOBUF_IDLE) {
e2c77314 544 dprintk(1, "qbuf: buffer is already queued or active.\n");
7a7d9a89
MCC
545 goto done;
546 }
547
548 if (b->flags & V4L2_BUF_FLAG_INPUT) {
549 if (b->input >= q->inputs) {
e2c77314 550 dprintk(1, "qbuf: wrong input.\n");
7a7d9a89
MCC
551 goto done;
552 }
553 buf->input = b->input;
554 } else {
555 buf->input = UNSET;
556 }
557
558 switch (b->memory) {
559 case V4L2_MEMORY_MMAP:
560 if (0 == buf->baddr) {
e2c77314
MCC
561 dprintk(1, "qbuf: mmap requested "
562 "but buffer addr is zero!\n");
7a7d9a89
MCC
563 goto done;
564 }
96f2ec67
PO
565 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT
566 || q->type == V4L2_BUF_TYPE_VBI_OUTPUT
567 || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
568 buf->size = b->bytesused;
569 buf->field = b->field;
570 buf->ts = b->timestamp;
571 }
7a7d9a89
MCC
572 break;
573 case V4L2_MEMORY_USERPTR:
574 if (b->length < buf->bsize) {
e2c77314 575 dprintk(1, "qbuf: buffer length is not enough\n");
7a7d9a89
MCC
576 goto done;
577 }
e2c77314
MCC
578 if (VIDEOBUF_NEEDS_INIT != buf->state &&
579 buf->baddr != b->m.userptr)
580 q->ops->buf_release(q, buf);
7a7d9a89
MCC
581 buf->baddr = b->m.userptr;
582 break;
583 case V4L2_MEMORY_OVERLAY:
584 buf->boff = b->m.offset;
585 break;
586 default:
e2c77314 587 dprintk(1, "qbuf: wrong memory type\n");
7a7d9a89
MCC
588 goto done;
589 }
590
e2c77314 591 dprintk(1, "qbuf: requesting next field\n");
7a7d9a89 592 field = videobuf_next_field(q);
e2c77314 593 retval = q->ops->buf_prepare(q, buf, field);
7a7d9a89 594 if (0 != retval) {
e2c77314 595 dprintk(1, "qbuf: buffer_prepare returned %d\n", retval);
7a7d9a89
MCC
596 goto done;
597 }
598
e2c77314 599 list_add_tail(&buf->stream, &q->stream);
7a7d9a89 600 if (q->streaming) {
0cf4daee 601 spin_lock_irqsave(q->irqlock, flags);
e2c77314 602 q->ops->buf_queue(q, buf);
0cf4daee 603 spin_unlock_irqrestore(q->irqlock, flags);
7a7d9a89 604 }
771075bb 605 dprintk(1, "qbuf: succeeded\n");
7a7d9a89 606 retval = 0;
137d1cb1 607 wake_up_interruptible_sync(&q->wait);
7a7d9a89 608
7a02264c 609done:
97397687 610 videobuf_queue_unlock(q);
9900132f
ML
611
612 if (b->memory == V4L2_MEMORY_MMAP)
613 up_read(&current->mm->mmap_sem);
614
7a7d9a89
MCC
615 return retval;
616}
7a02264c 617EXPORT_SYMBOL_GPL(videobuf_qbuf);
137d1cb1
BP
618
619/* Locking: Caller holds q->vb_lock */
620static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock)
7a7d9a89 621{
7a7d9a89
MCC
622 int retval;
623
137d1cb1
BP
624checks:
625 if (!q->streaming) {
626 dprintk(1, "next_buffer: Not streaming\n");
627 retval = -EINVAL;
7a7d9a89
MCC
628 goto done;
629 }
137d1cb1 630
7a7d9a89 631 if (list_empty(&q->stream)) {
137d1cb1
BP
632 if (noblock) {
633 retval = -EAGAIN;
634 dprintk(2, "next_buffer: no buffers to dequeue\n");
635 goto done;
636 } else {
637 dprintk(2, "next_buffer: waiting on buffer\n");
638
639 /* Drop lock to avoid deadlock with qbuf */
97397687 640 videobuf_queue_unlock(q);
137d1cb1
BP
641
642 /* Checking list_empty and streaming is safe without
643 * locks because we goto checks to validate while
644 * holding locks before proceeding */
645 retval = wait_event_interruptible(q->wait,
646 !list_empty(&q->stream) || !q->streaming);
97397687 647 videobuf_queue_lock(q);
137d1cb1
BP
648
649 if (retval)
650 goto done;
651
652 goto checks;
653 }
7a7d9a89 654 }
137d1cb1
BP
655
656 retval = 0;
657
658done:
659 return retval;
660}
661
137d1cb1
BP
662/* Locking: Caller holds q->vb_lock */
663static int stream_next_buffer(struct videobuf_queue *q,
664 struct videobuf_buffer **vb, int nonblocking)
665{
666 int retval;
667 struct videobuf_buffer *buf = NULL;
668
669 retval = stream_next_buffer_check_queue(q, nonblocking);
670 if (retval)
671 goto done;
672
7a7d9a89
MCC
673 buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
674 retval = videobuf_waiton(buf, nonblocking, 1);
137d1cb1
BP
675 if (retval < 0)
676 goto done;
677
678 *vb = buf;
679done:
680 return retval;
681}
682
683int videobuf_dqbuf(struct videobuf_queue *q,
7a02264c 684 struct v4l2_buffer *b, int nonblocking)
137d1cb1
BP
685{
686 struct videobuf_buffer *buf = NULL;
687 int retval;
688
689 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
690
b2dfd1a4 691 memset(b, 0, sizeof(*b));
97397687 692 videobuf_queue_lock(q);
137d1cb1
BP
693
694 retval = stream_next_buffer(q, &buf, nonblocking);
7a7d9a89 695 if (retval < 0) {
137d1cb1 696 dprintk(1, "dqbuf: next_buffer error: %i\n", retval);
7a7d9a89
MCC
697 goto done;
698 }
137d1cb1 699
7a7d9a89 700 switch (buf->state) {
0fc0686e 701 case VIDEOBUF_ERROR:
e2c77314 702 dprintk(1, "dqbuf: state is error\n");
7a7d9a89 703 break;
0fc0686e 704 case VIDEOBUF_DONE:
e2c77314 705 dprintk(1, "dqbuf: state is done\n");
7a7d9a89
MCC
706 break;
707 default:
e2c77314 708 dprintk(1, "dqbuf: state invalid\n");
7a7d9a89
MCC
709 retval = -EINVAL;
710 goto done;
711 }
b2dfd1a4 712 CALL(q, sync, q, buf);
e2c77314 713 videobuf_status(q, b, buf, q->type);
b2dfd1a4
HV
714 list_del(&buf->stream);
715 buf->state = VIDEOBUF_IDLE;
716 b->flags &= ~V4L2_BUF_FLAG_DONE;
7a02264c 717done:
97397687 718 videobuf_queue_unlock(q);
7a7d9a89
MCC
719 return retval;
720}
7a02264c 721EXPORT_SYMBOL_GPL(videobuf_dqbuf);
7a7d9a89
MCC
722
723int videobuf_streamon(struct videobuf_queue *q)
724{
725 struct videobuf_buffer *buf;
e2c77314 726 unsigned long flags = 0;
7a7d9a89
MCC
727 int retval;
728
97397687 729 videobuf_queue_lock(q);
7a7d9a89
MCC
730 retval = -EBUSY;
731 if (q->reading)
732 goto done;
733 retval = 0;
734 if (q->streaming)
735 goto done;
736 q->streaming = 1;
0cf4daee 737 spin_lock_irqsave(q->irqlock, flags);
a991f44b 738 list_for_each_entry(buf, &q->stream, stream)
0fc0686e 739 if (buf->state == VIDEOBUF_PREPARED)
e2c77314 740 q->ops->buf_queue(q, buf);
0cf4daee 741 spin_unlock_irqrestore(q->irqlock, flags);
7a7d9a89 742
137d1cb1 743 wake_up_interruptible_sync(&q->wait);
7a02264c 744done:
97397687 745 videobuf_queue_unlock(q);
7a7d9a89
MCC
746 return retval;
747}
7a02264c 748EXPORT_SYMBOL_GPL(videobuf_streamon);
7a7d9a89 749
64f9477f 750/* Locking: Caller holds q->vb_lock */
19bc5133 751static int __videobuf_streamoff(struct videobuf_queue *q)
7a7d9a89 752{
7a7d9a89 753 if (!q->streaming)
19bc5133
BP
754 return -EINVAL;
755
7a7d9a89 756 videobuf_queue_cancel(q);
7a7d9a89 757
19bc5133
BP
758 return 0;
759}
760
761int videobuf_streamoff(struct videobuf_queue *q)
762{
763 int retval;
764
97397687 765 videobuf_queue_lock(q);
19bc5133 766 retval = __videobuf_streamoff(q);
97397687 767 videobuf_queue_unlock(q);
19bc5133 768
7a7d9a89
MCC
769 return retval;
770}
7a02264c 771EXPORT_SYMBOL_GPL(videobuf_streamoff);
7a7d9a89 772
64f9477f 773/* Locking: Caller holds q->vb_lock */
7a7d9a89
MCC
774static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q,
775 char __user *data,
776 size_t count, loff_t *ppos)
777{
778 enum v4l2_field field;
e2c77314 779 unsigned long flags = 0;
7a7d9a89
MCC
780 int retval;
781
e2c77314 782 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
7a7d9a89
MCC
783
784 /* setup stuff */
33c38283 785 q->read_buf = videobuf_alloc_vb(q);
7a7d9a89
MCC
786 if (NULL == q->read_buf)
787 return -ENOMEM;
788
789 q->read_buf->memory = V4L2_MEMORY_USERPTR;
790 q->read_buf->baddr = (unsigned long)data;
791 q->read_buf->bsize = count;
792
793 field = videobuf_next_field(q);
e2c77314 794 retval = q->ops->buf_prepare(q, q->read_buf, field);
7a7d9a89
MCC
795 if (0 != retval)
796 goto done;
797
798 /* start capture & wait */
0cf4daee 799 spin_lock_irqsave(q->irqlock, flags);
e2c77314 800 q->ops->buf_queue(q, q->read_buf);
0cf4daee 801 spin_unlock_irqrestore(q->irqlock, flags);
e2c77314 802 retval = videobuf_waiton(q->read_buf, 0, 0);
7a7d9a89 803 if (0 == retval) {
e2c77314 804 CALL(q, sync, q, q->read_buf);
0fc0686e 805 if (VIDEOBUF_ERROR == q->read_buf->state)
7a7d9a89
MCC
806 retval = -EIO;
807 else
808 retval = q->read_buf->size;
809 }
810
7a02264c 811done:
7a7d9a89 812 /* cleanup */
e2c77314 813 q->ops->buf_release(q, q->read_buf);
7a7d9a89
MCC
814 kfree(q->read_buf);
815 q->read_buf = NULL;
816 return retval;
817}
818
37111039
HV
819static int __videobuf_copy_to_user(struct videobuf_queue *q,
820 struct videobuf_buffer *buf,
821 char __user *data, size_t count,
822 int nonblocking)
823{
824 void *vaddr = CALL(q, vaddr, buf);
825
826 /* copy to userspace */
827 if (count > buf->size - q->read_off)
828 count = buf->size - q->read_off;
829
830 if (copy_to_user(data, vaddr + q->read_off, count))
831 return -EFAULT;
832
833 return count;
834}
835
836static int __videobuf_copy_stream(struct videobuf_queue *q,
837 struct videobuf_buffer *buf,
838 char __user *data, size_t count, size_t pos,
839 int vbihack, int nonblocking)
840{
841 unsigned int *fc = CALL(q, vaddr, buf);
842
843 if (vbihack) {
844 /* dirty, undocumented hack -- pass the frame counter
845 * within the last four bytes of each vbi data block.
846 * We need that one to maintain backward compatibility
847 * to all vbi decoding software out there ... */
848 fc += (buf->size >> 2) - 1;
849 *fc = buf->field_count >> 1;
850 dprintk(1, "vbihack: %d\n", *fc);
851 }
852
853 /* copy stuff using the common method */
854 count = __videobuf_copy_to_user(q, buf, data, count, nonblocking);
855
856 if ((count == -EFAULT) && (pos == 0))
857 return -EFAULT;
858
859 return count;
860}
861
7a7d9a89
MCC
862ssize_t videobuf_read_one(struct videobuf_queue *q,
863 char __user *data, size_t count, loff_t *ppos,
864 int nonblocking)
865{
866 enum v4l2_field field;
e2c77314 867 unsigned long flags = 0;
7daa4a88 868 unsigned size = 0, nbufs = 1;
7a7d9a89
MCC
869 int retval;
870
e2c77314 871 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
7a7d9a89 872
97397687 873 videobuf_queue_lock(q);
7a7d9a89 874
e2c77314 875 q->ops->buf_setup(q, &nbufs, &size);
7a7d9a89
MCC
876
877 if (NULL == q->read_buf &&
878 count >= size &&
879 !nonblocking) {
e2c77314 880 retval = videobuf_read_zerocopy(q, data, count, ppos);
7a7d9a89
MCC
881 if (retval >= 0 || retval == -EIO)
882 /* ok, all done */
883 goto done;
884 /* fallback to kernel bounce buffer on failures */
885 }
886
887 if (NULL == q->read_buf) {
888 /* need to capture a new frame */
889 retval = -ENOMEM;
33c38283 890 q->read_buf = videobuf_alloc_vb(q);
7a7d9a89 891
e2c77314 892 dprintk(1, "video alloc=0x%p\n", q->read_buf);
7a7d9a89
MCC
893 if (NULL == q->read_buf)
894 goto done;
895 q->read_buf->memory = V4L2_MEMORY_USERPTR;
896 q->read_buf->bsize = count; /* preferred size */
897 field = videobuf_next_field(q);
e2c77314 898 retval = q->ops->buf_prepare(q, q->read_buf, field);
7a7d9a89
MCC
899
900 if (0 != retval) {
e2c77314 901 kfree(q->read_buf);
7a7d9a89
MCC
902 q->read_buf = NULL;
903 goto done;
904 }
7a7d9a89 905
0cf4daee 906 spin_lock_irqsave(q->irqlock, flags);
e2c77314 907 q->ops->buf_queue(q, q->read_buf);
0cf4daee
BP
908 spin_unlock_irqrestore(q->irqlock, flags);
909
7a7d9a89
MCC
910 q->read_off = 0;
911 }
912
913 /* wait until capture is done */
914 retval = videobuf_waiton(q->read_buf, nonblocking, 1);
915 if (0 != retval)
916 goto done;
917
e2c77314 918 CALL(q, sync, q, q->read_buf);
7a7d9a89 919
0fc0686e 920 if (VIDEOBUF_ERROR == q->read_buf->state) {
7a7d9a89 921 /* catch I/O errors */
e2c77314 922 q->ops->buf_release(q, q->read_buf);
7a7d9a89
MCC
923 kfree(q->read_buf);
924 q->read_buf = NULL;
925 retval = -EIO;
926 goto done;
927 }
928
929 /* Copy to userspace */
37111039 930 retval = __videobuf_copy_to_user(q, q->read_buf, data, count, nonblocking);
e2c77314 931 if (retval < 0)
7a7d9a89
MCC
932 goto done;
933
934 q->read_off += retval;
935 if (q->read_off == q->read_buf->size) {
936 /* all data copied, cleanup */
e2c77314 937 q->ops->buf_release(q, q->read_buf);
7a7d9a89
MCC
938 kfree(q->read_buf);
939 q->read_buf = NULL;
940 }
941
7a02264c 942done:
97397687 943 videobuf_queue_unlock(q);
7a7d9a89
MCC
944 return retval;
945}
7a02264c 946EXPORT_SYMBOL_GPL(videobuf_read_one);
7a7d9a89 947
64f9477f 948/* Locking: Caller holds q->vb_lock */
225ba900 949static int __videobuf_read_start(struct videobuf_queue *q)
7a7d9a89
MCC
950{
951 enum v4l2_field field;
e2c77314 952 unsigned long flags = 0;
49ee718e 953 unsigned int count = 0, size = 0;
7a7d9a89
MCC
954 int err, i;
955
e2c77314 956 q->ops->buf_setup(q, &count, &size);
7a7d9a89
MCC
957 if (count < 2)
958 count = 2;
959 if (count > VIDEO_MAX_FRAME)
960 count = VIDEO_MAX_FRAME;
961 size = PAGE_ALIGN(size);
962
19bc5133 963 err = __videobuf_mmap_setup(q, count, size, V4L2_MEMORY_USERPTR);
49ee718e 964 if (err < 0)
7a7d9a89
MCC
965 return err;
966
49ee718e
BP
967 count = err;
968
7a7d9a89
MCC
969 for (i = 0; i < count; i++) {
970 field = videobuf_next_field(q);
e2c77314 971 err = q->ops->buf_prepare(q, q->bufs[i], field);
7a7d9a89
MCC
972 if (err)
973 return err;
974 list_add_tail(&q->bufs[i]->stream, &q->stream);
975 }
0cf4daee 976 spin_lock_irqsave(q->irqlock, flags);
7a7d9a89 977 for (i = 0; i < count; i++)
e2c77314 978 q->ops->buf_queue(q, q->bufs[i]);
0cf4daee 979 spin_unlock_irqrestore(q->irqlock, flags);
7a7d9a89
MCC
980 q->reading = 1;
981 return 0;
982}
983
19bc5133 984static void __videobuf_read_stop(struct videobuf_queue *q)
7a7d9a89
MCC
985{
986 int i;
987
988 videobuf_queue_cancel(q);
a438d6da 989 __videobuf_free(q);
7a7d9a89
MCC
990 INIT_LIST_HEAD(&q->stream);
991 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
992 if (NULL == q->bufs[i])
993 continue;
994 kfree(q->bufs[i]);
995 q->bufs[i] = NULL;
996 }
997 q->read_buf = NULL;
19bc5133
BP
998}
999
19fb1457
MCC
1000int videobuf_read_start(struct videobuf_queue *q)
1001{
1002 int rc;
1003
97397687 1004 videobuf_queue_lock(q);
19fb1457 1005 rc = __videobuf_read_start(q);
97397687 1006 videobuf_queue_unlock(q);
19fb1457
MCC
1007
1008 return rc;
1009}
7a02264c 1010EXPORT_SYMBOL_GPL(videobuf_read_start);
19fb1457 1011
19bc5133
BP
1012void videobuf_read_stop(struct videobuf_queue *q)
1013{
97397687 1014 videobuf_queue_lock(q);
19bc5133 1015 __videobuf_read_stop(q);
97397687 1016 videobuf_queue_unlock(q);
19bc5133 1017}
7a02264c 1018EXPORT_SYMBOL_GPL(videobuf_read_stop);
19bc5133
BP
1019
1020void videobuf_stop(struct videobuf_queue *q)
1021{
97397687 1022 videobuf_queue_lock(q);
19bc5133
BP
1023
1024 if (q->streaming)
1025 __videobuf_streamoff(q);
1026
1027 if (q->reading)
1028 __videobuf_read_stop(q);
1029
97397687 1030 videobuf_queue_unlock(q);
7a7d9a89 1031}
7a02264c 1032EXPORT_SYMBOL_GPL(videobuf_stop);
19bc5133 1033
7a7d9a89
MCC
1034ssize_t videobuf_read_stream(struct videobuf_queue *q,
1035 char __user *data, size_t count, loff_t *ppos,
1036 int vbihack, int nonblocking)
1037{
1038 int rc, retval;
e2c77314 1039 unsigned long flags = 0;
7a7d9a89 1040
e2c77314 1041 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
7a7d9a89 1042
7e28adb2 1043 dprintk(2, "%s\n", __func__);
97397687 1044 videobuf_queue_lock(q);
7a7d9a89
MCC
1045 retval = -EBUSY;
1046 if (q->streaming)
1047 goto done;
1048 if (!q->reading) {
3f84307a 1049 retval = __videobuf_read_start(q);
7a7d9a89
MCC
1050 if (retval < 0)
1051 goto done;
1052 }
1053
1054 retval = 0;
1055 while (count > 0) {
1056 /* get / wait for data */
1057 if (NULL == q->read_buf) {
1058 q->read_buf = list_entry(q->stream.next,
1059 struct videobuf_buffer,
1060 stream);
1061 list_del(&q->read_buf->stream);
1062 q->read_off = 0;
1063 }
1064 rc = videobuf_waiton(q->read_buf, nonblocking, 1);
1065 if (rc < 0) {
1066 if (0 == retval)
1067 retval = rc;
1068 break;
1069 }
1070
0fc0686e 1071 if (q->read_buf->state == VIDEOBUF_DONE) {
37111039 1072 rc = __videobuf_copy_stream(q, q->read_buf, data + retval, count,
7a7d9a89
MCC
1073 retval, vbihack, nonblocking);
1074 if (rc < 0) {
1075 retval = rc;
1076 break;
1077 }
1078 retval += rc;
1079 count -= rc;
1080 q->read_off += rc;
1081 } else {
1082 /* some error */
1083 q->read_off = q->read_buf->size;
1084 if (0 == retval)
1085 retval = -EIO;
1086 }
1087
1088 /* requeue buffer when done with copying */
1089 if (q->read_off == q->read_buf->size) {
1090 list_add_tail(&q->read_buf->stream,
1091 &q->stream);
0cf4daee 1092 spin_lock_irqsave(q->irqlock, flags);
e2c77314 1093 q->ops->buf_queue(q, q->read_buf);
0cf4daee 1094 spin_unlock_irqrestore(q->irqlock, flags);
7a7d9a89
MCC
1095 q->read_buf = NULL;
1096 }
1097 if (retval < 0)
1098 break;
1099 }
1100
7a02264c 1101done:
97397687 1102 videobuf_queue_unlock(q);
7a7d9a89
MCC
1103 return retval;
1104}
7a02264c 1105EXPORT_SYMBOL_GPL(videobuf_read_stream);
7a7d9a89
MCC
1106
1107unsigned int videobuf_poll_stream(struct file *file,
1108 struct videobuf_queue *q,
1109 poll_table *wait)
1110{
1111 struct videobuf_buffer *buf = NULL;
1112 unsigned int rc = 0;
1113
97397687 1114 videobuf_queue_lock(q);
7a7d9a89
MCC
1115 if (q->streaming) {
1116 if (!list_empty(&q->stream))
1117 buf = list_entry(q->stream.next,
1118 struct videobuf_buffer, stream);
1119 } else {
1120 if (!q->reading)
3f84307a 1121 __videobuf_read_start(q);
7a7d9a89
MCC
1122 if (!q->reading) {
1123 rc = POLLERR;
1124 } else if (NULL == q->read_buf) {
1125 q->read_buf = list_entry(q->stream.next,
1126 struct videobuf_buffer,
1127 stream);
1128 list_del(&q->read_buf->stream);
1129 q->read_off = 0;
1130 }
1131 buf = q->read_buf;
1132 }
1133 if (!buf)
1134 rc = POLLERR;
1135
1136 if (0 == rc) {
1137 poll_wait(file, &buf->done, wait);
0fc0686e 1138 if (buf->state == VIDEOBUF_DONE ||
9b558434
PO
1139 buf->state == VIDEOBUF_ERROR) {
1140 switch (q->type) {
1141 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1142 case V4L2_BUF_TYPE_VBI_OUTPUT:
1143 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
1144 rc = POLLOUT | POLLWRNORM;
1145 break;
1146 default:
1147 rc = POLLIN | POLLRDNORM;
1148 break;
1149 }
1150 }
7a7d9a89 1151 }
97397687 1152 videobuf_queue_unlock(q);
7a7d9a89
MCC
1153 return rc;
1154}
7a02264c 1155EXPORT_SYMBOL_GPL(videobuf_poll_stream);
7a7d9a89 1156
7a02264c 1157int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma)
7a7d9a89 1158{
0b62b737
HV
1159 int rc = -EINVAL;
1160 int i;
7a7d9a89 1161
e2c77314 1162 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
7a7d9a89 1163
0b62b737
HV
1164 if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) {
1165 dprintk(1, "mmap appl bug: PROT_WRITE and MAP_SHARED are required\n");
1166 return -EINVAL;
1167 }
1168
97397687 1169 videobuf_queue_lock(q);
0b62b737
HV
1170 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
1171 struct videobuf_buffer *buf = q->bufs[i];
1172
1173 if (buf && buf->memory == V4L2_MEMORY_MMAP &&
1174 buf->boff == (vma->vm_pgoff << PAGE_SHIFT)) {
1175 rc = CALL(q, mmap_mapper, q, buf, vma);
1176 break;
1177 }
1178 }
97397687 1179 videobuf_queue_unlock(q);
7a7d9a89 1180
0b62b737 1181 return rc;
7a7d9a89 1182}
7a02264c 1183EXPORT_SYMBOL_GPL(videobuf_mmap_mapper);
7a7d9a89
MCC
1184
1185#ifdef CONFIG_VIDEO_V4L1_COMPAT
1186int videobuf_cgmbuf(struct videobuf_queue *q,
1187 struct video_mbuf *mbuf, int count)
1188{
1189 struct v4l2_requestbuffers req;
e2c77314 1190 int rc, i;
7a7d9a89 1191
e2c77314 1192 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
7a7d9a89 1193
e2c77314 1194 memset(&req, 0, sizeof(req));
7a7d9a89
MCC
1195 req.type = q->type;
1196 req.count = count;
1197 req.memory = V4L2_MEMORY_MMAP;
e2c77314 1198 rc = videobuf_reqbufs(q, &req);
7a7d9a89
MCC
1199 if (rc < 0)
1200 return rc;
1201
1202 mbuf->frames = req.count;
1203 mbuf->size = 0;
1204 for (i = 0; i < mbuf->frames; i++) {
1205 mbuf->offsets[i] = q->bufs[i]->boff;
7cbefad0 1206 mbuf->size += PAGE_ALIGN(q->bufs[i]->bsize);
7a7d9a89
MCC
1207 }
1208
1209 return 0;
1210}
a13625c5 1211EXPORT_SYMBOL_GPL(videobuf_cgmbuf);
7a7d9a89
MCC
1212#endif
1213