1 // SPDX-License-Identifier: GPL-2.0+
3 * A virtual v4l2-mem2mem example device.
5 * This is a virtual device driver for testing mem-to-mem vb2 framework.
6 * It simulates a device that uses memory buffers for both source and
7 * destination, processes the data and issues an "irq" (simulated by a delayed
9 * The device is capable of multi-instance, multi-buffer-per-transaction
10 * operation (via the mem2mem framework).
12 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
13 * Pawel Osciak, <pawel@osciak.com>
14 * Marek Szyprowski, <m.szyprowski@samsung.com>
16 #include <linux/module.h>
17 #include <linux/delay.h>
19 #include <linux/sched.h>
20 #include <linux/slab.h>
22 #include <linux/platform_device.h>
23 #include <media/v4l2-mem2mem.h>
24 #include <media/v4l2-device.h>
25 #include <media/v4l2-ioctl.h>
26 #include <media/v4l2-ctrls.h>
27 #include <media/v4l2-event.h>
28 #include <media/videobuf2-vmalloc.h>
30 MODULE_DESCRIPTION("Virtual device for mem2mem framework testing");
31 MODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
32 MODULE_LICENSE("GPL");
33 MODULE_VERSION("0.2");
34 MODULE_ALIAS("mem2mem_testdev");
36 static unsigned int debug
;
37 module_param(debug
, uint
, 0644);
38 MODULE_PARM_DESC(debug
, "debug level");
40 /* Default transaction time in msec */
41 static unsigned int default_transtime
= 40; /* Max 25 fps */
42 module_param(default_transtime
, uint
, 0644);
43 MODULE_PARM_DESC(default_transtime
, "default transaction time in ms");
50 /* Pixel alignment for non-bayer formats */
52 #define HEIGHT_ALIGN 1
54 /* Pixel alignment for bayer formats */
55 #define BAYER_WIDTH_ALIGN 2
56 #define BAYER_HEIGHT_ALIGN 2
58 /* Flags that indicate a format can be used for capture/output */
59 #define MEM2MEM_CAPTURE BIT(0)
60 #define MEM2MEM_OUTPUT BIT(1)
62 #define MEM2MEM_NAME "vim2m"
65 #define MEM2MEM_DEF_NUM_BUFS VIDEO_MAX_FRAME
66 /* In bytes, per queue */
67 #define MEM2MEM_VID_MEM_LIMIT (16 * 1024 * 1024)
69 /* Flags that indicate processing mode */
70 #define MEM2MEM_HFLIP BIT(0)
71 #define MEM2MEM_VFLIP BIT(1)
73 #define dprintk(dev, lvl, fmt, arg...) \
74 v4l2_dbg(lvl, debug, &(dev)->v4l2_dev, "%s: " fmt, __func__, ## arg)
76 static void vim2m_dev_release(struct device
*dev
)
79 static struct platform_device vim2m_pdev
= {
81 .dev
.release
= vim2m_dev_release
,
87 /* Types the format can be used for */
91 static struct vim2m_fmt formats
[] = {
93 .fourcc
= V4L2_PIX_FMT_RGB565
, /* rrrrrggg gggbbbbb */
95 .types
= MEM2MEM_CAPTURE
| MEM2MEM_OUTPUT
,
97 .fourcc
= V4L2_PIX_FMT_RGB565X
, /* gggbbbbb rrrrrggg */
99 .types
= MEM2MEM_CAPTURE
| MEM2MEM_OUTPUT
,
101 .fourcc
= V4L2_PIX_FMT_RGB24
,
103 .types
= MEM2MEM_CAPTURE
| MEM2MEM_OUTPUT
,
105 .fourcc
= V4L2_PIX_FMT_BGR24
,
107 .types
= MEM2MEM_CAPTURE
| MEM2MEM_OUTPUT
,
109 .fourcc
= V4L2_PIX_FMT_YUYV
,
111 .types
= MEM2MEM_CAPTURE
,
113 .fourcc
= V4L2_PIX_FMT_SBGGR8
,
115 .types
= MEM2MEM_CAPTURE
,
117 .fourcc
= V4L2_PIX_FMT_SGBRG8
,
119 .types
= MEM2MEM_CAPTURE
,
121 .fourcc
= V4L2_PIX_FMT_SGRBG8
,
123 .types
= MEM2MEM_CAPTURE
,
125 .fourcc
= V4L2_PIX_FMT_SRGGB8
,
127 .types
= MEM2MEM_CAPTURE
,
131 #define NUM_FORMATS ARRAY_SIZE(formats)
133 /* Per-queue, driver-specific private data */
134 struct vim2m_q_data
{
137 unsigned int sizeimage
;
138 unsigned int sequence
;
139 struct vim2m_fmt
*fmt
;
147 #define V4L2_CID_TRANS_TIME_MSEC (V4L2_CID_USER_BASE + 0x1000)
148 #define V4L2_CID_TRANS_NUM_BUFS (V4L2_CID_USER_BASE + 0x1001)
150 static struct vim2m_fmt
*find_format(u32 fourcc
)
152 struct vim2m_fmt
*fmt
;
155 for (k
= 0; k
< NUM_FORMATS
; k
++) {
157 if (fmt
->fourcc
== fourcc
)
161 if (k
== NUM_FORMATS
)
167 static void get_alignment(u32 fourcc
,
168 unsigned int *walign
, unsigned int *halign
)
171 case V4L2_PIX_FMT_SBGGR8
:
172 case V4L2_PIX_FMT_SGBRG8
:
173 case V4L2_PIX_FMT_SGRBG8
:
174 case V4L2_PIX_FMT_SRGGB8
:
175 *walign
= BAYER_WIDTH_ALIGN
;
176 *halign
= BAYER_HEIGHT_ALIGN
;
179 *walign
= WIDTH_ALIGN
;
180 *halign
= HEIGHT_ALIGN
;
186 struct v4l2_device v4l2_dev
;
187 struct video_device vfd
;
188 #ifdef CONFIG_MEDIA_CONTROLLER
189 struct media_device mdev
;
193 struct mutex dev_mutex
;
195 struct v4l2_m2m_dev
*m2m_dev
;
200 struct vim2m_dev
*dev
;
202 struct v4l2_ctrl_handler hdl
;
204 /* Processed buffers in this transaction */
207 /* Transaction length (i.e. how many buffers per transaction) */
209 /* Transaction time (i.e. simulated processing time) in milliseconds */
212 struct mutex vb_mutex
;
213 struct delayed_work work_run
;
215 /* Abort requested by m2m */
218 /* Processing mode */
221 enum v4l2_colorspace colorspace
;
222 enum v4l2_ycbcr_encoding ycbcr_enc
;
223 enum v4l2_xfer_func xfer_func
;
224 enum v4l2_quantization quant
;
226 /* Source and destination queue data */
227 struct vim2m_q_data q_data
[2];
230 static inline struct vim2m_ctx
*file2ctx(struct file
*file
)
232 return container_of(file
->private_data
, struct vim2m_ctx
, fh
);
235 static struct vim2m_q_data
*get_q_data(struct vim2m_ctx
*ctx
,
236 enum v4l2_buf_type type
)
239 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
240 return &ctx
->q_data
[V4L2_M2M_SRC
];
241 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
242 return &ctx
->q_data
[V4L2_M2M_DST
];
248 static const char *type_name(enum v4l2_buf_type type
)
251 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
253 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
260 #define CLIP(__color) \
261 (u8)(((__color) > 0xff) ? 0xff : (((__color) < 0) ? 0 : (__color)))
263 static void copy_line(struct vim2m_q_data
*q_data_out
,
264 u8
*src
, u8
*dst
, bool reverse
)
266 int x
, depth
= q_data_out
->fmt
->depth
>> 3;
269 memcpy(dst
, src
, q_data_out
->width
* depth
);
271 for (x
= 0; x
< q_data_out
->width
>> 1; x
++) {
272 memcpy(dst
, src
, depth
);
273 memcpy(dst
+ depth
, src
- depth
, depth
);
281 static void copy_two_pixels(struct vim2m_q_data
*q_data_in
,
282 struct vim2m_q_data
*q_data_out
,
283 u8
*src
[2], u8
**dst
, int ypos
, bool reverse
)
285 struct vim2m_fmt
*out
= q_data_out
->fmt
;
286 struct vim2m_fmt
*in
= q_data_in
->fmt
;
287 u8 _r
[2], _g
[2], _b
[2], *r
, *g
, *b
;
290 /* Step 1: read two consecutive pixels from src pointer */
296 switch (in
->fourcc
) {
297 case V4L2_PIX_FMT_RGB565
: /* rrrrrggg gggbbbbb */
298 for (i
= 0; i
< 2; i
++) {
299 u16 pix
= le16_to_cpu(*(__le16
*)(src
[i
]));
301 *r
++ = (u8
)(((pix
& 0xf800) >> 11) << 3) | 0x07;
302 *g
++ = (u8
)((((pix
& 0x07e0) >> 5)) << 2) | 0x03;
303 *b
++ = (u8
)((pix
& 0x1f) << 3) | 0x07;
306 case V4L2_PIX_FMT_RGB565X
: /* gggbbbbb rrrrrggg */
307 for (i
= 0; i
< 2; i
++) {
308 u16 pix
= be16_to_cpu(*(__be16
*)(src
[i
]));
310 *r
++ = (u8
)(((pix
& 0xf800) >> 11) << 3) | 0x07;
311 *g
++ = (u8
)((((pix
& 0x07e0) >> 5)) << 2) | 0x03;
312 *b
++ = (u8
)((pix
& 0x1f) << 3) | 0x07;
316 case V4L2_PIX_FMT_RGB24
:
317 for (i
= 0; i
< 2; i
++) {
323 case V4L2_PIX_FMT_BGR24
:
324 for (i
= 0; i
< 2; i
++) {
332 /* Step 2: store two consecutive points, reversing them if needed */
338 switch (out
->fourcc
) {
339 case V4L2_PIX_FMT_RGB565
: /* rrrrrggg gggbbbbb */
340 for (i
= 0; i
< 2; i
++) {
342 __le16
*dst_pix
= (__le16
*)*dst
;
344 pix
= ((*r
<< 8) & 0xf800) | ((*g
<< 3) & 0x07e0) |
347 *dst_pix
= cpu_to_le16(pix
);
352 case V4L2_PIX_FMT_RGB565X
: /* gggbbbbb rrrrrggg */
353 for (i
= 0; i
< 2; i
++) {
355 __be16
*dst_pix
= (__be16
*)*dst
;
357 pix
= ((*r
<< 8) & 0xf800) | ((*g
<< 3) & 0x07e0) |
360 *dst_pix
= cpu_to_be16(pix
);
365 case V4L2_PIX_FMT_RGB24
:
366 for (i
= 0; i
< 2; i
++) {
372 case V4L2_PIX_FMT_BGR24
:
373 for (i
= 0; i
< 2; i
++) {
379 case V4L2_PIX_FMT_YUYV
:
384 y
= ((8453 * (*r
) + 16594 * (*g
) + 3223 * (*b
)
386 u
= ((-4878 * (*r
) - 9578 * (*g
) + 14456 * (*b
)
388 v
= ((14456 * (*r
++) - 12105 * (*g
++) - 2351 * (*b
++)
390 y1
= ((8453 * (*r
) + 16594 * (*g
) + 3223 * (*b
)
400 case V4L2_PIX_FMT_SBGGR8
:
409 case V4L2_PIX_FMT_SGBRG8
:
418 case V4L2_PIX_FMT_SGRBG8
:
427 case V4L2_PIX_FMT_SRGGB8
:
439 static int device_process(struct vim2m_ctx
*ctx
,
440 struct vb2_v4l2_buffer
*in_vb
,
441 struct vb2_v4l2_buffer
*out_vb
)
443 struct vim2m_dev
*dev
= ctx
->dev
;
444 struct vim2m_q_data
*q_data_in
, *q_data_out
;
445 u8
*p_in
, *p_line
, *p_in_x
[2], *p
, *p_out
;
446 unsigned int width
, height
, bytesperline
, bytes_per_pixel
;
447 unsigned int x
, y
, y_in
, y_out
, x_int
, x_fract
, x_err
, x_offset
;
448 int start
, end
, step
;
450 q_data_in
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_OUTPUT
);
453 bytesperline
= (q_data_in
->width
* q_data_in
->fmt
->depth
) >> 3;
454 bytes_per_pixel
= q_data_in
->fmt
->depth
>> 3;
456 q_data_out
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_CAPTURE
);
460 /* As we're doing scaling, use the output dimensions here */
461 height
= q_data_out
->height
;
462 width
= q_data_out
->width
;
464 p_in
= vb2_plane_vaddr(&in_vb
->vb2_buf
, 0);
465 p_out
= vb2_plane_vaddr(&out_vb
->vb2_buf
, 0);
466 if (!p_in
|| !p_out
) {
467 v4l2_err(&dev
->v4l2_dev
,
468 "Acquiring kernel pointers to buffers failed\n");
472 out_vb
->sequence
= q_data_out
->sequence
++;
473 in_vb
->sequence
= q_data_in
->sequence
++;
474 v4l2_m2m_buf_copy_metadata(in_vb
, out_vb
, true);
476 if (ctx
->mode
& MEM2MEM_VFLIP
) {
488 * When format and resolution are identical,
489 * we can use a faster copy logic
491 if (q_data_in
->fmt
->fourcc
== q_data_out
->fmt
->fourcc
&&
492 q_data_in
->width
== q_data_out
->width
&&
493 q_data_in
->height
== q_data_out
->height
) {
494 for (y
= start
; y
!= end
; y
+= step
, y_out
++) {
495 p
= p_in
+ (y
* bytesperline
);
496 if (ctx
->mode
& MEM2MEM_HFLIP
)
497 p
+= bytesperline
- (q_data_in
->fmt
->depth
>> 3);
499 copy_line(q_data_out
, p
, p_out
,
500 ctx
->mode
& MEM2MEM_HFLIP
);
502 p_out
+= bytesperline
;
507 /* Slower algorithm with format conversion, hflip, vflip and scaler */
509 /* To speed scaler up, use Bresenham for X dimension */
510 x_int
= q_data_in
->width
/ q_data_out
->width
;
511 x_fract
= q_data_in
->width
% q_data_out
->width
;
513 for (y
= start
; y
!= end
; y
+= step
, y_out
++) {
514 y_in
= (y
* q_data_in
->height
) / q_data_out
->height
;
518 p_line
= p_in
+ (y_in
* bytesperline
);
519 if (ctx
->mode
& MEM2MEM_HFLIP
)
520 p_line
+= bytesperline
- (q_data_in
->fmt
->depth
>> 3);
523 for (x
= 0; x
< width
>> 1; x
++) {
531 if (ctx
->mode
& MEM2MEM_HFLIP
)
532 p_in_x
[1] = p_line
- x_offset
* bytes_per_pixel
;
534 p_in_x
[1] = p_line
+ x_offset
* bytes_per_pixel
;
536 copy_two_pixels(q_data_in
, q_data_out
,
537 p_in_x
, &p_out
, y_out
,
538 ctx
->mode
& MEM2MEM_HFLIP
);
540 /* Calculate the next p_in_x0 */
548 if (ctx
->mode
& MEM2MEM_HFLIP
)
549 p_in_x
[0] = p_line
- x_offset
* bytes_per_pixel
;
551 p_in_x
[0] = p_line
+ x_offset
* bytes_per_pixel
;
563 * job_ready() - check whether an instance is ready to be scheduled to run
565 static int job_ready(void *priv
)
567 struct vim2m_ctx
*ctx
= priv
;
569 if (v4l2_m2m_num_src_bufs_ready(ctx
->fh
.m2m_ctx
) < ctx
->translen
570 || v4l2_m2m_num_dst_bufs_ready(ctx
->fh
.m2m_ctx
) < ctx
->translen
) {
571 dprintk(ctx
->dev
, 1, "Not enough buffers available\n");
578 static void job_abort(void *priv
)
580 struct vim2m_ctx
*ctx
= priv
;
582 /* Will cancel the transaction in the next interrupt handler */
586 /* device_run() - prepares and starts the device
588 * This simulates all the immediate preparations required before starting
589 * a device. This will be called by the framework when it decides to schedule
590 * a particular instance.
592 static void device_run(void *priv
)
594 struct vim2m_ctx
*ctx
= priv
;
595 struct vb2_v4l2_buffer
*src_buf
, *dst_buf
;
597 src_buf
= v4l2_m2m_next_src_buf(ctx
->fh
.m2m_ctx
);
598 dst_buf
= v4l2_m2m_next_dst_buf(ctx
->fh
.m2m_ctx
);
600 /* Apply request controls if any */
601 v4l2_ctrl_request_setup(src_buf
->vb2_buf
.req_obj
.req
,
604 device_process(ctx
, src_buf
, dst_buf
);
606 /* Complete request controls if any */
607 v4l2_ctrl_request_complete(src_buf
->vb2_buf
.req_obj
.req
,
610 /* Run delayed work, which simulates a hardware irq */
611 schedule_delayed_work(&ctx
->work_run
, msecs_to_jiffies(ctx
->transtime
));
614 static void device_work(struct work_struct
*w
)
616 struct vim2m_ctx
*curr_ctx
;
617 struct vim2m_dev
*vim2m_dev
;
618 struct vb2_v4l2_buffer
*src_vb
, *dst_vb
;
620 curr_ctx
= container_of(w
, struct vim2m_ctx
, work_run
.work
);
622 vim2m_dev
= curr_ctx
->dev
;
624 src_vb
= v4l2_m2m_src_buf_remove(curr_ctx
->fh
.m2m_ctx
);
625 dst_vb
= v4l2_m2m_dst_buf_remove(curr_ctx
->fh
.m2m_ctx
);
627 curr_ctx
->num_processed
++;
629 v4l2_m2m_buf_done(src_vb
, VB2_BUF_STATE_DONE
);
630 v4l2_m2m_buf_done(dst_vb
, VB2_BUF_STATE_DONE
);
632 if (curr_ctx
->num_processed
== curr_ctx
->translen
633 || curr_ctx
->aborting
) {
634 dprintk(curr_ctx
->dev
, 2, "Finishing capture buffer fill\n");
635 curr_ctx
->num_processed
= 0;
636 v4l2_m2m_job_finish(vim2m_dev
->m2m_dev
, curr_ctx
->fh
.m2m_ctx
);
638 device_run(curr_ctx
);
645 static int vidioc_querycap(struct file
*file
, void *priv
,
646 struct v4l2_capability
*cap
)
648 strscpy(cap
->driver
, MEM2MEM_NAME
, sizeof(cap
->driver
));
649 strscpy(cap
->card
, MEM2MEM_NAME
, sizeof(cap
->card
));
650 snprintf(cap
->bus_info
, sizeof(cap
->bus_info
),
651 "platform:%s", MEM2MEM_NAME
);
655 static int enum_fmt(struct v4l2_fmtdesc
*f
, u32 type
)
658 struct vim2m_fmt
*fmt
;
662 for (i
= 0; i
< NUM_FORMATS
; ++i
) {
663 if (formats
[i
].types
& type
) {
664 /* index-th format of type type found ? */
668 * Correct type but haven't reached our index yet,
669 * just increment per-type index
675 if (i
< NUM_FORMATS
) {
678 f
->pixelformat
= fmt
->fourcc
;
682 /* Format not found */
686 static int vidioc_enum_fmt_vid_cap(struct file
*file
, void *priv
,
687 struct v4l2_fmtdesc
*f
)
689 return enum_fmt(f
, MEM2MEM_CAPTURE
);
692 static int vidioc_enum_fmt_vid_out(struct file
*file
, void *priv
,
693 struct v4l2_fmtdesc
*f
)
695 return enum_fmt(f
, MEM2MEM_OUTPUT
);
698 static int vidioc_enum_framesizes(struct file
*file
, void *priv
,
699 struct v4l2_frmsizeenum
*fsize
)
701 if (fsize
->index
!= 0)
704 if (!find_format(fsize
->pixel_format
))
707 fsize
->type
= V4L2_FRMSIZE_TYPE_STEPWISE
;
708 fsize
->stepwise
.min_width
= MIN_W
;
709 fsize
->stepwise
.min_height
= MIN_H
;
710 fsize
->stepwise
.max_width
= MAX_W
;
711 fsize
->stepwise
.max_height
= MAX_H
;
713 get_alignment(fsize
->pixel_format
,
714 &fsize
->stepwise
.step_width
,
715 &fsize
->stepwise
.step_height
);
719 static int vidioc_g_fmt(struct vim2m_ctx
*ctx
, struct v4l2_format
*f
)
721 struct vb2_queue
*vq
;
722 struct vim2m_q_data
*q_data
;
724 vq
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
, f
->type
);
728 q_data
= get_q_data(ctx
, f
->type
);
732 f
->fmt
.pix
.width
= q_data
->width
;
733 f
->fmt
.pix
.height
= q_data
->height
;
734 f
->fmt
.pix
.field
= V4L2_FIELD_NONE
;
735 f
->fmt
.pix
.pixelformat
= q_data
->fmt
->fourcc
;
736 f
->fmt
.pix
.bytesperline
= (q_data
->width
* q_data
->fmt
->depth
) >> 3;
737 f
->fmt
.pix
.sizeimage
= q_data
->sizeimage
;
738 f
->fmt
.pix
.colorspace
= ctx
->colorspace
;
739 f
->fmt
.pix
.xfer_func
= ctx
->xfer_func
;
740 f
->fmt
.pix
.ycbcr_enc
= ctx
->ycbcr_enc
;
741 f
->fmt
.pix
.quantization
= ctx
->quant
;
746 static int vidioc_g_fmt_vid_out(struct file
*file
, void *priv
,
747 struct v4l2_format
*f
)
749 return vidioc_g_fmt(file2ctx(file
), f
);
752 static int vidioc_g_fmt_vid_cap(struct file
*file
, void *priv
,
753 struct v4l2_format
*f
)
755 return vidioc_g_fmt(file2ctx(file
), f
);
758 static int vidioc_try_fmt(struct v4l2_format
*f
, struct vim2m_fmt
*fmt
)
762 * V4L2 specification specifies the driver corrects the
763 * format struct if any of the dimensions is unsupported
765 if (f
->fmt
.pix
.height
< MIN_H
)
766 f
->fmt
.pix
.height
= MIN_H
;
767 else if (f
->fmt
.pix
.height
> MAX_H
)
768 f
->fmt
.pix
.height
= MAX_H
;
770 if (f
->fmt
.pix
.width
< MIN_W
)
771 f
->fmt
.pix
.width
= MIN_W
;
772 else if (f
->fmt
.pix
.width
> MAX_W
)
773 f
->fmt
.pix
.width
= MAX_W
;
775 get_alignment(f
->fmt
.pix
.pixelformat
, &walign
, &halign
);
776 f
->fmt
.pix
.width
&= ~(walign
- 1);
777 f
->fmt
.pix
.height
&= ~(halign
- 1);
778 f
->fmt
.pix
.bytesperline
= (f
->fmt
.pix
.width
* fmt
->depth
) >> 3;
779 f
->fmt
.pix
.sizeimage
= f
->fmt
.pix
.height
* f
->fmt
.pix
.bytesperline
;
780 f
->fmt
.pix
.field
= V4L2_FIELD_NONE
;
785 static int vidioc_try_fmt_vid_cap(struct file
*file
, void *priv
,
786 struct v4l2_format
*f
)
788 struct vim2m_fmt
*fmt
;
789 struct vim2m_ctx
*ctx
= file2ctx(file
);
791 fmt
= find_format(f
->fmt
.pix
.pixelformat
);
793 f
->fmt
.pix
.pixelformat
= formats
[0].fourcc
;
794 fmt
= find_format(f
->fmt
.pix
.pixelformat
);
796 if (!(fmt
->types
& MEM2MEM_CAPTURE
)) {
797 v4l2_err(&ctx
->dev
->v4l2_dev
,
798 "Fourcc format (0x%08x) invalid.\n",
799 f
->fmt
.pix
.pixelformat
);
802 f
->fmt
.pix
.colorspace
= ctx
->colorspace
;
803 f
->fmt
.pix
.xfer_func
= ctx
->xfer_func
;
804 f
->fmt
.pix
.ycbcr_enc
= ctx
->ycbcr_enc
;
805 f
->fmt
.pix
.quantization
= ctx
->quant
;
807 return vidioc_try_fmt(f
, fmt
);
810 static int vidioc_try_fmt_vid_out(struct file
*file
, void *priv
,
811 struct v4l2_format
*f
)
813 struct vim2m_fmt
*fmt
;
814 struct vim2m_ctx
*ctx
= file2ctx(file
);
816 fmt
= find_format(f
->fmt
.pix
.pixelformat
);
818 f
->fmt
.pix
.pixelformat
= formats
[0].fourcc
;
819 fmt
= find_format(f
->fmt
.pix
.pixelformat
);
821 if (!(fmt
->types
& MEM2MEM_OUTPUT
)) {
822 v4l2_err(&ctx
->dev
->v4l2_dev
,
823 "Fourcc format (0x%08x) invalid.\n",
824 f
->fmt
.pix
.pixelformat
);
827 if (!f
->fmt
.pix
.colorspace
)
828 f
->fmt
.pix
.colorspace
= V4L2_COLORSPACE_REC709
;
830 return vidioc_try_fmt(f
, fmt
);
833 static int vidioc_s_fmt(struct vim2m_ctx
*ctx
, struct v4l2_format
*f
)
835 struct vim2m_q_data
*q_data
;
836 struct vb2_queue
*vq
;
838 vq
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
, f
->type
);
842 q_data
= get_q_data(ctx
, f
->type
);
846 if (vb2_is_busy(vq
)) {
847 v4l2_err(&ctx
->dev
->v4l2_dev
, "%s queue busy\n", __func__
);
851 q_data
->fmt
= find_format(f
->fmt
.pix
.pixelformat
);
852 q_data
->width
= f
->fmt
.pix
.width
;
853 q_data
->height
= f
->fmt
.pix
.height
;
854 q_data
->sizeimage
= q_data
->width
* q_data
->height
855 * q_data
->fmt
->depth
>> 3;
858 "Format for type %s: %dx%d (%d bpp), fmt: %c%c%c%c\n",
859 type_name(f
->type
), q_data
->width
, q_data
->height
,
861 (q_data
->fmt
->fourcc
& 0xff),
862 (q_data
->fmt
->fourcc
>> 8) & 0xff,
863 (q_data
->fmt
->fourcc
>> 16) & 0xff,
864 (q_data
->fmt
->fourcc
>> 24) & 0xff);
869 static int vidioc_s_fmt_vid_cap(struct file
*file
, void *priv
,
870 struct v4l2_format
*f
)
874 ret
= vidioc_try_fmt_vid_cap(file
, priv
, f
);
878 return vidioc_s_fmt(file2ctx(file
), f
);
881 static int vidioc_s_fmt_vid_out(struct file
*file
, void *priv
,
882 struct v4l2_format
*f
)
884 struct vim2m_ctx
*ctx
= file2ctx(file
);
887 ret
= vidioc_try_fmt_vid_out(file
, priv
, f
);
891 ret
= vidioc_s_fmt(file2ctx(file
), f
);
893 ctx
->colorspace
= f
->fmt
.pix
.colorspace
;
894 ctx
->xfer_func
= f
->fmt
.pix
.xfer_func
;
895 ctx
->ycbcr_enc
= f
->fmt
.pix
.ycbcr_enc
;
896 ctx
->quant
= f
->fmt
.pix
.quantization
;
901 static int vim2m_s_ctrl(struct v4l2_ctrl
*ctrl
)
903 struct vim2m_ctx
*ctx
=
904 container_of(ctrl
->handler
, struct vim2m_ctx
, hdl
);
909 ctx
->mode
|= MEM2MEM_HFLIP
;
911 ctx
->mode
&= ~MEM2MEM_HFLIP
;
916 ctx
->mode
|= MEM2MEM_VFLIP
;
918 ctx
->mode
&= ~MEM2MEM_VFLIP
;
921 case V4L2_CID_TRANS_TIME_MSEC
:
922 ctx
->transtime
= ctrl
->val
;
923 if (ctx
->transtime
< 1)
927 case V4L2_CID_TRANS_NUM_BUFS
:
928 ctx
->translen
= ctrl
->val
;
932 v4l2_err(&ctx
->dev
->v4l2_dev
, "Invalid control\n");
939 static const struct v4l2_ctrl_ops vim2m_ctrl_ops
= {
940 .s_ctrl
= vim2m_s_ctrl
,
943 static const struct v4l2_ioctl_ops vim2m_ioctl_ops
= {
944 .vidioc_querycap
= vidioc_querycap
,
946 .vidioc_enum_fmt_vid_cap
= vidioc_enum_fmt_vid_cap
,
947 .vidioc_enum_framesizes
= vidioc_enum_framesizes
,
948 .vidioc_g_fmt_vid_cap
= vidioc_g_fmt_vid_cap
,
949 .vidioc_try_fmt_vid_cap
= vidioc_try_fmt_vid_cap
,
950 .vidioc_s_fmt_vid_cap
= vidioc_s_fmt_vid_cap
,
952 .vidioc_enum_fmt_vid_out
= vidioc_enum_fmt_vid_out
,
953 .vidioc_g_fmt_vid_out
= vidioc_g_fmt_vid_out
,
954 .vidioc_try_fmt_vid_out
= vidioc_try_fmt_vid_out
,
955 .vidioc_s_fmt_vid_out
= vidioc_s_fmt_vid_out
,
957 .vidioc_reqbufs
= v4l2_m2m_ioctl_reqbufs
,
958 .vidioc_querybuf
= v4l2_m2m_ioctl_querybuf
,
959 .vidioc_qbuf
= v4l2_m2m_ioctl_qbuf
,
960 .vidioc_dqbuf
= v4l2_m2m_ioctl_dqbuf
,
961 .vidioc_prepare_buf
= v4l2_m2m_ioctl_prepare_buf
,
962 .vidioc_create_bufs
= v4l2_m2m_ioctl_create_bufs
,
963 .vidioc_expbuf
= v4l2_m2m_ioctl_expbuf
,
965 .vidioc_streamon
= v4l2_m2m_ioctl_streamon
,
966 .vidioc_streamoff
= v4l2_m2m_ioctl_streamoff
,
968 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
969 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
976 static int vim2m_queue_setup(struct vb2_queue
*vq
,
977 unsigned int *nbuffers
,
978 unsigned int *nplanes
,
979 unsigned int sizes
[],
980 struct device
*alloc_devs
[])
982 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(vq
);
983 struct vim2m_q_data
*q_data
;
984 unsigned int size
, count
= *nbuffers
;
986 q_data
= get_q_data(ctx
, vq
->type
);
990 size
= q_data
->width
* q_data
->height
* q_data
->fmt
->depth
>> 3;
992 while (size
* count
> MEM2MEM_VID_MEM_LIMIT
)
997 return sizes
[0] < size
? -EINVAL
: 0;
1002 dprintk(ctx
->dev
, 1, "%s: get %d buffer(s) of size %d each.\n",
1003 type_name(vq
->type
), count
, size
);
1008 static int vim2m_buf_out_validate(struct vb2_buffer
*vb
)
1010 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1011 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1013 if (vbuf
->field
== V4L2_FIELD_ANY
)
1014 vbuf
->field
= V4L2_FIELD_NONE
;
1015 if (vbuf
->field
!= V4L2_FIELD_NONE
) {
1016 dprintk(ctx
->dev
, 1, "%s field isn't supported\n", __func__
);
1023 static int vim2m_buf_prepare(struct vb2_buffer
*vb
)
1025 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1026 struct vim2m_q_data
*q_data
;
1028 dprintk(ctx
->dev
, 2, "type: %s\n", type_name(vb
->vb2_queue
->type
));
1030 q_data
= get_q_data(ctx
, vb
->vb2_queue
->type
);
1033 if (vb2_plane_size(vb
, 0) < q_data
->sizeimage
) {
1034 dprintk(ctx
->dev
, 1,
1035 "%s data will not fit into plane (%lu < %lu)\n",
1036 __func__
, vb2_plane_size(vb
, 0),
1037 (long)q_data
->sizeimage
);
1041 vb2_set_plane_payload(vb
, 0, q_data
->sizeimage
);
1046 static void vim2m_buf_queue(struct vb2_buffer
*vb
)
1048 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1049 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1051 v4l2_m2m_buf_queue(ctx
->fh
.m2m_ctx
, vbuf
);
1054 static int vim2m_start_streaming(struct vb2_queue
*q
, unsigned int count
)
1056 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(q
);
1057 struct vim2m_q_data
*q_data
= get_q_data(ctx
, q
->type
);
1062 if (V4L2_TYPE_IS_OUTPUT(q
->type
))
1065 q_data
->sequence
= 0;
1069 static void vim2m_stop_streaming(struct vb2_queue
*q
)
1071 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(q
);
1072 struct vb2_v4l2_buffer
*vbuf
;
1074 cancel_delayed_work_sync(&ctx
->work_run
);
1077 if (V4L2_TYPE_IS_OUTPUT(q
->type
))
1078 vbuf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
1080 vbuf
= v4l2_m2m_dst_buf_remove(ctx
->fh
.m2m_ctx
);
1083 v4l2_ctrl_request_complete(vbuf
->vb2_buf
.req_obj
.req
,
1085 v4l2_m2m_buf_done(vbuf
, VB2_BUF_STATE_ERROR
);
1089 static void vim2m_buf_request_complete(struct vb2_buffer
*vb
)
1091 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1093 v4l2_ctrl_request_complete(vb
->req_obj
.req
, &ctx
->hdl
);
1096 static const struct vb2_ops vim2m_qops
= {
1097 .queue_setup
= vim2m_queue_setup
,
1098 .buf_out_validate
= vim2m_buf_out_validate
,
1099 .buf_prepare
= vim2m_buf_prepare
,
1100 .buf_queue
= vim2m_buf_queue
,
1101 .start_streaming
= vim2m_start_streaming
,
1102 .stop_streaming
= vim2m_stop_streaming
,
1103 .buf_request_complete
= vim2m_buf_request_complete
,
1106 static int queue_init(void *priv
, struct vb2_queue
*src_vq
,
1107 struct vb2_queue
*dst_vq
)
1109 struct vim2m_ctx
*ctx
= priv
;
1112 src_vq
->type
= V4L2_BUF_TYPE_VIDEO_OUTPUT
;
1113 src_vq
->io_modes
= VB2_MMAP
| VB2_USERPTR
| VB2_DMABUF
;
1114 src_vq
->drv_priv
= ctx
;
1115 src_vq
->buf_struct_size
= sizeof(struct v4l2_m2m_buffer
);
1116 src_vq
->ops
= &vim2m_qops
;
1117 src_vq
->mem_ops
= &vb2_vmalloc_memops
;
1118 src_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1119 src_vq
->lock
= &ctx
->vb_mutex
;
1120 src_vq
->supports_requests
= true;
1122 ret
= vb2_queue_init(src_vq
);
1126 dst_vq
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1127 dst_vq
->io_modes
= VB2_MMAP
| VB2_USERPTR
| VB2_DMABUF
;
1128 dst_vq
->drv_priv
= ctx
;
1129 dst_vq
->buf_struct_size
= sizeof(struct v4l2_m2m_buffer
);
1130 dst_vq
->ops
= &vim2m_qops
;
1131 dst_vq
->mem_ops
= &vb2_vmalloc_memops
;
1132 dst_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1133 dst_vq
->lock
= &ctx
->vb_mutex
;
1135 return vb2_queue_init(dst_vq
);
1138 static struct v4l2_ctrl_config vim2m_ctrl_trans_time_msec
= {
1139 .ops
= &vim2m_ctrl_ops
,
1140 .id
= V4L2_CID_TRANS_TIME_MSEC
,
1141 .name
= "Transaction Time (msec)",
1142 .type
= V4L2_CTRL_TYPE_INTEGER
,
1148 static const struct v4l2_ctrl_config vim2m_ctrl_trans_num_bufs
= {
1149 .ops
= &vim2m_ctrl_ops
,
1150 .id
= V4L2_CID_TRANS_NUM_BUFS
,
1151 .name
= "Buffers Per Transaction",
1152 .type
= V4L2_CTRL_TYPE_INTEGER
,
1155 .max
= MEM2MEM_DEF_NUM_BUFS
,
1162 static int vim2m_open(struct file
*file
)
1164 struct vim2m_dev
*dev
= video_drvdata(file
);
1165 struct vim2m_ctx
*ctx
= NULL
;
1166 struct v4l2_ctrl_handler
*hdl
;
1169 if (mutex_lock_interruptible(&dev
->dev_mutex
))
1170 return -ERESTARTSYS
;
1171 ctx
= kzalloc(sizeof(*ctx
), GFP_KERNEL
);
1177 v4l2_fh_init(&ctx
->fh
, video_devdata(file
));
1178 file
->private_data
= &ctx
->fh
;
1181 v4l2_ctrl_handler_init(hdl
, 4);
1182 v4l2_ctrl_new_std(hdl
, &vim2m_ctrl_ops
, V4L2_CID_HFLIP
, 0, 1, 1, 0);
1183 v4l2_ctrl_new_std(hdl
, &vim2m_ctrl_ops
, V4L2_CID_VFLIP
, 0, 1, 1, 0);
1185 vim2m_ctrl_trans_time_msec
.def
= default_transtime
;
1186 v4l2_ctrl_new_custom(hdl
, &vim2m_ctrl_trans_time_msec
, NULL
);
1187 v4l2_ctrl_new_custom(hdl
, &vim2m_ctrl_trans_num_bufs
, NULL
);
1190 v4l2_ctrl_handler_free(hdl
);
1194 ctx
->fh
.ctrl_handler
= hdl
;
1195 v4l2_ctrl_handler_setup(hdl
);
1197 ctx
->q_data
[V4L2_M2M_SRC
].fmt
= &formats
[0];
1198 ctx
->q_data
[V4L2_M2M_SRC
].width
= 640;
1199 ctx
->q_data
[V4L2_M2M_SRC
].height
= 480;
1200 ctx
->q_data
[V4L2_M2M_SRC
].sizeimage
=
1201 ctx
->q_data
[V4L2_M2M_SRC
].width
*
1202 ctx
->q_data
[V4L2_M2M_SRC
].height
*
1203 (ctx
->q_data
[V4L2_M2M_SRC
].fmt
->depth
>> 3);
1204 ctx
->q_data
[V4L2_M2M_DST
] = ctx
->q_data
[V4L2_M2M_SRC
];
1205 ctx
->colorspace
= V4L2_COLORSPACE_REC709
;
1207 ctx
->fh
.m2m_ctx
= v4l2_m2m_ctx_init(dev
->m2m_dev
, ctx
, &queue_init
);
1209 mutex_init(&ctx
->vb_mutex
);
1210 INIT_DELAYED_WORK(&ctx
->work_run
, device_work
);
1212 if (IS_ERR(ctx
->fh
.m2m_ctx
)) {
1213 rc
= PTR_ERR(ctx
->fh
.m2m_ctx
);
1215 v4l2_ctrl_handler_free(hdl
);
1216 v4l2_fh_exit(&ctx
->fh
);
1221 v4l2_fh_add(&ctx
->fh
);
1222 atomic_inc(&dev
->num_inst
);
1224 dprintk(dev
, 1, "Created instance: %p, m2m_ctx: %p\n",
1225 ctx
, ctx
->fh
.m2m_ctx
);
1228 mutex_unlock(&dev
->dev_mutex
);
1232 static int vim2m_release(struct file
*file
)
1234 struct vim2m_dev
*dev
= video_drvdata(file
);
1235 struct vim2m_ctx
*ctx
= file2ctx(file
);
1237 dprintk(dev
, 1, "Releasing instance %p\n", ctx
);
1239 v4l2_fh_del(&ctx
->fh
);
1240 v4l2_fh_exit(&ctx
->fh
);
1241 v4l2_ctrl_handler_free(&ctx
->hdl
);
1242 mutex_lock(&dev
->dev_mutex
);
1243 v4l2_m2m_ctx_release(ctx
->fh
.m2m_ctx
);
1244 mutex_unlock(&dev
->dev_mutex
);
1247 atomic_dec(&dev
->num_inst
);
1252 static void vim2m_device_release(struct video_device
*vdev
)
1254 struct vim2m_dev
*dev
= container_of(vdev
, struct vim2m_dev
, vfd
);
1256 v4l2_device_unregister(&dev
->v4l2_dev
);
1257 v4l2_m2m_release(dev
->m2m_dev
);
1258 #ifdef CONFIG_MEDIA_CONTROLLER
1259 media_device_cleanup(&dev
->mdev
);
1264 static const struct v4l2_file_operations vim2m_fops
= {
1265 .owner
= THIS_MODULE
,
1267 .release
= vim2m_release
,
1268 .poll
= v4l2_m2m_fop_poll
,
1269 .unlocked_ioctl
= video_ioctl2
,
1270 .mmap
= v4l2_m2m_fop_mmap
,
1273 static const struct video_device vim2m_videodev
= {
1274 .name
= MEM2MEM_NAME
,
1275 .vfl_dir
= VFL_DIR_M2M
,
1276 .fops
= &vim2m_fops
,
1277 .ioctl_ops
= &vim2m_ioctl_ops
,
1279 .release
= vim2m_device_release
,
1280 .device_caps
= V4L2_CAP_VIDEO_M2M
| V4L2_CAP_STREAMING
,
1283 static const struct v4l2_m2m_ops m2m_ops
= {
1284 .device_run
= device_run
,
1285 .job_ready
= job_ready
,
1286 .job_abort
= job_abort
,
1289 static const struct media_device_ops m2m_media_ops
= {
1290 .req_validate
= vb2_request_validate
,
1291 .req_queue
= v4l2_m2m_request_queue
,
1294 static int vim2m_probe(struct platform_device
*pdev
)
1296 struct vim2m_dev
*dev
;
1297 struct video_device
*vfd
;
1300 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
1304 ret
= v4l2_device_register(&pdev
->dev
, &dev
->v4l2_dev
);
1308 atomic_set(&dev
->num_inst
, 0);
1309 mutex_init(&dev
->dev_mutex
);
1311 dev
->vfd
= vim2m_videodev
;
1313 vfd
->lock
= &dev
->dev_mutex
;
1314 vfd
->v4l2_dev
= &dev
->v4l2_dev
;
1316 video_set_drvdata(vfd
, dev
);
1317 v4l2_info(&dev
->v4l2_dev
,
1318 "Device registered as /dev/video%d\n", vfd
->num
);
1320 platform_set_drvdata(pdev
, dev
);
1322 dev
->m2m_dev
= v4l2_m2m_init(&m2m_ops
);
1323 if (IS_ERR(dev
->m2m_dev
)) {
1324 v4l2_err(&dev
->v4l2_dev
, "Failed to init mem2mem device\n");
1325 ret
= PTR_ERR(dev
->m2m_dev
);
1326 dev
->m2m_dev
= NULL
;
1330 #ifdef CONFIG_MEDIA_CONTROLLER
1331 dev
->mdev
.dev
= &pdev
->dev
;
1332 strscpy(dev
->mdev
.model
, "vim2m", sizeof(dev
->mdev
.model
));
1333 strscpy(dev
->mdev
.bus_info
, "platform:vim2m",
1334 sizeof(dev
->mdev
.bus_info
));
1335 media_device_init(&dev
->mdev
);
1336 dev
->mdev
.ops
= &m2m_media_ops
;
1337 dev
->v4l2_dev
.mdev
= &dev
->mdev
;
1340 ret
= video_register_device(vfd
, VFL_TYPE_VIDEO
, 0);
1342 v4l2_err(&dev
->v4l2_dev
, "Failed to register video device\n");
1346 #ifdef CONFIG_MEDIA_CONTROLLER
1347 ret
= v4l2_m2m_register_media_controller(dev
->m2m_dev
, vfd
,
1348 MEDIA_ENT_F_PROC_VIDEO_SCALER
);
1350 v4l2_err(&dev
->v4l2_dev
, "Failed to init mem2mem media controller\n");
1354 ret
= media_device_register(&dev
->mdev
);
1356 v4l2_err(&dev
->v4l2_dev
, "Failed to register mem2mem media device\n");
1362 #ifdef CONFIG_MEDIA_CONTROLLER
1364 v4l2_m2m_unregister_media_controller(dev
->m2m_dev
);
1367 video_unregister_device(&dev
->vfd
);
1368 /* vim2m_device_release called by video_unregister_device to release various objects */
1371 v4l2_m2m_release(dev
->m2m_dev
);
1373 v4l2_device_unregister(&dev
->v4l2_dev
);
1380 static void vim2m_remove(struct platform_device
*pdev
)
1382 struct vim2m_dev
*dev
= platform_get_drvdata(pdev
);
1384 v4l2_info(&dev
->v4l2_dev
, "Removing " MEM2MEM_NAME
);
1386 #ifdef CONFIG_MEDIA_CONTROLLER
1387 media_device_unregister(&dev
->mdev
);
1388 v4l2_m2m_unregister_media_controller(dev
->m2m_dev
);
1390 video_unregister_device(&dev
->vfd
);
1393 static struct platform_driver vim2m_pdrv
= {
1394 .probe
= vim2m_probe
,
1395 .remove
= vim2m_remove
,
1397 .name
= MEM2MEM_NAME
,
1401 static void __exit
vim2m_exit(void)
1403 platform_driver_unregister(&vim2m_pdrv
);
1404 platform_device_unregister(&vim2m_pdev
);
1407 static int __init
vim2m_init(void)
1411 ret
= platform_device_register(&vim2m_pdev
);
1415 ret
= platform_driver_register(&vim2m_pdrv
);
1417 platform_device_unregister(&vim2m_pdev
);
1422 module_init(vim2m_init
);
1423 module_exit(vim2m_exit
);