~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/media/video/v4l2-mem2mem.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 * source and destination.
6
6
 *
7
7
 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
8
 
 * Pawel Osciak, <p.osciak@samsung.com>
 
8
 * Pawel Osciak, <pawel@osciak.com>
9
9
 * Marek Szyprowski, <m.szyprowski@samsung.com>
10
10
 *
11
11
 * This program is free software; you can redistribute it and/or modify
17
17
#include <linux/sched.h>
18
18
#include <linux/slab.h>
19
19
 
20
 
#include <media/videobuf-core.h>
 
20
#include <media/videobuf2-core.h>
21
21
#include <media/v4l2-mem2mem.h>
22
22
 
23
23
MODULE_DESCRIPTION("Mem to mem device framework for videobuf");
24
 
MODULE_AUTHOR("Pawel Osciak, <p.osciak@samsung.com>");
 
24
MODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
25
25
MODULE_LICENSE("GPL");
26
26
 
27
27
static bool debug;
65
65
static struct v4l2_m2m_queue_ctx *get_queue_ctx(struct v4l2_m2m_ctx *m2m_ctx,
66
66
                                                enum v4l2_buf_type type)
67
67
{
68
 
        switch (type) {
69
 
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 
68
        if (V4L2_TYPE_IS_OUTPUT(type))
 
69
                return &m2m_ctx->out_q_ctx;
 
70
        else
70
71
                return &m2m_ctx->cap_q_ctx;
71
 
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
72
 
                return &m2m_ctx->out_q_ctx;
73
 
        default:
74
 
                printk(KERN_ERR "Invalid buffer type\n");
75
 
                return NULL;
76
 
        }
77
72
}
78
73
 
79
74
/**
80
 
 * v4l2_m2m_get_vq() - return videobuf_queue for the given type
 
75
 * v4l2_m2m_get_vq() - return vb2_queue for the given type
81
76
 */
82
 
struct videobuf_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx,
 
77
struct vb2_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx,
83
78
                                       enum v4l2_buf_type type)
84
79
{
85
80
        struct v4l2_m2m_queue_ctx *q_ctx;
95
90
/**
96
91
 * v4l2_m2m_next_buf() - return next buffer from the list of ready buffers
97
92
 */
98
 
void *v4l2_m2m_next_buf(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type)
 
93
void *v4l2_m2m_next_buf(struct v4l2_m2m_queue_ctx *q_ctx)
99
94
{
100
 
        struct v4l2_m2m_queue_ctx *q_ctx;
101
 
        struct videobuf_buffer *vb = NULL;
 
95
        struct v4l2_m2m_buffer *b = NULL;
102
96
        unsigned long flags;
103
97
 
104
 
        q_ctx = get_queue_ctx(m2m_ctx, type);
105
 
        if (!q_ctx)
106
 
                return NULL;
107
 
 
108
 
        spin_lock_irqsave(q_ctx->q.irqlock, flags);
 
98
        spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
109
99
 
110
100
        if (list_empty(&q_ctx->rdy_queue))
111
101
                goto end;
112
102
 
113
 
        vb = list_entry(q_ctx->rdy_queue.next, struct videobuf_buffer, queue);
114
 
        vb->state = VIDEOBUF_ACTIVE;
115
 
 
 
103
        b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer, list);
116
104
end:
117
 
        spin_unlock_irqrestore(q_ctx->q.irqlock, flags);
118
 
        return vb;
 
105
        spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
 
106
        return &b->vb;
119
107
}
120
108
EXPORT_SYMBOL_GPL(v4l2_m2m_next_buf);
121
109
 
123
111
 * v4l2_m2m_buf_remove() - take off a buffer from the list of ready buffers and
124
112
 * return it
125
113
 */
126
 
void *v4l2_m2m_buf_remove(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type)
 
114
void *v4l2_m2m_buf_remove(struct v4l2_m2m_queue_ctx *q_ctx)
127
115
{
128
 
        struct v4l2_m2m_queue_ctx *q_ctx;
129
 
        struct videobuf_buffer *vb = NULL;
 
116
        struct v4l2_m2m_buffer *b = NULL;
130
117
        unsigned long flags;
131
118
 
132
 
        q_ctx = get_queue_ctx(m2m_ctx, type);
133
 
        if (!q_ctx)
134
 
                return NULL;
135
 
 
136
 
        spin_lock_irqsave(q_ctx->q.irqlock, flags);
 
119
        spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
137
120
        if (!list_empty(&q_ctx->rdy_queue)) {
138
 
                vb = list_entry(q_ctx->rdy_queue.next, struct videobuf_buffer,
139
 
                                queue);
140
 
                list_del(&vb->queue);
 
121
                b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer,
 
122
                                list);
 
123
                list_del(&b->list);
141
124
                q_ctx->num_rdy--;
142
125
        }
143
 
        spin_unlock_irqrestore(q_ctx->q.irqlock, flags);
 
126
        spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
144
127
 
145
 
        return vb;
 
128
        return &b->vb;
146
129
}
147
130
EXPORT_SYMBOL_GPL(v4l2_m2m_buf_remove);
148
131
 
235
218
                return;
236
219
        }
237
220
 
238
 
        spin_lock_irqsave(m2m_ctx->out_q_ctx.q.irqlock, flags);
 
221
        spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags);
239
222
        if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue)) {
240
 
                spin_unlock_irqrestore(m2m_ctx->out_q_ctx.q.irqlock, flags);
 
223
                spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags);
241
224
                spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
242
225
                dprintk("No input buffers available\n");
243
226
                return;
244
227
        }
245
228
        if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue)) {
246
 
                spin_unlock_irqrestore(m2m_ctx->out_q_ctx.q.irqlock, flags);
 
229
                spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags);
247
230
                spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
248
231
                dprintk("No output buffers available\n");
249
232
                return;
250
233
        }
251
 
        spin_unlock_irqrestore(m2m_ctx->out_q_ctx.q.irqlock, flags);
 
234
        spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags);
252
235
 
253
236
        if (m2m_dev->m2m_ops->job_ready
254
237
                && (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) {
291
274
 
292
275
        list_del(&m2m_dev->curr_ctx->queue);
293
276
        m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
 
277
        wake_up(&m2m_dev->curr_ctx->finished);
294
278
        m2m_dev->curr_ctx = NULL;
295
279
 
296
280
        spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
309
293
int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
310
294
                     struct v4l2_requestbuffers *reqbufs)
311
295
{
312
 
        struct videobuf_queue *vq;
 
296
        struct vb2_queue *vq;
313
297
 
314
298
        vq = v4l2_m2m_get_vq(m2m_ctx, reqbufs->type);
315
 
        return videobuf_reqbufs(vq, reqbufs);
 
299
        return vb2_reqbufs(vq, reqbufs);
316
300
}
317
301
EXPORT_SYMBOL_GPL(v4l2_m2m_reqbufs);
318
302
 
324
308
int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
325
309
                      struct v4l2_buffer *buf)
326
310
{
327
 
        struct videobuf_queue *vq;
328
 
        int ret;
 
311
        struct vb2_queue *vq;
 
312
        int ret = 0;
 
313
        unsigned int i;
329
314
 
330
315
        vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
331
 
        ret = videobuf_querybuf(vq, buf);
 
316
        ret = vb2_querybuf(vq, buf);
332
317
 
333
 
        if (buf->memory == V4L2_MEMORY_MMAP
334
 
            && vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
335
 
                buf->m.offset += DST_QUEUE_OFF_BASE;
 
318
        /* Adjust MMAP memory offsets for the CAPTURE queue */
 
319
        if (buf->memory == V4L2_MEMORY_MMAP && !V4L2_TYPE_IS_OUTPUT(vq->type)) {
 
320
                if (V4L2_TYPE_IS_MULTIPLANAR(vq->type)) {
 
321
                        for (i = 0; i < buf->length; ++i)
 
322
                                buf->m.planes[i].m.mem_offset
 
323
                                        += DST_QUEUE_OFF_BASE;
 
324
                } else {
 
325
                        buf->m.offset += DST_QUEUE_OFF_BASE;
 
326
                }
336
327
        }
337
328
 
338
329
        return ret;
346
337
int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
347
338
                  struct v4l2_buffer *buf)
348
339
{
349
 
        struct videobuf_queue *vq;
 
340
        struct vb2_queue *vq;
350
341
        int ret;
351
342
 
352
343
        vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
353
 
        ret = videobuf_qbuf(vq, buf);
 
344
        ret = vb2_qbuf(vq, buf);
354
345
        if (!ret)
355
346
                v4l2_m2m_try_schedule(m2m_ctx);
356
347
 
365
356
int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
366
357
                   struct v4l2_buffer *buf)
367
358
{
368
 
        struct videobuf_queue *vq;
 
359
        struct vb2_queue *vq;
369
360
 
370
361
        vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
371
 
        return videobuf_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
 
362
        return vb2_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
372
363
}
373
364
EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf);
374
365
 
378
369
int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
379
370
                      enum v4l2_buf_type type)
380
371
{
381
 
        struct videobuf_queue *vq;
 
372
        struct vb2_queue *vq;
382
373
        int ret;
383
374
 
384
375
        vq = v4l2_m2m_get_vq(m2m_ctx, type);
385
 
        ret = videobuf_streamon(vq);
 
376
        ret = vb2_streamon(vq, type);
386
377
        if (!ret)
387
378
                v4l2_m2m_try_schedule(m2m_ctx);
388
379
 
396
387
int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
397
388
                       enum v4l2_buf_type type)
398
389
{
399
 
        struct videobuf_queue *vq;
 
390
        struct vb2_queue *vq;
400
391
 
401
392
        vq = v4l2_m2m_get_vq(m2m_ctx, type);
402
 
        return videobuf_streamoff(vq);
 
393
        return vb2_streamoff(vq, type);
403
394
}
404
395
EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff);
405
396
 
414
405
unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
415
406
                           struct poll_table_struct *wait)
416
407
{
417
 
        struct videobuf_queue *src_q, *dst_q;
418
 
        struct videobuf_buffer *src_vb = NULL, *dst_vb = NULL;
 
408
        struct vb2_queue *src_q, *dst_q;
 
409
        struct vb2_buffer *src_vb = NULL, *dst_vb = NULL;
419
410
        unsigned int rc = 0;
 
411
        unsigned long flags;
420
412
 
421
413
        src_q = v4l2_m2m_get_src_vq(m2m_ctx);
422
414
        dst_q = v4l2_m2m_get_dst_vq(m2m_ctx);
423
415
 
424
 
        videobuf_queue_lock(src_q);
425
 
        videobuf_queue_lock(dst_q);
426
 
 
427
 
        if (src_q->streaming && !list_empty(&src_q->stream))
428
 
                src_vb = list_first_entry(&src_q->stream,
429
 
                                          struct videobuf_buffer, stream);
430
 
        if (dst_q->streaming && !list_empty(&dst_q->stream))
431
 
                dst_vb = list_first_entry(&dst_q->stream,
432
 
                                          struct videobuf_buffer, stream);
433
 
 
434
 
        if (!src_vb && !dst_vb) {
 
416
        /*
 
417
         * There has to be at least one buffer queued on each queued_list, which
 
418
         * means either in driver already or waiting for driver to claim it
 
419
         * and start processing.
 
420
         */
 
421
        if ((!src_q->streaming || list_empty(&src_q->queued_list))
 
422
                && (!dst_q->streaming || list_empty(&dst_q->queued_list))) {
435
423
                rc = POLLERR;
436
424
                goto end;
437
425
        }
438
426
 
439
 
        if (src_vb) {
440
 
                poll_wait(file, &src_vb->done, wait);
441
 
                if (src_vb->state == VIDEOBUF_DONE
442
 
                    || src_vb->state == VIDEOBUF_ERROR)
443
 
                        rc |= POLLOUT | POLLWRNORM;
444
 
        }
445
 
        if (dst_vb) {
446
 
                poll_wait(file, &dst_vb->done, wait);
447
 
                if (dst_vb->state == VIDEOBUF_DONE
448
 
                    || dst_vb->state == VIDEOBUF_ERROR)
449
 
                        rc |= POLLIN | POLLRDNORM;
450
 
        }
 
427
        if (m2m_ctx->m2m_dev->m2m_ops->unlock)
 
428
                m2m_ctx->m2m_dev->m2m_ops->unlock(m2m_ctx->priv);
 
429
 
 
430
        poll_wait(file, &src_q->done_wq, wait);
 
431
        poll_wait(file, &dst_q->done_wq, wait);
 
432
 
 
433
        if (m2m_ctx->m2m_dev->m2m_ops->lock)
 
434
                m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv);
 
435
 
 
436
        spin_lock_irqsave(&src_q->done_lock, flags);
 
437
        if (!list_empty(&src_q->done_list))
 
438
                src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer,
 
439
                                                done_entry);
 
440
        if (src_vb && (src_vb->state == VB2_BUF_STATE_DONE
 
441
                        || src_vb->state == VB2_BUF_STATE_ERROR))
 
442
                rc |= POLLOUT | POLLWRNORM;
 
443
        spin_unlock_irqrestore(&src_q->done_lock, flags);
 
444
 
 
445
        spin_lock_irqsave(&dst_q->done_lock, flags);
 
446
        if (!list_empty(&dst_q->done_list))
 
447
                dst_vb = list_first_entry(&dst_q->done_list, struct vb2_buffer,
 
448
                                                done_entry);
 
449
        if (dst_vb && (dst_vb->state == VB2_BUF_STATE_DONE
 
450
                        || dst_vb->state == VB2_BUF_STATE_ERROR))
 
451
                rc |= POLLIN | POLLRDNORM;
 
452
        spin_unlock_irqrestore(&dst_q->done_lock, flags);
451
453
 
452
454
end:
453
 
        videobuf_queue_unlock(dst_q);
454
 
        videobuf_queue_unlock(src_q);
455
455
        return rc;
456
456
}
457
457
EXPORT_SYMBOL_GPL(v4l2_m2m_poll);
470
470
                         struct vm_area_struct *vma)
471
471
{
472
472
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
473
 
        struct videobuf_queue *vq;
 
473
        struct vb2_queue *vq;
474
474
 
475
475
        if (offset < DST_QUEUE_OFF_BASE) {
476
476
                vq = v4l2_m2m_get_src_vq(m2m_ctx);
479
479
                vma->vm_pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT);
480
480
        }
481
481
 
482
 
        return videobuf_mmap_mapper(vq, vma);
 
482
        return vb2_mmap(vq, vma);
483
483
}
484
484
EXPORT_SYMBOL(v4l2_m2m_mmap);
485
485
 
531
531
 *
532
532
 * Usually called from driver's open() function.
533
533
 */
534
 
struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(void *priv, struct v4l2_m2m_dev *m2m_dev,
535
 
                        void (*vq_init)(void *priv, struct videobuf_queue *,
536
 
                                        enum v4l2_buf_type))
 
534
struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev,
 
535
                void *drv_priv,
 
536
                int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq))
537
537
{
538
538
        struct v4l2_m2m_ctx *m2m_ctx;
539
539
        struct v4l2_m2m_queue_ctx *out_q_ctx, *cap_q_ctx;
540
 
 
541
 
        if (!vq_init)
542
 
                return ERR_PTR(-EINVAL);
 
540
        int ret;
543
541
 
544
542
        m2m_ctx = kzalloc(sizeof *m2m_ctx, GFP_KERNEL);
545
543
        if (!m2m_ctx)
546
544
                return ERR_PTR(-ENOMEM);
547
545
 
548
 
        m2m_ctx->priv = priv;
 
546
        m2m_ctx->priv = drv_priv;
549
547
        m2m_ctx->m2m_dev = m2m_dev;
 
548
        init_waitqueue_head(&m2m_ctx->finished);
550
549
 
551
 
        out_q_ctx = get_queue_ctx(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
552
 
        cap_q_ctx = get_queue_ctx(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 
550
        out_q_ctx = &m2m_ctx->out_q_ctx;
 
551
        cap_q_ctx = &m2m_ctx->cap_q_ctx;
553
552
 
554
553
        INIT_LIST_HEAD(&out_q_ctx->rdy_queue);
555
554
        INIT_LIST_HEAD(&cap_q_ctx->rdy_queue);
 
555
        spin_lock_init(&out_q_ctx->rdy_spinlock);
 
556
        spin_lock_init(&cap_q_ctx->rdy_spinlock);
556
557
 
557
558
        INIT_LIST_HEAD(&m2m_ctx->queue);
558
559
 
559
 
        vq_init(priv, &out_q_ctx->q, V4L2_BUF_TYPE_VIDEO_OUTPUT);
560
 
        vq_init(priv, &cap_q_ctx->q, V4L2_BUF_TYPE_VIDEO_CAPTURE);
561
 
        out_q_ctx->q.priv_data = cap_q_ctx->q.priv_data = priv;
 
560
        ret = queue_init(drv_priv, &out_q_ctx->q, &cap_q_ctx->q);
 
561
 
 
562
        if (ret)
 
563
                goto err;
562
564
 
563
565
        return m2m_ctx;
 
566
err:
 
567
        kfree(m2m_ctx);
 
568
        return ERR_PTR(ret);
564
569
}
565
570
EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_init);
566
571
 
572
577
void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx)
573
578
{
574
579
        struct v4l2_m2m_dev *m2m_dev;
575
 
        struct videobuf_buffer *vb;
576
580
        unsigned long flags;
577
581
 
578
582
        m2m_dev = m2m_ctx->m2m_dev;
582
586
                spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
583
587
                m2m_dev->m2m_ops->job_abort(m2m_ctx->priv);
584
588
                dprintk("m2m_ctx %p running, will wait to complete", m2m_ctx);
585
 
                vb = v4l2_m2m_next_dst_buf(m2m_ctx);
586
 
                BUG_ON(NULL == vb);
587
 
                wait_event(vb->done, vb->state != VIDEOBUF_ACTIVE
588
 
                                     && vb->state != VIDEOBUF_QUEUED);
 
589
                wait_event(m2m_ctx->finished, !(m2m_ctx->job_flags & TRANS_RUNNING));
589
590
        } else if (m2m_ctx->job_flags & TRANS_QUEUED) {
590
591
                list_del(&m2m_ctx->queue);
591
592
                m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
597
598
                spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
598
599
        }
599
600
 
600
 
        videobuf_stop(&m2m_ctx->cap_q_ctx.q);
601
 
        videobuf_stop(&m2m_ctx->out_q_ctx.q);
602
 
 
603
 
        videobuf_mmap_free(&m2m_ctx->cap_q_ctx.q);
604
 
        videobuf_mmap_free(&m2m_ctx->out_q_ctx.q);
 
601
        vb2_queue_release(&m2m_ctx->cap_q_ctx.q);
 
602
        vb2_queue_release(&m2m_ctx->out_q_ctx.q);
605
603
 
606
604
        kfree(m2m_ctx);
607
605
}
611
609
 * v4l2_m2m_buf_queue() - add a buffer to the proper ready buffers list.
612
610
 *
613
611
 * Call from buf_queue(), videobuf_queue_ops callback.
614
 
 *
615
 
 * Locking: Caller holds q->irqlock (taken by videobuf before calling buf_queue
616
 
 * callback in the driver).
617
612
 */
618
 
void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct videobuf_queue *vq,
619
 
                        struct videobuf_buffer *vb)
 
613
void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb)
620
614
{
 
615
        struct v4l2_m2m_buffer *b = container_of(vb, struct v4l2_m2m_buffer, vb);
621
616
        struct v4l2_m2m_queue_ctx *q_ctx;
 
617
        unsigned long flags;
622
618
 
623
 
        q_ctx = get_queue_ctx(m2m_ctx, vq->type);
 
619
        q_ctx = get_queue_ctx(m2m_ctx, vb->vb2_queue->type);
624
620
        if (!q_ctx)
625
621
                return;
626
622
 
627
 
        list_add_tail(&vb->queue, &q_ctx->rdy_queue);
 
623
        spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
 
624
        list_add_tail(&b->list, &q_ctx->rdy_queue);
628
625
        q_ctx->num_rdy++;
629
 
 
630
 
        vb->state = VIDEOBUF_QUEUED;
 
626
        spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
631
627
}
632
628
EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue);
633
629