aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2011-01-12 04:50:55 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-21 19:31:35 -0400
commitd80ee38cd845baadef175893b99df24e7a03ec40 (patch)
treecd2c46fa8e57c4e0d9f382d7e21cd381ae6a9a27 /drivers
parent908a0d7c588ef87e5cf0a26805e6002a78ac9d13 (diff)
[media] v4l: mem2mem: port m2m_testdev to vb2
This patch ports mem2mem test device to videobuf2 framework. 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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/Kconfig3
-rw-r--r--drivers/media/video/mem2mem_testdev.c227
2 files changed, 107 insertions, 123 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 3749c8941d0c..1c0f080599e8 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -989,8 +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 VIDEOBUF2_VMALLOC
993 select VIDEOBUF_VMALLOC
994 select V4L2_MEM2MEM_DEV 993 select V4L2_MEM2MEM_DEV
995 default n 994 default n
996 ---help--- 995 ---help---
diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c
index e7e717800ee2..e1f96ea45bcb 100644
--- a/drivers/media/video/mem2mem_testdev.c
+++ b/drivers/media/video/mem2mem_testdev.c
@@ -28,7 +28,7 @@
28#include <media/v4l2-mem2mem.h> 28#include <media/v4l2-mem2mem.h>
29#include <media/v4l2-device.h> 29#include <media/v4l2-device.h>
30#include <media/v4l2-ioctl.h> 30#include <media/v4l2-ioctl.h>
31#include <media/videobuf-vmalloc.h> 31#include <media/videobuf2-vmalloc.h>
32 32
33#define MEM2MEM_TEST_MODULE_NAME "mem2mem-testdev" 33#define MEM2MEM_TEST_MODULE_NAME "mem2mem-testdev"
34 34
@@ -201,11 +201,6 @@ struct m2mtest_ctx {
201 struct v4l2_m2m_ctx *m2m_ctx; 201 struct v4l2_m2m_ctx *m2m_ctx;
202}; 202};
203 203
204struct m2mtest_buffer {
205 /* vb must be first! */
206 struct videobuf_buffer vb;
207};
208
209static struct v4l2_queryctrl *get_ctrl(int id) 204static struct v4l2_queryctrl *get_ctrl(int id)
210{ 205{
211 int i; 206 int i;
@@ -219,37 +214,41 @@ static struct v4l2_queryctrl *get_ctrl(int id)
219} 214}
220 215
221static int device_process(struct m2mtest_ctx *ctx, 216static int device_process(struct m2mtest_ctx *ctx,
222 struct m2mtest_buffer *in_buf, 217 struct vb2_buffer *in_vb,
223 struct m2mtest_buffer *out_buf) 218 struct vb2_buffer *out_vb)
224{ 219{
225 struct m2mtest_dev *dev = ctx->dev; 220 struct m2mtest_dev *dev = ctx->dev;
221 struct m2mtest_q_data *q_data;
226 u8 *p_in, *p_out; 222 u8 *p_in, *p_out;
227 int x, y, t, w; 223 int x, y, t, w;
228 int tile_w, bytes_left; 224 int tile_w, bytes_left;
229 struct videobuf_queue *src_q; 225 int width, height, bytesperline;
230 struct videobuf_queue *dst_q;
231 226
232 src_q = v4l2_m2m_get_src_vq(ctx->m2m_ctx); 227 q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT);
233 dst_q = v4l2_m2m_get_dst_vq(ctx->m2m_ctx); 228
234 p_in = videobuf_queue_to_vaddr(src_q, &in_buf->vb); 229 width = q_data->width;
235 p_out = videobuf_queue_to_vaddr(dst_q, &out_buf->vb); 230 height = q_data->height;
231 bytesperline = (q_data->width * q_data->fmt->depth) >> 3;
232
233 p_in = vb2_plane_vaddr(in_vb, 0);
234 p_out = vb2_plane_vaddr(out_vb, 0);
236 if (!p_in || !p_out) { 235 if (!p_in || !p_out) {
237 v4l2_err(&dev->v4l2_dev, 236 v4l2_err(&dev->v4l2_dev,
238 "Acquiring kernel pointers to buffers failed\n"); 237 "Acquiring kernel pointers to buffers failed\n");
239 return -EFAULT; 238 return -EFAULT;
240 } 239 }
241 240
242 if (in_buf->vb.size > out_buf->vb.size) { 241 if (vb2_plane_size(in_vb, 0) > vb2_plane_size(out_vb, 0)) {
243 v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n"); 242 v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n");
244 return -EINVAL; 243 return -EINVAL;
245 } 244 }
246 245
247 tile_w = (in_buf->vb.width * (q_data[V4L2_M2M_DST].fmt->depth >> 3)) 246 tile_w = (width * (q_data[V4L2_M2M_DST].fmt->depth >> 3))
248 / MEM2MEM_NUM_TILES; 247 / MEM2MEM_NUM_TILES;
249 bytes_left = in_buf->vb.bytesperline - tile_w * MEM2MEM_NUM_TILES; 248 bytes_left = bytesperline - tile_w * MEM2MEM_NUM_TILES;
250 w = 0; 249 w = 0;
251 250
252 for (y = 0; y < in_buf->vb.height; ++y) { 251 for (y = 0; y < height; ++y) {
253 for (t = 0; t < MEM2MEM_NUM_TILES; ++t) { 252 for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
254 if (w & 0x1) { 253 if (w & 0x1) {
255 for (x = 0; x < tile_w; ++x) 254 for (x = 0; x < tile_w; ++x)
@@ -301,6 +300,21 @@ static void job_abort(void *priv)
301 ctx->aborting = 1; 300 ctx->aborting = 1;
302} 301}
303 302
303static void m2mtest_lock(void *priv)
304{
305 struct m2mtest_ctx *ctx = priv;
306 struct m2mtest_dev *dev = ctx->dev;
307 mutex_lock(&dev->dev_mutex);
308}
309
310static void m2mtest_unlock(void *priv)
311{
312 struct m2mtest_ctx *ctx = priv;
313 struct m2mtest_dev *dev = ctx->dev;
314 mutex_unlock(&dev->dev_mutex);
315}
316
317
304/* device_run() - prepares and starts the device 318/* device_run() - prepares and starts the device
305 * 319 *
306 * This simulates all the immediate preparations required before starting 320 * This simulates all the immediate preparations required before starting
@@ -311,7 +325,7 @@ static void device_run(void *priv)
311{ 325{
312 struct m2mtest_ctx *ctx = priv; 326 struct m2mtest_ctx *ctx = priv;
313 struct m2mtest_dev *dev = ctx->dev; 327 struct m2mtest_dev *dev = ctx->dev;
314 struct m2mtest_buffer *src_buf, *dst_buf; 328 struct vb2_buffer *src_buf, *dst_buf;
315 329
316 src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); 330 src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
317 dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); 331 dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
@@ -322,12 +336,11 @@ static void device_run(void *priv)
322 schedule_irq(dev, ctx->transtime); 336 schedule_irq(dev, ctx->transtime);
323} 337}
324 338
325
326static void device_isr(unsigned long priv) 339static void device_isr(unsigned long priv)
327{ 340{
328 struct m2mtest_dev *m2mtest_dev = (struct m2mtest_dev *)priv; 341 struct m2mtest_dev *m2mtest_dev = (struct m2mtest_dev *)priv;
329 struct m2mtest_ctx *curr_ctx; 342 struct m2mtest_ctx *curr_ctx;
330 struct m2mtest_buffer *src_buf, *dst_buf; 343 struct vb2_buffer *src_vb, *dst_vb;
331 unsigned long flags; 344 unsigned long flags;
332 345
333 curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev); 346 curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev);
@@ -338,31 +351,26 @@ static void device_isr(unsigned long priv)
338 return; 351 return;
339 } 352 }
340 353
341 src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); 354 src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
342 dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); 355 dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
356
343 curr_ctx->num_processed++; 357 curr_ctx->num_processed++;
344 358
359 spin_lock_irqsave(&m2mtest_dev->irqlock, flags);
360 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
361 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
362 spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags);
363
345 if (curr_ctx->num_processed == curr_ctx->translen 364 if (curr_ctx->num_processed == curr_ctx->translen
346 || curr_ctx->aborting) { 365 || curr_ctx->aborting) {
347 dprintk(curr_ctx->dev, "Finishing transaction\n"); 366 dprintk(curr_ctx->dev, "Finishing transaction\n");
348 curr_ctx->num_processed = 0; 367 curr_ctx->num_processed = 0;
349 spin_lock_irqsave(&m2mtest_dev->irqlock, flags);
350 src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE;
351 wake_up(&src_buf->vb.done);
352 wake_up(&dst_buf->vb.done);
353 spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags);
354 v4l2_m2m_job_finish(m2mtest_dev->m2m_dev, curr_ctx->m2m_ctx); 368 v4l2_m2m_job_finish(m2mtest_dev->m2m_dev, curr_ctx->m2m_ctx);
355 } else { 369 } else {
356 spin_lock_irqsave(&m2mtest_dev->irqlock, flags);
357 src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE;
358 wake_up(&src_buf->vb.done);
359 wake_up(&dst_buf->vb.done);
360 spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags);
361 device_run(curr_ctx); 370 device_run(curr_ctx);
362 } 371 }
363} 372}
364 373
365
366/* 374/*
367 * video ioctls 375 * video ioctls
368 */ 376 */
@@ -423,7 +431,7 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
423 431
424static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) 432static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
425{ 433{
426 struct videobuf_queue *vq; 434 struct vb2_queue *vq;
427 struct m2mtest_q_data *q_data; 435 struct m2mtest_q_data *q_data;
428 436
429 vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); 437 vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
@@ -434,7 +442,7 @@ static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
434 442
435 f->fmt.pix.width = q_data->width; 443 f->fmt.pix.width = q_data->width;
436 f->fmt.pix.height = q_data->height; 444 f->fmt.pix.height = q_data->height;
437 f->fmt.pix.field = vq->field; 445 f->fmt.pix.field = V4L2_FIELD_NONE;
438 f->fmt.pix.pixelformat = q_data->fmt->fourcc; 446 f->fmt.pix.pixelformat = q_data->fmt->fourcc;
439 f->fmt.pix.bytesperline = (q_data->width * q_data->fmt->depth) >> 3; 447 f->fmt.pix.bytesperline = (q_data->width * q_data->fmt->depth) >> 3;
440 f->fmt.pix.sizeimage = q_data->sizeimage; 448 f->fmt.pix.sizeimage = q_data->sizeimage;
@@ -523,7 +531,7 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
523static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) 531static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
524{ 532{
525 struct m2mtest_q_data *q_data; 533 struct m2mtest_q_data *q_data;
526 struct videobuf_queue *vq; 534 struct vb2_queue *vq;
527 535
528 vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); 536 vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
529 if (!vq) 537 if (!vq)
@@ -533,7 +541,7 @@ static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
533 if (!q_data) 541 if (!q_data)
534 return -EINVAL; 542 return -EINVAL;
535 543
536 if (videobuf_queue_is_busy(vq)) { 544 if (vb2_is_busy(vq)) {
537 v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__); 545 v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
538 return -EBUSY; 546 return -EBUSY;
539 } 547 }
@@ -543,7 +551,6 @@ static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
543 q_data->height = f->fmt.pix.height; 551 q_data->height = f->fmt.pix.height;
544 q_data->sizeimage = q_data->width * q_data->height 552 q_data->sizeimage = q_data->width * q_data->height
545 * q_data->fmt->depth >> 3; 553 * q_data->fmt->depth >> 3;
546 vq->field = f->fmt.pix.field;
547 554
548 dprintk(ctx->dev, 555 dprintk(ctx->dev,
549 "Setting format for type %d, wxh: %dx%d, fmt: %d\n", 556 "Setting format for type %d, wxh: %dx%d, fmt: %d\n",
@@ -733,120 +740,94 @@ static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = {
733 * Queue operations 740 * Queue operations
734 */ 741 */
735 742
736static void m2mtest_buf_release(struct videobuf_queue *vq, 743static int m2mtest_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
737 struct videobuf_buffer *vb) 744 unsigned int *nplanes, unsigned long sizes[],
738{ 745 void *alloc_ctxs[])
739 struct m2mtest_ctx *ctx = vq->priv_data;
740
741 dprintk(ctx->dev, "type: %d, index: %d, state: %d\n",
742 vq->type, vb->i, vb->state);
743
744 videobuf_vmalloc_free(vb);
745 vb->state = VIDEOBUF_NEEDS_INIT;
746}
747
748static int m2mtest_buf_setup(struct videobuf_queue *vq, unsigned int *count,
749 unsigned int *size)
750{ 746{
751 struct m2mtest_ctx *ctx = vq->priv_data; 747 struct m2mtest_ctx *ctx = vb2_get_drv_priv(vq);
752 struct m2mtest_q_data *q_data; 748 struct m2mtest_q_data *q_data;
749 unsigned int size, count = *nbuffers;
753 750
754 q_data = get_q_data(vq->type); 751 q_data = get_q_data(vq->type);
755 752
756 *size = q_data->width * q_data->height * q_data->fmt->depth >> 3; 753 size = q_data->width * q_data->height * q_data->fmt->depth >> 3;
757 dprintk(ctx->dev, "size:%d, w/h %d/%d, depth: %d\n",
758 *size, q_data->width, q_data->height, q_data->fmt->depth);
759 754
760 if (0 == *count) 755 while (size * count > MEM2MEM_VID_MEM_LIMIT)
761 *count = MEM2MEM_DEF_NUM_BUFS; 756 (count)--;
762 757
763 while (*size * *count > MEM2MEM_VID_MEM_LIMIT) 758 *nplanes = 1;
764 (*count)--; 759 *nbuffers = count;
760 sizes[0] = size;
765 761
766 v4l2_info(&ctx->dev->v4l2_dev, 762 /*
767 "%d buffers of size %d set up.\n", *count, *size); 763 * videobuf2-vmalloc allocator is context-less so no need to set
764 * alloc_ctxs array.
765 */
766
767 dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
768 768
769 return 0; 769 return 0;
770} 770}
771 771
772static int m2mtest_buf_prepare(struct videobuf_queue *vq, 772static int m2mtest_buf_prepare(struct vb2_buffer *vb)
773 struct videobuf_buffer *vb,
774 enum v4l2_field field)
775{ 773{
776 struct m2mtest_ctx *ctx = vq->priv_data; 774 struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
777 struct m2mtest_q_data *q_data; 775 struct m2mtest_q_data *q_data;
778 int ret;
779 776
780 dprintk(ctx->dev, "type: %d, index: %d, state: %d\n", 777 dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
781 vq->type, vb->i, vb->state);
782 778
783 q_data = get_q_data(vq->type); 779 q_data = get_q_data(vb->vb2_queue->type);
784 780
785 if (vb->baddr) { 781 if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
786 /* User-provided buffer */ 782 dprintk(ctx->dev, "%s data will not fit into plane (%lu < %lu)\n",
787 if (vb->bsize < q_data->sizeimage) { 783 __func__, vb2_plane_size(vb, 0), (long)q_data->sizeimage);
788 /* Buffer too small to fit a frame */
789 v4l2_err(&ctx->dev->v4l2_dev,
790 "User-provided buffer too small\n");
791 return -EINVAL;
792 }
793 } else if (vb->state != VIDEOBUF_NEEDS_INIT
794 && vb->bsize < q_data->sizeimage) {
795 /* We provide the buffer, but it's already been initialized
796 * and is too small */
797 return -EINVAL; 784 return -EINVAL;
798 } 785 }
799 786
800 vb->width = q_data->width; 787 vb2_set_plane_payload(vb, 0, q_data->sizeimage);
801 vb->height = q_data->height;
802 vb->bytesperline = (q_data->width * q_data->fmt->depth) >> 3;
803 vb->size = q_data->sizeimage;
804 vb->field = field;
805
806 if (VIDEOBUF_NEEDS_INIT == vb->state) {
807 ret = videobuf_iolock(vq, vb, NULL);
808 if (ret) {
809 v4l2_err(&ctx->dev->v4l2_dev,
810 "Iolock failed\n");
811 goto fail;
812 }
813 }
814
815 vb->state = VIDEOBUF_PREPARED;
816 788
817 return 0; 789 return 0;
818fail:
819 m2mtest_buf_release(vq, vb);
820 return ret;
821} 790}
822 791
823static void m2mtest_buf_queue(struct videobuf_queue *vq, 792static void m2mtest_buf_queue(struct vb2_buffer *vb)
824 struct videobuf_buffer *vb)
825{ 793{
826 struct m2mtest_ctx *ctx = vq->priv_data; 794 struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
827 795 v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
828 v4l2_m2m_buf_queue(ctx->m2m_ctx, vq, vb);
829} 796}
830 797
831static struct videobuf_queue_ops m2mtest_qops = { 798static struct vb2_ops m2mtest_qops = {
832 .buf_setup = m2mtest_buf_setup, 799 .queue_setup = m2mtest_queue_setup,
833 .buf_prepare = m2mtest_buf_prepare, 800 .buf_prepare = m2mtest_buf_prepare,
834 .buf_queue = m2mtest_buf_queue, 801 .buf_queue = m2mtest_buf_queue,
835 .buf_release = m2mtest_buf_release,
836}; 802};
837 803
838static void queue_init(void *priv, struct videobuf_queue *vq, 804static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
839 enum v4l2_buf_type type)
840{ 805{
841 struct m2mtest_ctx *ctx = priv; 806 struct m2mtest_ctx *ctx = priv;
842 struct m2mtest_dev *dev = ctx->dev; 807 int ret;
843 808
844 videobuf_queue_vmalloc_init(vq, &m2mtest_qops, dev->v4l2_dev.dev, 809 memset(src_vq, 0, sizeof(*src_vq));
845 &dev->irqlock, type, V4L2_FIELD_NONE, 810 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
846 sizeof(struct m2mtest_buffer), priv, 811 src_vq->io_modes = VB2_MMAP;
847 &dev->dev_mutex); 812 src_vq->drv_priv = ctx;
848} 813 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
814 src_vq->ops = &m2mtest_qops;
815 src_vq->mem_ops = &vb2_vmalloc_memops;
849 816
817 ret = vb2_queue_init(src_vq);
818 if (ret)
819 return ret;
820
821 memset(dst_vq, 0, sizeof(*dst_vq));
822 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
823 dst_vq->io_modes = VB2_MMAP;
824 dst_vq->drv_priv = ctx;
825 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
826 dst_vq->ops = &m2mtest_qops;
827 dst_vq->mem_ops = &vb2_vmalloc_memops;
828
829 return vb2_queue_init(dst_vq);
830}
850 831
851/* 832/*
852 * File operations 833 * File operations
@@ -866,7 +847,8 @@ static int m2mtest_open(struct file *file)
866 ctx->transtime = MEM2MEM_DEF_TRANSTIME; 847 ctx->transtime = MEM2MEM_DEF_TRANSTIME;
867 ctx->num_processed = 0; 848 ctx->num_processed = 0;
868 849
869 ctx->m2m_ctx = v4l2_m2m_ctx_init(ctx, dev->m2m_dev, queue_init); 850 ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
851
870 if (IS_ERR(ctx->m2m_ctx)) { 852 if (IS_ERR(ctx->m2m_ctx)) {
871 int ret = PTR_ERR(ctx->m2m_ctx); 853 int ret = PTR_ERR(ctx->m2m_ctx);
872 854
@@ -932,6 +914,8 @@ static struct v4l2_m2m_ops m2m_ops = {
932 .device_run = device_run, 914 .device_run = device_run,
933 .job_ready = job_ready, 915 .job_ready = job_ready,
934 .job_abort = job_abort, 916 .job_abort = job_abort,
917 .lock = m2mtest_lock,
918 .unlock = m2mtest_unlock,
935}; 919};
936 920
937static int m2mtest_probe(struct platform_device *pdev) 921static int m2mtest_probe(struct platform_device *pdev)
@@ -990,6 +974,7 @@ static int m2mtest_probe(struct platform_device *pdev)
990 974
991 return 0; 975 return 0;
992 976
977 v4l2_m2m_release(dev->m2m_dev);
993err_m2m: 978err_m2m:
994 video_unregister_device(dev->vfd); 979 video_unregister_device(dev->vfd);
995rel_vdev: 980rel_vdev: