aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2011-01-12 04:50:24 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-21 19:31:35 -0400
commit908a0d7c588ef87e5cf0a26805e6002a78ac9d13 (patch)
tree91e0cb5cc13fd6f1c01867b327d6b751db131da1
parent53b5d5749b6fcca37c7ad60cd40feafadd390b70 (diff)
[media] v4l: mem2mem: port to videobuf2
Port memory-to-memory framework to videobuf2 framework. Add support for multi-planar Video for Linux 2 API extensions to the memory-to-memory driver framework. Based on the original patch written by Pawel Osciak. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/Kconfig4
-rw-r--r--drivers/media/video/v4l2-mem2mem.c232
-rw-r--r--include/media/v4l2-mem2mem.h56
3 files changed, 152 insertions, 140 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 8710d90f9e16..3749c8941d0c 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -42,7 +42,7 @@ config VIDEO_TUNER
42 42
43config V4L2_MEM2MEM_DEV 43config V4L2_MEM2MEM_DEV
44 tristate 44 tristate
45 depends on VIDEOBUF_GEN 45 depends on VIDEOBUF2_CORE
46 46
47config VIDEOBUF2_CORE 47config VIDEOBUF2_CORE
48 tristate 48 tristate
@@ -989,6 +989,7 @@ if V4L_MEM2MEM_DRIVERS
989config VIDEO_MEM2MEM_TESTDEV 989config VIDEO_MEM2MEM_TESTDEV
990 tristate "Virtual test device for mem2mem framework" 990 tristate "Virtual test device for mem2mem framework"
991 depends on VIDEO_DEV && VIDEO_V4L2 991 depends on VIDEO_DEV && VIDEO_V4L2
992 depends on BROKEN
992 select VIDEOBUF_VMALLOC 993 select VIDEOBUF_VMALLOC
993 select V4L2_MEM2MEM_DEV 994 select V4L2_MEM2MEM_DEV
994 default n 995 default n
@@ -999,6 +1000,7 @@ config VIDEO_MEM2MEM_TESTDEV
999config VIDEO_SAMSUNG_S5P_FIMC 1000config VIDEO_SAMSUNG_S5P_FIMC
1000 tristate "Samsung S5P FIMC (video postprocessor) driver" 1001 tristate "Samsung S5P FIMC (video postprocessor) driver"
1001 depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P 1002 depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
1003 depends on BROKEN
1002 select VIDEOBUF_DMA_CONTIG 1004 select VIDEOBUF_DMA_CONTIG
1003 select V4L2_MEM2MEM_DEV 1005 select V4L2_MEM2MEM_DEV
1004 help 1006 help
diff --git a/drivers/media/video/v4l2-mem2mem.c b/drivers/media/video/v4l2-mem2mem.c
index ac832a28e18e..a78e5c9be1a2 100644
--- a/drivers/media/video/v4l2-mem2mem.c
+++ b/drivers/media/video/v4l2-mem2mem.c
@@ -17,7 +17,7 @@
17#include <linux/sched.h> 17#include <linux/sched.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19 19
20#include <media/videobuf-core.h> 20#include <media/videobuf2-core.h>
21#include <media/v4l2-mem2mem.h> 21#include <media/v4l2-mem2mem.h>
22 22
23MODULE_DESCRIPTION("Mem to mem device framework for videobuf"); 23MODULE_DESCRIPTION("Mem to mem device framework for videobuf");
@@ -65,21 +65,16 @@ struct v4l2_m2m_dev {
65static struct v4l2_m2m_queue_ctx *get_queue_ctx(struct v4l2_m2m_ctx *m2m_ctx, 65static struct v4l2_m2m_queue_ctx *get_queue_ctx(struct v4l2_m2m_ctx *m2m_ctx,
66 enum v4l2_buf_type type) 66 enum v4l2_buf_type type)
67{ 67{
68 switch (type) { 68 if (V4L2_TYPE_IS_OUTPUT(type))
69 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
70 return &m2m_ctx->cap_q_ctx;
71 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
72 return &m2m_ctx->out_q_ctx; 69 return &m2m_ctx->out_q_ctx;
73 default: 70 else
74 printk(KERN_ERR "Invalid buffer type\n"); 71 return &m2m_ctx->cap_q_ctx;
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 */
82struct videobuf_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx, 77struct vb2_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx,
83 enum v4l2_buf_type type) 78 enum v4l2_buf_type type)
84{ 79{
85 struct v4l2_m2m_queue_ctx *q_ctx; 80 struct v4l2_m2m_queue_ctx *q_ctx;
@@ -95,27 +90,20 @@ EXPORT_SYMBOL(v4l2_m2m_get_vq);
95/** 90/**
96 * v4l2_m2m_next_buf() - return next buffer from the list of ready buffers 91 * v4l2_m2m_next_buf() - return next buffer from the list of ready buffers
97 */ 92 */
98void *v4l2_m2m_next_buf(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type) 93void *v4l2_m2m_next_buf(struct v4l2_m2m_queue_ctx *q_ctx)
99{ 94{
100 struct v4l2_m2m_queue_ctx *q_ctx; 95 struct v4l2_m2m_buffer *b = NULL;
101 struct videobuf_buffer *vb = NULL;
102 unsigned long flags; 96 unsigned long flags;
103 97
104 q_ctx = get_queue_ctx(m2m_ctx, type); 98 spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
105 if (!q_ctx)
106 return NULL;
107
108 spin_lock_irqsave(q_ctx->q.irqlock, flags);
109 99
110 if (list_empty(&q_ctx->rdy_queue)) 100 if (list_empty(&q_ctx->rdy_queue))
111 goto end; 101 goto end;
112 102
113 vb = list_entry(q_ctx->rdy_queue.next, struct videobuf_buffer, queue); 103 b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer, list);
114 vb->state = VIDEOBUF_ACTIVE;
115
116end: 104end:
117 spin_unlock_irqrestore(q_ctx->q.irqlock, flags); 105 spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
118 return vb; 106 return &b->vb;
119} 107}
120EXPORT_SYMBOL_GPL(v4l2_m2m_next_buf); 108EXPORT_SYMBOL_GPL(v4l2_m2m_next_buf);
121 109
@@ -123,26 +111,21 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_next_buf);
123 * v4l2_m2m_buf_remove() - take off a buffer from the list of ready buffers and 111 * v4l2_m2m_buf_remove() - take off a buffer from the list of ready buffers and
124 * return it 112 * return it
125 */ 113 */
126void *v4l2_m2m_buf_remove(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type) 114void *v4l2_m2m_buf_remove(struct v4l2_m2m_queue_ctx *q_ctx)
127{ 115{
128 struct v4l2_m2m_queue_ctx *q_ctx; 116 struct v4l2_m2m_buffer *b = NULL;
129 struct videobuf_buffer *vb = NULL;
130 unsigned long flags; 117 unsigned long flags;
131 118
132 q_ctx = get_queue_ctx(m2m_ctx, type); 119 spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
133 if (!q_ctx)
134 return NULL;
135
136 spin_lock_irqsave(q_ctx->q.irqlock, flags);
137 if (!list_empty(&q_ctx->rdy_queue)) { 120 if (!list_empty(&q_ctx->rdy_queue)) {
138 vb = list_entry(q_ctx->rdy_queue.next, struct videobuf_buffer, 121 b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer,
139 queue); 122 list);
140 list_del(&vb->queue); 123 list_del(&b->list);
141 q_ctx->num_rdy--; 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}
147EXPORT_SYMBOL_GPL(v4l2_m2m_buf_remove); 130EXPORT_SYMBOL_GPL(v4l2_m2m_buf_remove);
148 131
@@ -235,20 +218,20 @@ static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
235 return; 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 if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue)) { 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 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); 224 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
242 dprintk("No input buffers available\n"); 225 dprintk("No input buffers available\n");
243 return; 226 return;
244 } 227 }
245 if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue)) { 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 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); 230 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
248 dprintk("No output buffers available\n"); 231 dprintk("No output buffers available\n");
249 return; 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 if (m2m_dev->m2m_ops->job_ready 236 if (m2m_dev->m2m_ops->job_ready
254 && (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) { 237 && (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) {
@@ -291,6 +274,7 @@ void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev,
291 274
292 list_del(&m2m_dev->curr_ctx->queue); 275 list_del(&m2m_dev->curr_ctx->queue);
293 m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); 276 m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
277 wake_up(&m2m_dev->curr_ctx->finished);
294 m2m_dev->curr_ctx = NULL; 278 m2m_dev->curr_ctx = NULL;
295 279
296 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); 280 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
@@ -309,10 +293,10 @@ EXPORT_SYMBOL(v4l2_m2m_job_finish);
309int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, 293int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
310 struct v4l2_requestbuffers *reqbufs) 294 struct v4l2_requestbuffers *reqbufs)
311{ 295{
312 struct videobuf_queue *vq; 296 struct vb2_queue *vq;
313 297
314 vq = v4l2_m2m_get_vq(m2m_ctx, reqbufs->type); 298 vq = v4l2_m2m_get_vq(m2m_ctx, reqbufs->type);
315 return videobuf_reqbufs(vq, reqbufs); 299 return vb2_reqbufs(vq, reqbufs);
316} 300}
317EXPORT_SYMBOL_GPL(v4l2_m2m_reqbufs); 301EXPORT_SYMBOL_GPL(v4l2_m2m_reqbufs);
318 302
@@ -324,15 +308,22 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_reqbufs);
324int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, 308int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
325 struct v4l2_buffer *buf) 309 struct v4l2_buffer *buf)
326{ 310{
327 struct videobuf_queue *vq; 311 struct vb2_queue *vq;
328 int ret; 312 int ret = 0;
313 unsigned int i;
329 314
330 vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); 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 318 /* Adjust MMAP memory offsets for the CAPTURE queue */
334 && vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 319 if (buf->memory == V4L2_MEMORY_MMAP && !V4L2_TYPE_IS_OUTPUT(vq->type)) {
335 buf->m.offset += DST_QUEUE_OFF_BASE; 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 return ret; 329 return ret;
@@ -346,11 +337,11 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_querybuf);
346int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, 337int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
347 struct v4l2_buffer *buf) 338 struct v4l2_buffer *buf)
348{ 339{
349 struct videobuf_queue *vq; 340 struct vb2_queue *vq;
350 int ret; 341 int ret;
351 342
352 vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); 343 vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
353 ret = videobuf_qbuf(vq, buf); 344 ret = vb2_qbuf(vq, buf);
354 if (!ret) 345 if (!ret)
355 v4l2_m2m_try_schedule(m2m_ctx); 346 v4l2_m2m_try_schedule(m2m_ctx);
356 347
@@ -365,10 +356,10 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_qbuf);
365int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, 356int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
366 struct v4l2_buffer *buf) 357 struct v4l2_buffer *buf)
367{ 358{
368 struct videobuf_queue *vq; 359 struct vb2_queue *vq;
369 360
370 vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); 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}
373EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf); 364EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf);
374 365
@@ -378,11 +369,11 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf);
378int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, 369int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
379 enum v4l2_buf_type type) 370 enum v4l2_buf_type type)
380{ 371{
381 struct videobuf_queue *vq; 372 struct vb2_queue *vq;
382 int ret; 373 int ret;
383 374
384 vq = v4l2_m2m_get_vq(m2m_ctx, type); 375 vq = v4l2_m2m_get_vq(m2m_ctx, type);
385 ret = videobuf_streamon(vq); 376 ret = vb2_streamon(vq, type);
386 if (!ret) 377 if (!ret)
387 v4l2_m2m_try_schedule(m2m_ctx); 378 v4l2_m2m_try_schedule(m2m_ctx);
388 379
@@ -396,10 +387,10 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_streamon);
396int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, 387int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
397 enum v4l2_buf_type type) 388 enum v4l2_buf_type type)
398{ 389{
399 struct videobuf_queue *vq; 390 struct vb2_queue *vq;
400 391
401 vq = v4l2_m2m_get_vq(m2m_ctx, type); 392 vq = v4l2_m2m_get_vq(m2m_ctx, type);
402 return videobuf_streamoff(vq); 393 return vb2_streamoff(vq, type);
403} 394}
404EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff); 395EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff);
405 396
@@ -414,44 +405,53 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff);
414unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, 405unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
415 struct poll_table_struct *wait) 406 struct poll_table_struct *wait)
416{ 407{
417 struct videobuf_queue *src_q, *dst_q; 408 struct vb2_queue *src_q, *dst_q;
418 struct videobuf_buffer *src_vb = NULL, *dst_vb = NULL; 409 struct vb2_buffer *src_vb = NULL, *dst_vb = NULL;
419 unsigned int rc = 0; 410 unsigned int rc = 0;
411 unsigned long flags;
420 412
421 src_q = v4l2_m2m_get_src_vq(m2m_ctx); 413 src_q = v4l2_m2m_get_src_vq(m2m_ctx);
422 dst_q = v4l2_m2m_get_dst_vq(m2m_ctx); 414 dst_q = v4l2_m2m_get_dst_vq(m2m_ctx);
423 415
424 videobuf_queue_lock(src_q); 416 /*
425 videobuf_queue_lock(dst_q); 417 * There has to be at least one buffer queued on each queued_list, which
426 418 * means either in driver already or waiting for driver to claim it
427 if (src_q->streaming && !list_empty(&src_q->stream)) 419 * and start processing.
428 src_vb = list_first_entry(&src_q->stream, 420 */
429 struct videobuf_buffer, stream); 421 if ((!src_q->streaming || list_empty(&src_q->queued_list))
430 if (dst_q->streaming && !list_empty(&dst_q->stream)) 422 && (!dst_q->streaming || list_empty(&dst_q->queued_list))) {
431 dst_vb = list_first_entry(&dst_q->stream,
432 struct videobuf_buffer, stream);
433
434 if (!src_vb && !dst_vb) {
435 rc = POLLERR; 423 rc = POLLERR;
436 goto end; 424 goto end;
437 } 425 }
438 426
439 if (src_vb) { 427 if (m2m_ctx->m2m_dev->m2m_ops->unlock)
440 poll_wait(file, &src_vb->done, wait); 428 m2m_ctx->m2m_dev->m2m_ops->unlock(m2m_ctx->priv);
441 if (src_vb->state == VIDEOBUF_DONE 429
442 || src_vb->state == VIDEOBUF_ERROR) 430 poll_wait(file, &src_q->done_wq, wait);
443 rc |= POLLOUT | POLLWRNORM; 431 poll_wait(file, &dst_q->done_wq, wait);
444 } 432
445 if (dst_vb) { 433 if (m2m_ctx->m2m_dev->m2m_ops->lock)
446 poll_wait(file, &dst_vb->done, wait); 434 m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv);
447 if (dst_vb->state == VIDEOBUF_DONE 435
448 || dst_vb->state == VIDEOBUF_ERROR) 436 spin_lock_irqsave(&src_q->done_lock, flags);
449 rc |= POLLIN | POLLRDNORM; 437 if (!list_empty(&src_q->done_list))
450 } 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
452end: 454end:
453 videobuf_queue_unlock(dst_q);
454 videobuf_queue_unlock(src_q);
455 return rc; 455 return rc;
456} 456}
457EXPORT_SYMBOL_GPL(v4l2_m2m_poll); 457EXPORT_SYMBOL_GPL(v4l2_m2m_poll);
@@ -470,7 +470,7 @@ int v4l2_m2m_mmap(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
470 struct vm_area_struct *vma) 470 struct vm_area_struct *vma)
471{ 471{
472 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; 472 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
473 struct videobuf_queue *vq; 473 struct vb2_queue *vq;
474 474
475 if (offset < DST_QUEUE_OFF_BASE) { 475 if (offset < DST_QUEUE_OFF_BASE) {
476 vq = v4l2_m2m_get_src_vq(m2m_ctx); 476 vq = v4l2_m2m_get_src_vq(m2m_ctx);
@@ -479,7 +479,7 @@ int v4l2_m2m_mmap(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
479 vma->vm_pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT); 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}
484EXPORT_SYMBOL(v4l2_m2m_mmap); 484EXPORT_SYMBOL(v4l2_m2m_mmap);
485 485
@@ -531,36 +531,41 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_release);
531 * 531 *
532 * Usually called from driver's open() function. 532 * Usually called from driver's open() function.
533 */ 533 */
534struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(void *priv, struct v4l2_m2m_dev *m2m_dev, 534struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev,
535 void (*vq_init)(void *priv, struct videobuf_queue *, 535 void *drv_priv,
536 enum v4l2_buf_type)) 536 int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq))
537{ 537{
538 struct v4l2_m2m_ctx *m2m_ctx; 538 struct v4l2_m2m_ctx *m2m_ctx;
539 struct v4l2_m2m_queue_ctx *out_q_ctx, *cap_q_ctx; 539 struct v4l2_m2m_queue_ctx *out_q_ctx, *cap_q_ctx;
540 540 int ret;
541 if (!vq_init)
542 return ERR_PTR(-EINVAL);
543 541
544 m2m_ctx = kzalloc(sizeof *m2m_ctx, GFP_KERNEL); 542 m2m_ctx = kzalloc(sizeof *m2m_ctx, GFP_KERNEL);
545 if (!m2m_ctx) 543 if (!m2m_ctx)
546 return ERR_PTR(-ENOMEM); 544 return ERR_PTR(-ENOMEM);
547 545
548 m2m_ctx->priv = priv; 546 m2m_ctx->priv = drv_priv;
549 m2m_ctx->m2m_dev = m2m_dev; 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); 550 out_q_ctx = &m2m_ctx->out_q_ctx;
552 cap_q_ctx = get_queue_ctx(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); 551 cap_q_ctx = &m2m_ctx->cap_q_ctx;
553 552
554 INIT_LIST_HEAD(&out_q_ctx->rdy_queue); 553 INIT_LIST_HEAD(&out_q_ctx->rdy_queue);
555 INIT_LIST_HEAD(&cap_q_ctx->rdy_queue); 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 INIT_LIST_HEAD(&m2m_ctx->queue); 558 INIT_LIST_HEAD(&m2m_ctx->queue);
558 559
559 vq_init(priv, &out_q_ctx->q, V4L2_BUF_TYPE_VIDEO_OUTPUT); 560 ret = queue_init(drv_priv, &out_q_ctx->q, &cap_q_ctx->q);
560 vq_init(priv, &cap_q_ctx->q, V4L2_BUF_TYPE_VIDEO_CAPTURE); 561
561 out_q_ctx->q.priv_data = cap_q_ctx->q.priv_data = priv; 562 if (ret)
563 goto err;
562 564
563 return m2m_ctx; 565 return m2m_ctx;
566err:
567 kfree(m2m_ctx);
568 return ERR_PTR(ret);
564} 569}
565EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_init); 570EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_init);
566 571
@@ -572,7 +577,6 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_init);
572void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx) 577void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx)
573{ 578{
574 struct v4l2_m2m_dev *m2m_dev; 579 struct v4l2_m2m_dev *m2m_dev;
575 struct videobuf_buffer *vb;
576 unsigned long flags; 580 unsigned long flags;
577 581
578 m2m_dev = m2m_ctx->m2m_dev; 582 m2m_dev = m2m_ctx->m2m_dev;
@@ -582,10 +586,7 @@ void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx)
582 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); 586 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
583 m2m_dev->m2m_ops->job_abort(m2m_ctx->priv); 587 m2m_dev->m2m_ops->job_abort(m2m_ctx->priv);
584 dprintk("m2m_ctx %p running, will wait to complete", m2m_ctx); 588 dprintk("m2m_ctx %p running, will wait to complete", m2m_ctx);
585 vb = v4l2_m2m_next_dst_buf(m2m_ctx); 589 wait_event(m2m_ctx->finished, !(m2m_ctx->job_flags & TRANS_RUNNING));
586 BUG_ON(NULL == vb);
587 wait_event(vb->done, vb->state != VIDEOBUF_ACTIVE
588 && vb->state != VIDEOBUF_QUEUED);
589 } else if (m2m_ctx->job_flags & TRANS_QUEUED) { 590 } else if (m2m_ctx->job_flags & TRANS_QUEUED) {
590 list_del(&m2m_ctx->queue); 591 list_del(&m2m_ctx->queue);
591 m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); 592 m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
@@ -597,11 +598,8 @@ void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx)
597 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); 598 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
598 } 599 }
599 600
600 videobuf_stop(&m2m_ctx->cap_q_ctx.q); 601 vb2_queue_release(&m2m_ctx->cap_q_ctx.q);
601 videobuf_stop(&m2m_ctx->out_q_ctx.q); 602 vb2_queue_release(&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);
605 603
606 kfree(m2m_ctx); 604 kfree(m2m_ctx);
607} 605}
@@ -611,23 +609,21 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_release);
611 * v4l2_m2m_buf_queue() - add a buffer to the proper ready buffers list. 609 * v4l2_m2m_buf_queue() - add a buffer to the proper ready buffers list.
612 * 610 *
613 * Call from buf_queue(), videobuf_queue_ops callback. 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 */
618void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct videobuf_queue *vq, 613void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb)
619 struct videobuf_buffer *vb)
620{ 614{
615 struct v4l2_m2m_buffer *b = container_of(vb, struct v4l2_m2m_buffer, vb);
621 struct v4l2_m2m_queue_ctx *q_ctx; 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 if (!q_ctx) 620 if (!q_ctx)
625 return; 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 q_ctx->num_rdy++; 625 q_ctx->num_rdy++;
629 626 spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
630 vb->state = VIDEOBUF_QUEUED;
631} 627}
632EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue); 628EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue);
633 629
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index 8d149f1c58d0..bf5eaaf3bd97 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -17,7 +17,7 @@
17#ifndef _MEDIA_V4L2_MEM2MEM_H 17#ifndef _MEDIA_V4L2_MEM2MEM_H
18#define _MEDIA_V4L2_MEM2MEM_H 18#define _MEDIA_V4L2_MEM2MEM_H
19 19
20#include <media/videobuf-core.h> 20#include <media/videobuf2-core.h>
21 21
22/** 22/**
23 * struct v4l2_m2m_ops - mem-to-mem device driver callbacks 23 * struct v4l2_m2m_ops - mem-to-mem device driver callbacks
@@ -45,17 +45,20 @@ struct v4l2_m2m_ops {
45 void (*device_run)(void *priv); 45 void (*device_run)(void *priv);
46 int (*job_ready)(void *priv); 46 int (*job_ready)(void *priv);
47 void (*job_abort)(void *priv); 47 void (*job_abort)(void *priv);
48 void (*lock)(void *priv);
49 void (*unlock)(void *priv);
48}; 50};
49 51
50struct v4l2_m2m_dev; 52struct v4l2_m2m_dev;
51 53
52struct v4l2_m2m_queue_ctx { 54struct v4l2_m2m_queue_ctx {
53/* private: internal use only */ 55/* private: internal use only */
54 struct videobuf_queue q; 56 struct vb2_queue q;
55 57
56 /* Queue for buffers ready to be processed as soon as this 58 /* Queue for buffers ready to be processed as soon as this
57 * instance receives access to the device */ 59 * instance receives access to the device */
58 struct list_head rdy_queue; 60 struct list_head rdy_queue;
61 spinlock_t rdy_spinlock;
59 u8 num_rdy; 62 u8 num_rdy;
60}; 63};
61 64
@@ -72,19 +75,31 @@ struct v4l2_m2m_ctx {
72 /* For device job queue */ 75 /* For device job queue */
73 struct list_head queue; 76 struct list_head queue;
74 unsigned long job_flags; 77 unsigned long job_flags;
78 wait_queue_head_t finished;
75 79
76 /* Instance private data */ 80 /* Instance private data */
77 void *priv; 81 void *priv;
78}; 82};
79 83
84struct v4l2_m2m_buffer {
85 struct vb2_buffer vb;
86 struct list_head list;
87};
88
80void *v4l2_m2m_get_curr_priv(struct v4l2_m2m_dev *m2m_dev); 89void *v4l2_m2m_get_curr_priv(struct v4l2_m2m_dev *m2m_dev);
81 90
82struct videobuf_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx, 91struct vb2_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx,
83 enum v4l2_buf_type type); 92 enum v4l2_buf_type type);
84 93
85void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, 94void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev,
86 struct v4l2_m2m_ctx *m2m_ctx); 95 struct v4l2_m2m_ctx *m2m_ctx);
87 96
97static inline void
98v4l2_m2m_buf_done(struct vb2_buffer *buf, enum vb2_buffer_state state)
99{
100 vb2_buffer_done(buf, state);
101}
102
88int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, 103int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
89 struct v4l2_requestbuffers *reqbufs); 104 struct v4l2_requestbuffers *reqbufs);
90 105
@@ -110,13 +125,13 @@ int v4l2_m2m_mmap(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
110struct v4l2_m2m_dev *v4l2_m2m_init(struct v4l2_m2m_ops *m2m_ops); 125struct v4l2_m2m_dev *v4l2_m2m_init(struct v4l2_m2m_ops *m2m_ops);
111void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev); 126void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev);
112 127
113struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(void *priv, struct v4l2_m2m_dev *m2m_dev, 128struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev,
114 void (*vq_init)(void *priv, struct videobuf_queue *, 129 void *drv_priv,
115 enum v4l2_buf_type)); 130 int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq));
131
116void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx); 132void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx);
117 133
118void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct videobuf_queue *vq, 134void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb);
119 struct videobuf_buffer *vb);
120 135
121/** 136/**
122 * v4l2_m2m_num_src_bufs_ready() - return the number of source buffers ready for 137 * v4l2_m2m_num_src_bufs_ready() - return the number of source buffers ready for
@@ -138,7 +153,7 @@ unsigned int v4l2_m2m_num_dst_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx)
138 return m2m_ctx->out_q_ctx.num_rdy; 153 return m2m_ctx->out_q_ctx.num_rdy;
139} 154}
140 155
141void *v4l2_m2m_next_buf(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type); 156void *v4l2_m2m_next_buf(struct v4l2_m2m_queue_ctx *q_ctx);
142 157
143/** 158/**
144 * v4l2_m2m_next_src_buf() - return next source buffer from the list of ready 159 * v4l2_m2m_next_src_buf() - return next source buffer from the list of ready
@@ -146,7 +161,7 @@ void *v4l2_m2m_next_buf(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type);
146 */ 161 */
147static inline void *v4l2_m2m_next_src_buf(struct v4l2_m2m_ctx *m2m_ctx) 162static inline void *v4l2_m2m_next_src_buf(struct v4l2_m2m_ctx *m2m_ctx)
148{ 163{
149 return v4l2_m2m_next_buf(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); 164 return v4l2_m2m_next_buf(&m2m_ctx->out_q_ctx);
150} 165}
151 166
152/** 167/**
@@ -155,29 +170,28 @@ static inline void *v4l2_m2m_next_src_buf(struct v4l2_m2m_ctx *m2m_ctx)
155 */ 170 */
156static inline void *v4l2_m2m_next_dst_buf(struct v4l2_m2m_ctx *m2m_ctx) 171static inline void *v4l2_m2m_next_dst_buf(struct v4l2_m2m_ctx *m2m_ctx)
157{ 172{
158 return v4l2_m2m_next_buf(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); 173 return v4l2_m2m_next_buf(&m2m_ctx->cap_q_ctx);
159} 174}
160 175
161/** 176/**
162 * v4l2_m2m_get_src_vq() - return videobuf_queue for source buffers 177 * v4l2_m2m_get_src_vq() - return vb2_queue for source buffers
163 */ 178 */
164static inline 179static inline
165struct videobuf_queue *v4l2_m2m_get_src_vq(struct v4l2_m2m_ctx *m2m_ctx) 180struct vb2_queue *v4l2_m2m_get_src_vq(struct v4l2_m2m_ctx *m2m_ctx)
166{ 181{
167 return v4l2_m2m_get_vq(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); 182 return &m2m_ctx->out_q_ctx.q;
168} 183}
169 184
170/** 185/**
171 * v4l2_m2m_get_dst_vq() - return videobuf_queue for destination buffers 186 * v4l2_m2m_get_dst_vq() - return vb2_queue for destination buffers
172 */ 187 */
173static inline 188static inline
174struct videobuf_queue *v4l2_m2m_get_dst_vq(struct v4l2_m2m_ctx *m2m_ctx) 189struct vb2_queue *v4l2_m2m_get_dst_vq(struct v4l2_m2m_ctx *m2m_ctx)
175{ 190{
176 return v4l2_m2m_get_vq(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); 191 return &m2m_ctx->cap_q_ctx.q;
177} 192}
178 193
179void *v4l2_m2m_buf_remove(struct v4l2_m2m_ctx *m2m_ctx, 194void *v4l2_m2m_buf_remove(struct v4l2_m2m_queue_ctx *q_ctx);
180 enum v4l2_buf_type type);
181 195
182/** 196/**
183 * v4l2_m2m_src_buf_remove() - take off a source buffer from the list of ready 197 * v4l2_m2m_src_buf_remove() - take off a source buffer from the list of ready
@@ -185,7 +199,7 @@ void *v4l2_m2m_buf_remove(struct v4l2_m2m_ctx *m2m_ctx,
185 */ 199 */
186static inline void *v4l2_m2m_src_buf_remove(struct v4l2_m2m_ctx *m2m_ctx) 200static inline void *v4l2_m2m_src_buf_remove(struct v4l2_m2m_ctx *m2m_ctx)
187{ 201{
188 return v4l2_m2m_buf_remove(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); 202 return v4l2_m2m_buf_remove(&m2m_ctx->out_q_ctx);
189} 203}
190 204
191/** 205/**
@@ -194,7 +208,7 @@ static inline void *v4l2_m2m_src_buf_remove(struct v4l2_m2m_ctx *m2m_ctx)
194 */ 208 */
195static inline void *v4l2_m2m_dst_buf_remove(struct v4l2_m2m_ctx *m2m_ctx) 209static inline void *v4l2_m2m_dst_buf_remove(struct v4l2_m2m_ctx *m2m_ctx)
196{ 210{
197 return v4l2_m2m_buf_remove(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); 211 return v4l2_m2m_buf_remove(&m2m_ctx->cap_q_ctx);
198} 212}
199 213
200#endif /* _MEDIA_V4L2_MEM2MEM_H */ 214#endif /* _MEDIA_V4L2_MEM2MEM_H */