2 * A virtual v4l2-mem2mem example device.
4 * This is a virtual device driver for testing mem-to-mem videobuf framework.
5 * It simulates a device that uses memory buffers for both source and
6 * destination, processes the data and issues an "irq" (simulated by a timer).
7 * The device is capable of multi-instance, multi-buffer-per-transaction
8 * operation (via the mem2mem framework).
10 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
11 * Pawel Osciak, <p.osciak@samsung.com>
12 * Marek Szyprowski, <m.szyprowski@samsung.com>
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version
19 #include <linux/module.h>
20 #include <linux/delay.h>
22 #include <linux/version.h>
23 #include <linux/timer.h>
24 #include <linux/sched.h>
25 #include <linux/slab.h>
27 #include <linux/platform_device.h>
28 #include <media/v4l2-mem2mem.h>
29 #include <media/v4l2-device.h>
30 #include <media/v4l2-ioctl.h>
31 #include <media/videobuf-vmalloc.h>
33 #define MEM2MEM_TEST_MODULE_NAME "mem2mem-testdev"
35 MODULE_DESCRIPTION("Virtual device for mem2mem framework testing");
36 MODULE_AUTHOR("Pawel Osciak, <p.osciak@samsung.com>");
37 MODULE_LICENSE("GPL");
44 #define DIM_ALIGN_MASK 0x08 /* 8-alignment for dimensions */
46 /* Flags that indicate a format can be used for capture/output */
47 #define MEM2MEM_CAPTURE (1 << 0)
48 #define MEM2MEM_OUTPUT (1 << 1)
50 #define MEM2MEM_NAME "m2m-testdev"
53 #define MEM2MEM_DEF_NUM_BUFS VIDEO_MAX_FRAME
54 /* In bytes, per queue */
55 #define MEM2MEM_VID_MEM_LIMIT (16 * 1024 * 1024)
57 /* Default transaction time in msec */
58 #define MEM2MEM_DEF_TRANSTIME 1000
59 /* Default number of buffers per transaction */
60 #define MEM2MEM_DEF_TRANSLEN 1
61 #define MEM2MEM_COLOR_STEP (0xff >> 4)
62 #define MEM2MEM_NUM_TILES 8
64 #define dprintk(dev, fmt, arg...) \
65 v4l2_dbg(1, 1, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
68 void m2mtest_dev_release(struct device
*dev
)
71 static struct platform_device m2mtest_pdev
= {
73 .dev
.release
= m2mtest_dev_release
,
80 /* Types the format can be used for */
84 static struct m2mtest_fmt formats
[] = {
86 .name
= "RGB565 (BE)",
87 .fourcc
= V4L2_PIX_FMT_RGB565X
, /* rrrrrggg gggbbbbb */
89 /* Both capture and output format */
90 .types
= MEM2MEM_CAPTURE
| MEM2MEM_OUTPUT
,
93 .name
= "4:2:2, packed, YUYV",
94 .fourcc
= V4L2_PIX_FMT_YUYV
,
96 /* Output-only format */
97 .types
= MEM2MEM_OUTPUT
,
101 /* Per-queue, driver-specific private data */
102 struct m2mtest_q_data
{
105 unsigned int sizeimage
;
106 struct m2mtest_fmt
*fmt
;
114 /* Source and destination queue data */
115 static struct m2mtest_q_data q_data
[2];
117 static struct m2mtest_q_data
*get_q_data(enum v4l2_buf_type type
)
120 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
121 return &q_data
[V4L2_M2M_SRC
];
122 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
123 return &q_data
[V4L2_M2M_DST
];
130 #define V4L2_CID_TRANS_TIME_MSEC V4L2_CID_PRIVATE_BASE
131 #define V4L2_CID_TRANS_NUM_BUFS (V4L2_CID_PRIVATE_BASE + 1)
133 static struct v4l2_queryctrl m2mtest_ctrls
[] = {
135 .id
= V4L2_CID_TRANS_TIME_MSEC
,
136 .type
= V4L2_CTRL_TYPE_INTEGER
,
137 .name
= "Transaction time (msec)",
141 .default_value
= 1000,
144 .id
= V4L2_CID_TRANS_NUM_BUFS
,
145 .type
= V4L2_CTRL_TYPE_INTEGER
,
146 .name
= "Buffers per transaction",
148 .maximum
= MEM2MEM_DEF_NUM_BUFS
,
155 #define NUM_FORMATS ARRAY_SIZE(formats)
157 static struct m2mtest_fmt
*find_format(struct v4l2_format
*f
)
159 struct m2mtest_fmt
*fmt
;
162 for (k
= 0; k
< NUM_FORMATS
; k
++) {
164 if (fmt
->fourcc
== f
->fmt
.pix
.pixelformat
)
168 if (k
== NUM_FORMATS
)
175 struct v4l2_device v4l2_dev
;
176 struct video_device
*vfd
;
179 struct mutex dev_mutex
;
182 struct timer_list timer
;
184 struct v4l2_m2m_dev
*m2m_dev
;
188 struct m2mtest_dev
*dev
;
190 /* Processed buffers in this transaction */
193 /* Transaction length (i.e. how many buffers per transaction) */
195 /* Transaction time (i.e. simulated processing time) in milliseconds */
198 /* Abort requested by m2m */
201 struct v4l2_m2m_ctx
*m2m_ctx
;
204 struct m2mtest_buffer
{
205 /* vb must be first! */
206 struct videobuf_buffer vb
;
209 static struct v4l2_queryctrl
*get_ctrl(int id
)
213 for (i
= 0; i
< ARRAY_SIZE(m2mtest_ctrls
); ++i
) {
214 if (id
== m2mtest_ctrls
[i
].id
)
215 return &m2mtest_ctrls
[i
];
221 static int device_process(struct m2mtest_ctx
*ctx
,
222 struct m2mtest_buffer
*in_buf
,
223 struct m2mtest_buffer
*out_buf
)
225 struct m2mtest_dev
*dev
= ctx
->dev
;
228 int tile_w
, bytes_left
;
229 struct videobuf_queue
*src_q
;
230 struct videobuf_queue
*dst_q
;
232 src_q
= v4l2_m2m_get_src_vq(ctx
->m2m_ctx
);
233 dst_q
= v4l2_m2m_get_dst_vq(ctx
->m2m_ctx
);
234 p_in
= videobuf_queue_to_vaddr(src_q
, &in_buf
->vb
);
235 p_out
= videobuf_queue_to_vaddr(dst_q
, &out_buf
->vb
);
236 if (!p_in
|| !p_out
) {
237 v4l2_err(&dev
->v4l2_dev
,
238 "Acquiring kernel pointers to buffers failed\n");
242 if (in_buf
->vb
.size
> out_buf
->vb
.size
) {
243 v4l2_err(&dev
->v4l2_dev
, "Output buffer is too small\n");
247 tile_w
= (in_buf
->vb
.width
* (q_data
[V4L2_M2M_DST
].fmt
->depth
>> 3))
249 bytes_left
= in_buf
->vb
.bytesperline
- tile_w
* MEM2MEM_NUM_TILES
;
252 for (y
= 0; y
< in_buf
->vb
.height
; ++y
) {
253 for (t
= 0; t
< MEM2MEM_NUM_TILES
; ++t
) {
255 for (x
= 0; x
< tile_w
; ++x
)
256 *p_out
++ = *p_in
++ + MEM2MEM_COLOR_STEP
;
258 for (x
= 0; x
< tile_w
; ++x
)
259 *p_out
++ = *p_in
++ - MEM2MEM_COLOR_STEP
;
270 static void schedule_irq(struct m2mtest_dev
*dev
, int msec_timeout
)
272 dprintk(dev
, "Scheduling a simulated irq\n");
273 mod_timer(&dev
->timer
, jiffies
+ msecs_to_jiffies(msec_timeout
));
281 * job_ready() - check whether an instance is ready to be scheduled to run
283 static int job_ready(void *priv
)
285 struct m2mtest_ctx
*ctx
= priv
;
287 if (v4l2_m2m_num_src_bufs_ready(ctx
->m2m_ctx
) < ctx
->translen
288 || v4l2_m2m_num_dst_bufs_ready(ctx
->m2m_ctx
) < ctx
->translen
) {
289 dprintk(ctx
->dev
, "Not enough buffers available\n");
296 static void job_abort(void *priv
)
298 struct m2mtest_ctx
*ctx
= priv
;
300 /* Will cancel the transaction in the next interrupt handler */
304 /* device_run() - prepares and starts the device
306 * This simulates all the immediate preparations required before starting
307 * a device. This will be called by the framework when it decides to schedule
308 * a particular instance.
310 static void device_run(void *priv
)
312 struct m2mtest_ctx
*ctx
= priv
;
313 struct m2mtest_dev
*dev
= ctx
->dev
;
314 struct m2mtest_buffer
*src_buf
, *dst_buf
;
316 src_buf
= v4l2_m2m_next_src_buf(ctx
->m2m_ctx
);
317 dst_buf
= v4l2_m2m_next_dst_buf(ctx
->m2m_ctx
);
319 device_process(ctx
, src_buf
, dst_buf
);
321 /* Run a timer, which simulates a hardware irq */
322 schedule_irq(dev
, ctx
->transtime
);
326 static void device_isr(unsigned long priv
)
328 struct m2mtest_dev
*m2mtest_dev
= (struct m2mtest_dev
*)priv
;
329 struct m2mtest_ctx
*curr_ctx
;
330 struct m2mtest_buffer
*src_buf
, *dst_buf
;
333 curr_ctx
= v4l2_m2m_get_curr_priv(m2mtest_dev
->m2m_dev
);
335 if (NULL
== curr_ctx
) {
337 "Instance released before the end of transaction\n");
341 src_buf
= v4l2_m2m_src_buf_remove(curr_ctx
->m2m_ctx
);
342 dst_buf
= v4l2_m2m_dst_buf_remove(curr_ctx
->m2m_ctx
);
343 curr_ctx
->num_processed
++;
345 if (curr_ctx
->num_processed
== curr_ctx
->translen
346 || curr_ctx
->aborting
) {
347 dprintk(curr_ctx
->dev
, "Finishing transaction\n");
348 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
);
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
);
369 static int vidioc_querycap(struct file
*file
, void *priv
,
370 struct v4l2_capability
*cap
)
372 strncpy(cap
->driver
, MEM2MEM_NAME
, sizeof(cap
->driver
) - 1);
373 strncpy(cap
->card
, MEM2MEM_NAME
, sizeof(cap
->card
) - 1);
374 cap
->bus_info
[0] = 0;
375 cap
->version
= KERNEL_VERSION(0, 1, 0);
376 cap
->capabilities
= V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_VIDEO_OUTPUT
377 | V4L2_CAP_STREAMING
;
382 static int enum_fmt(struct v4l2_fmtdesc
*f
, u32 type
)
385 struct m2mtest_fmt
*fmt
;
389 for (i
= 0; i
< NUM_FORMATS
; ++i
) {
390 if (formats
[i
].types
& type
) {
391 /* index-th format of type type found ? */
394 /* Correct type but haven't reached our index yet,
395 * just increment per-type index */
400 if (i
< NUM_FORMATS
) {
403 strncpy(f
->description
, fmt
->name
, sizeof(f
->description
) - 1);
404 f
->pixelformat
= fmt
->fourcc
;
408 /* Format not found */
412 static int vidioc_enum_fmt_vid_cap(struct file
*file
, void *priv
,
413 struct v4l2_fmtdesc
*f
)
415 return enum_fmt(f
, MEM2MEM_CAPTURE
);
418 static int vidioc_enum_fmt_vid_out(struct file
*file
, void *priv
,
419 struct v4l2_fmtdesc
*f
)
421 return enum_fmt(f
, MEM2MEM_OUTPUT
);
424 static int vidioc_g_fmt(struct m2mtest_ctx
*ctx
, struct v4l2_format
*f
)
426 struct videobuf_queue
*vq
;
427 struct m2mtest_q_data
*q_data
;
429 vq
= v4l2_m2m_get_vq(ctx
->m2m_ctx
, f
->type
);
433 q_data
= get_q_data(f
->type
);
435 f
->fmt
.pix
.width
= q_data
->width
;
436 f
->fmt
.pix
.height
= q_data
->height
;
437 f
->fmt
.pix
.field
= vq
->field
;
438 f
->fmt
.pix
.pixelformat
= q_data
->fmt
->fourcc
;
439 f
->fmt
.pix
.bytesperline
= (q_data
->width
* q_data
->fmt
->depth
) >> 3;
440 f
->fmt
.pix
.sizeimage
= q_data
->sizeimage
;
445 static int vidioc_g_fmt_vid_out(struct file
*file
, void *priv
,
446 struct v4l2_format
*f
)
448 return vidioc_g_fmt(priv
, f
);
451 static int vidioc_g_fmt_vid_cap(struct file
*file
, void *priv
,
452 struct v4l2_format
*f
)
454 return vidioc_g_fmt(priv
, f
);
457 static int vidioc_try_fmt(struct v4l2_format
*f
, struct m2mtest_fmt
*fmt
)
459 enum v4l2_field field
;
461 field
= f
->fmt
.pix
.field
;
463 if (field
== V4L2_FIELD_ANY
)
464 field
= V4L2_FIELD_NONE
;
465 else if (V4L2_FIELD_NONE
!= field
)
468 /* V4L2 specification suggests the driver corrects the format struct
469 * if any of the dimensions is unsupported */
470 f
->fmt
.pix
.field
= field
;
472 if (f
->fmt
.pix
.height
< MIN_H
)
473 f
->fmt
.pix
.height
= MIN_H
;
474 else if (f
->fmt
.pix
.height
> MAX_H
)
475 f
->fmt
.pix
.height
= MAX_H
;
477 if (f
->fmt
.pix
.width
< MIN_W
)
478 f
->fmt
.pix
.width
= MIN_W
;
479 else if (f
->fmt
.pix
.width
> MAX_W
)
480 f
->fmt
.pix
.width
= MAX_W
;
482 f
->fmt
.pix
.width
&= ~DIM_ALIGN_MASK
;
483 f
->fmt
.pix
.bytesperline
= (f
->fmt
.pix
.width
* fmt
->depth
) >> 3;
484 f
->fmt
.pix
.sizeimage
= f
->fmt
.pix
.height
* f
->fmt
.pix
.bytesperline
;
489 static int vidioc_try_fmt_vid_cap(struct file
*file
, void *priv
,
490 struct v4l2_format
*f
)
492 struct m2mtest_fmt
*fmt
;
493 struct m2mtest_ctx
*ctx
= priv
;
495 fmt
= find_format(f
);
496 if (!fmt
|| !(fmt
->types
& MEM2MEM_CAPTURE
)) {
497 v4l2_err(&ctx
->dev
->v4l2_dev
,
498 "Fourcc format (0x%08x) invalid.\n",
499 f
->fmt
.pix
.pixelformat
);
503 return vidioc_try_fmt(f
, fmt
);
506 static int vidioc_try_fmt_vid_out(struct file
*file
, void *priv
,
507 struct v4l2_format
*f
)
509 struct m2mtest_fmt
*fmt
;
510 struct m2mtest_ctx
*ctx
= priv
;
512 fmt
= find_format(f
);
513 if (!fmt
|| !(fmt
->types
& MEM2MEM_OUTPUT
)) {
514 v4l2_err(&ctx
->dev
->v4l2_dev
,
515 "Fourcc format (0x%08x) invalid.\n",
516 f
->fmt
.pix
.pixelformat
);
520 return vidioc_try_fmt(f
, fmt
);
523 static int vidioc_s_fmt(struct m2mtest_ctx
*ctx
, struct v4l2_format
*f
)
525 struct m2mtest_q_data
*q_data
;
526 struct videobuf_queue
*vq
;
529 vq
= v4l2_m2m_get_vq(ctx
->m2m_ctx
, f
->type
);
533 q_data
= get_q_data(f
->type
);
537 mutex_lock(&vq
->vb_lock
);
539 if (videobuf_queue_is_busy(vq
)) {
540 v4l2_err(&ctx
->dev
->v4l2_dev
, "%s queue busy\n", __func__
);
545 q_data
->fmt
= find_format(f
);
546 q_data
->width
= f
->fmt
.pix
.width
;
547 q_data
->height
= f
->fmt
.pix
.height
;
548 q_data
->sizeimage
= q_data
->width
* q_data
->height
549 * q_data
->fmt
->depth
>> 3;
550 vq
->field
= f
->fmt
.pix
.field
;
553 "Setting format for type %d, wxh: %dx%d, fmt: %d\n",
554 f
->type
, q_data
->width
, q_data
->height
, q_data
->fmt
->fourcc
);
557 mutex_unlock(&vq
->vb_lock
);
561 static int vidioc_s_fmt_vid_cap(struct file
*file
, void *priv
,
562 struct v4l2_format
*f
)
566 ret
= vidioc_try_fmt_vid_cap(file
, priv
, f
);
570 return vidioc_s_fmt(priv
, f
);
573 static int vidioc_s_fmt_vid_out(struct file
*file
, void *priv
,
574 struct v4l2_format
*f
)
578 ret
= vidioc_try_fmt_vid_out(file
, priv
, f
);
582 return vidioc_s_fmt(priv
, f
);
585 static int vidioc_reqbufs(struct file
*file
, void *priv
,
586 struct v4l2_requestbuffers
*reqbufs
)
588 struct m2mtest_ctx
*ctx
= priv
;
590 return v4l2_m2m_reqbufs(file
, ctx
->m2m_ctx
, reqbufs
);
593 static int vidioc_querybuf(struct file
*file
, void *priv
,
594 struct v4l2_buffer
*buf
)
596 struct m2mtest_ctx
*ctx
= priv
;
598 return v4l2_m2m_querybuf(file
, ctx
->m2m_ctx
, buf
);
601 static int vidioc_qbuf(struct file
*file
, void *priv
, struct v4l2_buffer
*buf
)
603 struct m2mtest_ctx
*ctx
= priv
;
605 return v4l2_m2m_qbuf(file
, ctx
->m2m_ctx
, buf
);
608 static int vidioc_dqbuf(struct file
*file
, void *priv
, struct v4l2_buffer
*buf
)
610 struct m2mtest_ctx
*ctx
= priv
;
612 return v4l2_m2m_dqbuf(file
, ctx
->m2m_ctx
, buf
);
615 static int vidioc_streamon(struct file
*file
, void *priv
,
616 enum v4l2_buf_type type
)
618 struct m2mtest_ctx
*ctx
= priv
;
620 return v4l2_m2m_streamon(file
, ctx
->m2m_ctx
, type
);
623 static int vidioc_streamoff(struct file
*file
, void *priv
,
624 enum v4l2_buf_type type
)
626 struct m2mtest_ctx
*ctx
= priv
;
628 return v4l2_m2m_streamoff(file
, ctx
->m2m_ctx
, type
);
631 static int vidioc_queryctrl(struct file
*file
, void *priv
,
632 struct v4l2_queryctrl
*qc
)
634 struct v4l2_queryctrl
*c
;
636 c
= get_ctrl(qc
->id
);
644 static int vidioc_g_ctrl(struct file
*file
, void *priv
,
645 struct v4l2_control
*ctrl
)
647 struct m2mtest_ctx
*ctx
= priv
;
650 case V4L2_CID_TRANS_TIME_MSEC
:
651 ctrl
->value
= ctx
->transtime
;
654 case V4L2_CID_TRANS_NUM_BUFS
:
655 ctrl
->value
= ctx
->translen
;
659 v4l2_err(&ctx
->dev
->v4l2_dev
, "Invalid control\n");
666 static int check_ctrl_val(struct m2mtest_ctx
*ctx
, struct v4l2_control
*ctrl
)
668 struct v4l2_queryctrl
*c
;
670 c
= get_ctrl(ctrl
->id
);
674 if (ctrl
->value
< c
->minimum
|| ctrl
->value
> c
->maximum
) {
675 v4l2_err(&ctx
->dev
->v4l2_dev
, "Value out of range\n");
682 static int vidioc_s_ctrl(struct file
*file
, void *priv
,
683 struct v4l2_control
*ctrl
)
685 struct m2mtest_ctx
*ctx
= priv
;
688 ret
= check_ctrl_val(ctx
, ctrl
);
693 case V4L2_CID_TRANS_TIME_MSEC
:
694 ctx
->transtime
= ctrl
->value
;
697 case V4L2_CID_TRANS_NUM_BUFS
:
698 ctx
->translen
= ctrl
->value
;
702 v4l2_err(&ctx
->dev
->v4l2_dev
, "Invalid control\n");
710 static const struct v4l2_ioctl_ops m2mtest_ioctl_ops
= {
711 .vidioc_querycap
= vidioc_querycap
,
713 .vidioc_enum_fmt_vid_cap
= vidioc_enum_fmt_vid_cap
,
714 .vidioc_g_fmt_vid_cap
= vidioc_g_fmt_vid_cap
,
715 .vidioc_try_fmt_vid_cap
= vidioc_try_fmt_vid_cap
,
716 .vidioc_s_fmt_vid_cap
= vidioc_s_fmt_vid_cap
,
718 .vidioc_enum_fmt_vid_out
= vidioc_enum_fmt_vid_out
,
719 .vidioc_g_fmt_vid_out
= vidioc_g_fmt_vid_out
,
720 .vidioc_try_fmt_vid_out
= vidioc_try_fmt_vid_out
,
721 .vidioc_s_fmt_vid_out
= vidioc_s_fmt_vid_out
,
723 .vidioc_reqbufs
= vidioc_reqbufs
,
724 .vidioc_querybuf
= vidioc_querybuf
,
726 .vidioc_qbuf
= vidioc_qbuf
,
727 .vidioc_dqbuf
= vidioc_dqbuf
,
729 .vidioc_streamon
= vidioc_streamon
,
730 .vidioc_streamoff
= vidioc_streamoff
,
732 .vidioc_queryctrl
= vidioc_queryctrl
,
733 .vidioc_g_ctrl
= vidioc_g_ctrl
,
734 .vidioc_s_ctrl
= vidioc_s_ctrl
,
742 static void m2mtest_buf_release(struct videobuf_queue
*vq
,
743 struct videobuf_buffer
*vb
)
745 struct m2mtest_ctx
*ctx
= vq
->priv_data
;
747 dprintk(ctx
->dev
, "type: %d, index: %d, state: %d\n",
748 vq
->type
, vb
->i
, vb
->state
);
750 videobuf_vmalloc_free(vb
);
751 vb
->state
= VIDEOBUF_NEEDS_INIT
;
754 static int m2mtest_buf_setup(struct videobuf_queue
*vq
, unsigned int *count
,
757 struct m2mtest_ctx
*ctx
= vq
->priv_data
;
758 struct m2mtest_q_data
*q_data
;
760 q_data
= get_q_data(vq
->type
);
762 *size
= q_data
->width
* q_data
->height
* q_data
->fmt
->depth
>> 3;
763 dprintk(ctx
->dev
, "size:%d, w/h %d/%d, depth: %d\n",
764 *size
, q_data
->width
, q_data
->height
, q_data
->fmt
->depth
);
767 *count
= MEM2MEM_DEF_NUM_BUFS
;
769 while (*size
* *count
> MEM2MEM_VID_MEM_LIMIT
)
772 v4l2_info(&ctx
->dev
->v4l2_dev
,
773 "%d buffers of size %d set up.\n", *count
, *size
);
778 static int m2mtest_buf_prepare(struct videobuf_queue
*vq
,
779 struct videobuf_buffer
*vb
,
780 enum v4l2_field field
)
782 struct m2mtest_ctx
*ctx
= vq
->priv_data
;
783 struct m2mtest_q_data
*q_data
;
786 dprintk(ctx
->dev
, "type: %d, index: %d, state: %d\n",
787 vq
->type
, vb
->i
, vb
->state
);
789 q_data
= get_q_data(vq
->type
);
792 /* User-provided buffer */
793 if (vb
->bsize
< q_data
->sizeimage
) {
794 /* Buffer too small to fit a frame */
795 v4l2_err(&ctx
->dev
->v4l2_dev
,
796 "User-provided buffer too small\n");
799 } else if (vb
->state
!= VIDEOBUF_NEEDS_INIT
800 && vb
->bsize
< q_data
->sizeimage
) {
801 /* We provide the buffer, but it's already been initialized
802 * and is too small */
806 vb
->width
= q_data
->width
;
807 vb
->height
= q_data
->height
;
808 vb
->bytesperline
= (q_data
->width
* q_data
->fmt
->depth
) >> 3;
809 vb
->size
= q_data
->sizeimage
;
812 if (VIDEOBUF_NEEDS_INIT
== vb
->state
) {
813 ret
= videobuf_iolock(vq
, vb
, NULL
);
815 v4l2_err(&ctx
->dev
->v4l2_dev
,
821 vb
->state
= VIDEOBUF_PREPARED
;
825 m2mtest_buf_release(vq
, vb
);
829 static void m2mtest_buf_queue(struct videobuf_queue
*vq
,
830 struct videobuf_buffer
*vb
)
832 struct m2mtest_ctx
*ctx
= vq
->priv_data
;
834 v4l2_m2m_buf_queue(ctx
->m2m_ctx
, vq
, vb
);
837 static struct videobuf_queue_ops m2mtest_qops
= {
838 .buf_setup
= m2mtest_buf_setup
,
839 .buf_prepare
= m2mtest_buf_prepare
,
840 .buf_queue
= m2mtest_buf_queue
,
841 .buf_release
= m2mtest_buf_release
,
844 static void queue_init(void *priv
, struct videobuf_queue
*vq
,
845 enum v4l2_buf_type type
)
847 struct m2mtest_ctx
*ctx
= priv
;
849 videobuf_queue_vmalloc_init(vq
, &m2mtest_qops
, ctx
->dev
->v4l2_dev
.dev
,
850 &ctx
->dev
->irqlock
, type
, V4L2_FIELD_NONE
,
851 sizeof(struct m2mtest_buffer
), priv
);
858 static int m2mtest_open(struct file
*file
)
860 struct m2mtest_dev
*dev
= video_drvdata(file
);
861 struct m2mtest_ctx
*ctx
= NULL
;
863 ctx
= kzalloc(sizeof *ctx
, GFP_KERNEL
);
867 file
->private_data
= ctx
;
869 ctx
->translen
= MEM2MEM_DEF_TRANSLEN
;
870 ctx
->transtime
= MEM2MEM_DEF_TRANSTIME
;
871 ctx
->num_processed
= 0;
873 ctx
->m2m_ctx
= v4l2_m2m_ctx_init(ctx
, dev
->m2m_dev
, queue_init
);
874 if (IS_ERR(ctx
->m2m_ctx
)) {
875 int ret
= PTR_ERR(ctx
->m2m_ctx
);
881 atomic_inc(&dev
->num_inst
);
883 dprintk(dev
, "Created instance %p, m2m_ctx: %p\n", ctx
, ctx
->m2m_ctx
);
888 static int m2mtest_release(struct file
*file
)
890 struct m2mtest_dev
*dev
= video_drvdata(file
);
891 struct m2mtest_ctx
*ctx
= file
->private_data
;
893 dprintk(dev
, "Releasing instance %p\n", ctx
);
895 v4l2_m2m_ctx_release(ctx
->m2m_ctx
);
898 atomic_dec(&dev
->num_inst
);
903 static unsigned int m2mtest_poll(struct file
*file
,
904 struct poll_table_struct
*wait
)
906 struct m2mtest_ctx
*ctx
= file
->private_data
;
908 return v4l2_m2m_poll(file
, ctx
->m2m_ctx
, wait
);
911 static int m2mtest_mmap(struct file
*file
, struct vm_area_struct
*vma
)
913 struct m2mtest_ctx
*ctx
= file
->private_data
;
915 return v4l2_m2m_mmap(file
, ctx
->m2m_ctx
, vma
);
918 static const struct v4l2_file_operations m2mtest_fops
= {
919 .owner
= THIS_MODULE
,
920 .open
= m2mtest_open
,
921 .release
= m2mtest_release
,
922 .poll
= m2mtest_poll
,
923 .ioctl
= video_ioctl2
,
924 .mmap
= m2mtest_mmap
,
927 static struct video_device m2mtest_videodev
= {
928 .name
= MEM2MEM_NAME
,
929 .fops
= &m2mtest_fops
,
930 .ioctl_ops
= &m2mtest_ioctl_ops
,
932 .release
= video_device_release
,
935 static struct v4l2_m2m_ops m2m_ops
= {
936 .device_run
= device_run
,
937 .job_ready
= job_ready
,
938 .job_abort
= job_abort
,
941 static int m2mtest_probe(struct platform_device
*pdev
)
943 struct m2mtest_dev
*dev
;
944 struct video_device
*vfd
;
947 dev
= kzalloc(sizeof *dev
, GFP_KERNEL
);
951 spin_lock_init(&dev
->irqlock
);
953 ret
= v4l2_device_register(&pdev
->dev
, &dev
->v4l2_dev
);
957 atomic_set(&dev
->num_inst
, 0);
958 mutex_init(&dev
->dev_mutex
);
960 vfd
= video_device_alloc();
962 v4l2_err(&dev
->v4l2_dev
, "Failed to allocate video device\n");
967 *vfd
= m2mtest_videodev
;
969 ret
= video_register_device(vfd
, VFL_TYPE_GRABBER
, 0);
971 v4l2_err(&dev
->v4l2_dev
, "Failed to register video device\n");
975 video_set_drvdata(vfd
, dev
);
976 snprintf(vfd
->name
, sizeof(vfd
->name
), "%s", m2mtest_videodev
.name
);
978 v4l2_info(&dev
->v4l2_dev
, MEM2MEM_TEST_MODULE_NAME
979 "Device registered as /dev/video%d\n", vfd
->num
);
981 setup_timer(&dev
->timer
, device_isr
, (long)dev
);
982 platform_set_drvdata(pdev
, dev
);
984 dev
->m2m_dev
= v4l2_m2m_init(&m2m_ops
);
985 if (IS_ERR(dev
->m2m_dev
)) {
986 v4l2_err(&dev
->v4l2_dev
, "Failed to init mem2mem device\n");
987 ret
= PTR_ERR(dev
->m2m_dev
);
991 q_data
[V4L2_M2M_SRC
].fmt
= &formats
[0];
992 q_data
[V4L2_M2M_DST
].fmt
= &formats
[0];
997 video_unregister_device(dev
->vfd
);
999 video_device_release(vfd
);
1001 v4l2_device_unregister(&dev
->v4l2_dev
);
1008 static int m2mtest_remove(struct platform_device
*pdev
)
1010 struct m2mtest_dev
*dev
=
1011 (struct m2mtest_dev
*)platform_get_drvdata(pdev
);
1013 v4l2_info(&dev
->v4l2_dev
, "Removing " MEM2MEM_TEST_MODULE_NAME
);
1014 v4l2_m2m_release(dev
->m2m_dev
);
1015 del_timer_sync(&dev
->timer
);
1016 video_unregister_device(dev
->vfd
);
1017 video_device_release(dev
->vfd
);
1018 v4l2_device_unregister(&dev
->v4l2_dev
);
1024 static struct platform_driver m2mtest_pdrv
= {
1025 .probe
= m2mtest_probe
,
1026 .remove
= m2mtest_remove
,
1028 .name
= MEM2MEM_NAME
,
1029 .owner
= THIS_MODULE
,
1033 static void __exit
m2mtest_exit(void)
1035 platform_driver_unregister(&m2mtest_pdrv
);
1036 platform_device_unregister(&m2mtest_pdev
);
1039 static int __init
m2mtest_init(void)
1043 ret
= platform_device_register(&m2mtest_pdev
);
1047 ret
= platform_driver_register(&m2mtest_pdrv
);
1049 platform_device_unregister(&m2mtest_pdev
);
1054 module_init(m2mtest_init
);
1055 module_exit(m2mtest_exit
);