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 videobuf 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 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by the
18 * Free Software Foundation; either version 2 of the
19 * License, or (at your option) any later version
21 #include <linux/module.h>
22 #include <linux/delay.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/v4l2-ctrls.h>
32 #include <media/v4l2-event.h>
33 #include <media/videobuf2-vmalloc.h>
35 MODULE_DESCRIPTION("Virtual device for mem2mem framework testing");
36 MODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
37 MODULE_LICENSE("GPL");
38 MODULE_VERSION("0.2");
39 MODULE_ALIAS("mem2mem_testdev");
41 static unsigned int debug
;
42 module_param(debug
, uint
, 0644);
43 MODULE_PARM_DESC(debug
, "debug level");
45 /* Default transaction time in msec */
46 static unsigned int default_transtime
= 40; /* Max 25 fps */
47 module_param(default_transtime
, uint
, 0644);
48 MODULE_PARM_DESC(default_transtime
, "default transaction time in ms");
55 /* Pixel alignment for non-bayer formats */
57 #define HEIGHT_ALIGN 1
59 /* Pixel alignment for bayer formats */
60 #define BAYER_WIDTH_ALIGN 2
61 #define BAYER_HEIGHT_ALIGN 2
63 /* Flags that indicate a format can be used for capture/output */
64 #define MEM2MEM_CAPTURE BIT(0)
65 #define MEM2MEM_OUTPUT BIT(1)
67 #define MEM2MEM_NAME "vim2m"
70 #define MEM2MEM_DEF_NUM_BUFS VIDEO_MAX_FRAME
71 /* In bytes, per queue */
72 #define MEM2MEM_VID_MEM_LIMIT (16 * 1024 * 1024)
74 /* Flags that indicate processing mode */
75 #define MEM2MEM_HFLIP BIT(0)
76 #define MEM2MEM_VFLIP BIT(1)
78 #define dprintk(dev, lvl, fmt, arg...) \
79 v4l2_dbg(lvl, debug, &(dev)->v4l2_dev, "%s: " fmt, __func__, ## arg)
81 static void vim2m_dev_release(struct device
*dev
)
84 static struct platform_device vim2m_pdev
= {
86 .dev
.release
= vim2m_dev_release
,
92 /* Types the format can be used for */
96 static struct vim2m_fmt formats
[] = {
98 .fourcc
= V4L2_PIX_FMT_RGB565
, /* rrrrrggg gggbbbbb */
100 .types
= MEM2MEM_CAPTURE
| MEM2MEM_OUTPUT
,
102 .fourcc
= V4L2_PIX_FMT_RGB565X
, /* gggbbbbb rrrrrggg */
104 .types
= MEM2MEM_CAPTURE
| MEM2MEM_OUTPUT
,
106 .fourcc
= V4L2_PIX_FMT_RGB24
,
108 .types
= MEM2MEM_CAPTURE
| MEM2MEM_OUTPUT
,
110 .fourcc
= V4L2_PIX_FMT_BGR24
,
112 .types
= MEM2MEM_CAPTURE
| MEM2MEM_OUTPUT
,
114 .fourcc
= V4L2_PIX_FMT_YUYV
,
116 .types
= MEM2MEM_CAPTURE
,
118 .fourcc
= V4L2_PIX_FMT_SBGGR8
,
120 .types
= MEM2MEM_CAPTURE
,
122 .fourcc
= V4L2_PIX_FMT_SGBRG8
,
124 .types
= MEM2MEM_CAPTURE
,
126 .fourcc
= V4L2_PIX_FMT_SGRBG8
,
128 .types
= MEM2MEM_CAPTURE
,
130 .fourcc
= V4L2_PIX_FMT_SRGGB8
,
132 .types
= MEM2MEM_CAPTURE
,
136 #define NUM_FORMATS ARRAY_SIZE(formats)
138 /* Per-queue, driver-specific private data */
139 struct vim2m_q_data
{
142 unsigned int sizeimage
;
143 unsigned int sequence
;
144 struct vim2m_fmt
*fmt
;
152 #define V4L2_CID_TRANS_TIME_MSEC (V4L2_CID_USER_BASE + 0x1000)
153 #define V4L2_CID_TRANS_NUM_BUFS (V4L2_CID_USER_BASE + 0x1001)
155 static struct vim2m_fmt
*find_format(u32 fourcc
)
157 struct vim2m_fmt
*fmt
;
160 for (k
= 0; k
< NUM_FORMATS
; k
++) {
162 if (fmt
->fourcc
== fourcc
)
166 if (k
== NUM_FORMATS
)
172 static void get_alignment(u32 fourcc
,
173 unsigned int *walign
, unsigned int *halign
)
176 case V4L2_PIX_FMT_SBGGR8
:
177 case V4L2_PIX_FMT_SGBRG8
:
178 case V4L2_PIX_FMT_SGRBG8
:
179 case V4L2_PIX_FMT_SRGGB8
:
180 *walign
= BAYER_WIDTH_ALIGN
;
181 *halign
= BAYER_HEIGHT_ALIGN
;
184 *walign
= WIDTH_ALIGN
;
185 *halign
= HEIGHT_ALIGN
;
191 struct v4l2_device v4l2_dev
;
192 struct video_device vfd
;
193 #ifdef CONFIG_MEDIA_CONTROLLER
194 struct media_device mdev
;
198 struct mutex dev_mutex
;
200 struct v4l2_m2m_dev
*m2m_dev
;
205 struct vim2m_dev
*dev
;
207 struct v4l2_ctrl_handler hdl
;
209 /* Processed buffers in this transaction */
212 /* Transaction length (i.e. how many buffers per transaction) */
214 /* Transaction time (i.e. simulated processing time) in milliseconds */
217 struct mutex vb_mutex
;
218 struct delayed_work work_run
;
221 /* Abort requested by m2m */
224 /* Processing mode */
227 enum v4l2_colorspace colorspace
;
228 enum v4l2_ycbcr_encoding ycbcr_enc
;
229 enum v4l2_xfer_func xfer_func
;
230 enum v4l2_quantization quant
;
232 /* Source and destination queue data */
233 struct vim2m_q_data q_data
[2];
236 static inline struct vim2m_ctx
*file2ctx(struct file
*file
)
238 return container_of(file
->private_data
, struct vim2m_ctx
, fh
);
241 static struct vim2m_q_data
*get_q_data(struct vim2m_ctx
*ctx
,
242 enum v4l2_buf_type type
)
245 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
246 return &ctx
->q_data
[V4L2_M2M_SRC
];
247 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
248 return &ctx
->q_data
[V4L2_M2M_DST
];
254 static const char *type_name(enum v4l2_buf_type type
)
257 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
259 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
266 #define CLIP(__color) \
267 (u8)(((__color) > 0xff) ? 0xff : (((__color) < 0) ? 0 : (__color)))
269 static void copy_line(struct vim2m_q_data
*q_data_out
,
270 u8
*src
, u8
*dst
, bool reverse
)
272 int x
, depth
= q_data_out
->fmt
->depth
>> 3;
275 memcpy(dst
, src
, q_data_out
->width
* depth
);
277 for (x
= 0; x
< q_data_out
->width
>> 1; x
++) {
278 memcpy(dst
, src
, depth
);
279 memcpy(dst
+ depth
, src
- depth
, depth
);
287 static void copy_two_pixels(struct vim2m_q_data
*q_data_in
,
288 struct vim2m_q_data
*q_data_out
,
289 u8
*src
[2], u8
**dst
, int ypos
, bool reverse
)
291 struct vim2m_fmt
*out
= q_data_out
->fmt
;
292 struct vim2m_fmt
*in
= q_data_in
->fmt
;
293 u8 _r
[2], _g
[2], _b
[2], *r
, *g
, *b
;
296 /* Step 1: read two consecutive pixels from src pointer */
302 switch (in
->fourcc
) {
303 case V4L2_PIX_FMT_RGB565
: /* rrrrrggg gggbbbbb */
304 for (i
= 0; i
< 2; i
++) {
305 u16 pix
= le16_to_cpu(*(__le16
*)(src
[i
]));
307 *r
++ = (u8
)(((pix
& 0xf800) >> 11) << 3) | 0x07;
308 *g
++ = (u8
)((((pix
& 0x07e0) >> 5)) << 2) | 0x03;
309 *b
++ = (u8
)((pix
& 0x1f) << 3) | 0x07;
312 case V4L2_PIX_FMT_RGB565X
: /* gggbbbbb rrrrrggg */
313 for (i
= 0; i
< 2; i
++) {
314 u16 pix
= be16_to_cpu(*(__be16
*)(src
[i
]));
316 *r
++ = (u8
)(((pix
& 0xf800) >> 11) << 3) | 0x07;
317 *g
++ = (u8
)((((pix
& 0x07e0) >> 5)) << 2) | 0x03;
318 *b
++ = (u8
)((pix
& 0x1f) << 3) | 0x07;
322 case V4L2_PIX_FMT_RGB24
:
323 for (i
= 0; i
< 2; i
++) {
329 case V4L2_PIX_FMT_BGR24
:
330 for (i
= 0; i
< 2; i
++) {
338 /* Step 2: store two consecutive points, reversing them if needed */
344 switch (out
->fourcc
) {
345 case V4L2_PIX_FMT_RGB565
: /* rrrrrggg gggbbbbb */
346 for (i
= 0; i
< 2; i
++) {
348 __le16
*dst_pix
= (__le16
*)*dst
;
350 pix
= ((*r
<< 8) & 0xf800) | ((*g
<< 3) & 0x07e0) |
353 *dst_pix
= cpu_to_le16(pix
);
358 case V4L2_PIX_FMT_RGB565X
: /* gggbbbbb rrrrrggg */
359 for (i
= 0; i
< 2; i
++) {
361 __be16
*dst_pix
= (__be16
*)*dst
;
363 pix
= ((*r
<< 8) & 0xf800) | ((*g
<< 3) & 0x07e0) |
366 *dst_pix
= cpu_to_be16(pix
);
371 case V4L2_PIX_FMT_RGB24
:
372 for (i
= 0; i
< 2; i
++) {
378 case V4L2_PIX_FMT_BGR24
:
379 for (i
= 0; i
< 2; i
++) {
385 case V4L2_PIX_FMT_YUYV
:
390 y
= ((8453 * (*r
) + 16594 * (*g
) + 3223 * (*b
)
392 u
= ((-4878 * (*r
) - 9578 * (*g
) + 14456 * (*b
)
394 v
= ((14456 * (*r
++) - 12105 * (*g
++) - 2351 * (*b
++)
396 y1
= ((8453 * (*r
) + 16594 * (*g
) + 3223 * (*b
)
406 case V4L2_PIX_FMT_SBGGR8
:
415 case V4L2_PIX_FMT_SGBRG8
:
424 case V4L2_PIX_FMT_SGRBG8
:
433 case V4L2_PIX_FMT_SRGGB8
:
445 static int device_process(struct vim2m_ctx
*ctx
,
446 struct vb2_v4l2_buffer
*in_vb
,
447 struct vb2_v4l2_buffer
*out_vb
)
449 struct vim2m_dev
*dev
= ctx
->dev
;
450 struct vim2m_q_data
*q_data_in
, *q_data_out
;
451 u8
*p_in
, *p_line
, *p_in_x
[2], *p
, *p_out
;
452 unsigned int width
, height
, bytesperline
, bytes_per_pixel
;
453 unsigned int x
, y
, y_in
, y_out
, x_int
, x_fract
, x_err
, x_offset
;
454 int start
, end
, step
;
456 q_data_in
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_OUTPUT
);
459 bytesperline
= (q_data_in
->width
* q_data_in
->fmt
->depth
) >> 3;
460 bytes_per_pixel
= q_data_in
->fmt
->depth
>> 3;
462 q_data_out
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_CAPTURE
);
466 /* As we're doing scaling, use the output dimensions here */
467 height
= q_data_out
->height
;
468 width
= q_data_out
->width
;
470 p_in
= vb2_plane_vaddr(&in_vb
->vb2_buf
, 0);
471 p_out
= vb2_plane_vaddr(&out_vb
->vb2_buf
, 0);
472 if (!p_in
|| !p_out
) {
473 v4l2_err(&dev
->v4l2_dev
,
474 "Acquiring kernel pointers to buffers failed\n");
478 out_vb
->sequence
= q_data_out
->sequence
++;
479 in_vb
->sequence
= q_data_in
->sequence
++;
480 v4l2_m2m_buf_copy_metadata(in_vb
, out_vb
, true);
482 if (ctx
->mode
& MEM2MEM_VFLIP
) {
494 * When format and resolution are identical,
495 * we can use a faster copy logic
497 if (q_data_in
->fmt
->fourcc
== q_data_out
->fmt
->fourcc
&&
498 q_data_in
->width
== q_data_out
->width
&&
499 q_data_in
->height
== q_data_out
->height
) {
500 for (y
= start
; y
!= end
; y
+= step
, y_out
++) {
501 p
= p_in
+ (y
* bytesperline
);
502 if (ctx
->mode
& MEM2MEM_HFLIP
)
503 p
+= bytesperline
- (q_data_in
->fmt
->depth
>> 3);
505 copy_line(q_data_out
, p
, p_out
,
506 ctx
->mode
& MEM2MEM_HFLIP
);
508 p_out
+= bytesperline
;
513 /* Slower algorithm with format conversion, hflip, vflip and scaler */
515 /* To speed scaler up, use Bresenham for X dimension */
516 x_int
= q_data_in
->width
/ q_data_out
->width
;
517 x_fract
= q_data_in
->width
% q_data_out
->width
;
519 for (y
= start
; y
!= end
; y
+= step
, y_out
++) {
520 y_in
= (y
* q_data_in
->height
) / q_data_out
->height
;
524 p_line
= p_in
+ (y_in
* bytesperline
);
525 if (ctx
->mode
& MEM2MEM_HFLIP
)
526 p_line
+= bytesperline
- (q_data_in
->fmt
->depth
>> 3);
529 for (x
= 0; x
< width
>> 1; x
++) {
537 if (ctx
->mode
& MEM2MEM_HFLIP
)
538 p_in_x
[1] = p_line
- x_offset
* bytes_per_pixel
;
540 p_in_x
[1] = p_line
+ x_offset
* bytes_per_pixel
;
542 copy_two_pixels(q_data_in
, q_data_out
,
543 p_in_x
, &p_out
, y_out
,
544 ctx
->mode
& MEM2MEM_HFLIP
);
546 /* Calculate the next p_in_x0 */
554 if (ctx
->mode
& MEM2MEM_HFLIP
)
555 p_in_x
[0] = p_line
- x_offset
* bytes_per_pixel
;
557 p_in_x
[0] = p_line
+ x_offset
* bytes_per_pixel
;
569 * job_ready() - check whether an instance is ready to be scheduled to run
571 static int job_ready(void *priv
)
573 struct vim2m_ctx
*ctx
= priv
;
575 if (v4l2_m2m_num_src_bufs_ready(ctx
->fh
.m2m_ctx
) < ctx
->translen
576 || v4l2_m2m_num_dst_bufs_ready(ctx
->fh
.m2m_ctx
) < ctx
->translen
) {
577 dprintk(ctx
->dev
, 1, "Not enough buffers available\n");
584 static void job_abort(void *priv
)
586 struct vim2m_ctx
*ctx
= priv
;
588 /* Will cancel the transaction in the next interrupt handler */
592 /* device_run() - prepares and starts the device
594 * This simulates all the immediate preparations required before starting
595 * a device. This will be called by the framework when it decides to schedule
596 * a particular instance.
598 static void device_run(void *priv
)
600 struct vim2m_ctx
*ctx
= priv
;
601 struct vb2_v4l2_buffer
*src_buf
, *dst_buf
;
603 src_buf
= v4l2_m2m_next_src_buf(ctx
->fh
.m2m_ctx
);
604 dst_buf
= v4l2_m2m_next_dst_buf(ctx
->fh
.m2m_ctx
);
606 /* Apply request controls if any */
607 v4l2_ctrl_request_setup(src_buf
->vb2_buf
.req_obj
.req
,
610 device_process(ctx
, src_buf
, dst_buf
);
612 /* Complete request controls if any */
613 v4l2_ctrl_request_complete(src_buf
->vb2_buf
.req_obj
.req
,
616 /* Run delayed work, which simulates a hardware irq */
617 schedule_delayed_work(&ctx
->work_run
, msecs_to_jiffies(ctx
->transtime
));
620 static void device_work(struct work_struct
*w
)
622 struct vim2m_ctx
*curr_ctx
;
623 struct vim2m_dev
*vim2m_dev
;
624 struct vb2_v4l2_buffer
*src_vb
, *dst_vb
;
627 curr_ctx
= container_of(w
, struct vim2m_ctx
, work_run
.work
);
630 pr_err("Instance released before the end of transaction\n");
634 vim2m_dev
= curr_ctx
->dev
;
636 src_vb
= v4l2_m2m_src_buf_remove(curr_ctx
->fh
.m2m_ctx
);
637 dst_vb
= v4l2_m2m_dst_buf_remove(curr_ctx
->fh
.m2m_ctx
);
639 curr_ctx
->num_processed
++;
641 spin_lock_irqsave(&curr_ctx
->irqlock
, flags
);
642 v4l2_m2m_buf_done(src_vb
, VB2_BUF_STATE_DONE
);
643 v4l2_m2m_buf_done(dst_vb
, VB2_BUF_STATE_DONE
);
644 spin_unlock_irqrestore(&curr_ctx
->irqlock
, flags
);
646 if (curr_ctx
->num_processed
== curr_ctx
->translen
647 || curr_ctx
->aborting
) {
648 dprintk(curr_ctx
->dev
, 2, "Finishing capture buffer fill\n");
649 curr_ctx
->num_processed
= 0;
650 v4l2_m2m_job_finish(vim2m_dev
->m2m_dev
, curr_ctx
->fh
.m2m_ctx
);
652 device_run(curr_ctx
);
659 static int vidioc_querycap(struct file
*file
, void *priv
,
660 struct v4l2_capability
*cap
)
662 strscpy(cap
->driver
, MEM2MEM_NAME
, sizeof(cap
->driver
));
663 strscpy(cap
->card
, MEM2MEM_NAME
, sizeof(cap
->card
));
664 snprintf(cap
->bus_info
, sizeof(cap
->bus_info
),
665 "platform:%s", MEM2MEM_NAME
);
669 static int enum_fmt(struct v4l2_fmtdesc
*f
, u32 type
)
672 struct vim2m_fmt
*fmt
;
676 for (i
= 0; i
< NUM_FORMATS
; ++i
) {
677 if (formats
[i
].types
& type
) {
678 /* index-th format of type type found ? */
682 * Correct type but haven't reached our index yet,
683 * just increment per-type index
689 if (i
< NUM_FORMATS
) {
692 f
->pixelformat
= fmt
->fourcc
;
696 /* Format not found */
700 static int vidioc_enum_fmt_vid_cap(struct file
*file
, void *priv
,
701 struct v4l2_fmtdesc
*f
)
703 return enum_fmt(f
, MEM2MEM_CAPTURE
);
706 static int vidioc_enum_fmt_vid_out(struct file
*file
, void *priv
,
707 struct v4l2_fmtdesc
*f
)
709 return enum_fmt(f
, MEM2MEM_OUTPUT
);
712 static int vidioc_enum_framesizes(struct file
*file
, void *priv
,
713 struct v4l2_frmsizeenum
*fsize
)
715 if (fsize
->index
!= 0)
718 if (!find_format(fsize
->pixel_format
))
721 fsize
->type
= V4L2_FRMSIZE_TYPE_STEPWISE
;
722 fsize
->stepwise
.min_width
= MIN_W
;
723 fsize
->stepwise
.min_height
= MIN_H
;
724 fsize
->stepwise
.max_width
= MAX_W
;
725 fsize
->stepwise
.max_height
= MAX_H
;
727 get_alignment(fsize
->pixel_format
,
728 &fsize
->stepwise
.step_width
,
729 &fsize
->stepwise
.step_height
);
733 static int vidioc_g_fmt(struct vim2m_ctx
*ctx
, struct v4l2_format
*f
)
735 struct vb2_queue
*vq
;
736 struct vim2m_q_data
*q_data
;
738 vq
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
, f
->type
);
742 q_data
= get_q_data(ctx
, f
->type
);
746 f
->fmt
.pix
.width
= q_data
->width
;
747 f
->fmt
.pix
.height
= q_data
->height
;
748 f
->fmt
.pix
.field
= V4L2_FIELD_NONE
;
749 f
->fmt
.pix
.pixelformat
= q_data
->fmt
->fourcc
;
750 f
->fmt
.pix
.bytesperline
= (q_data
->width
* q_data
->fmt
->depth
) >> 3;
751 f
->fmt
.pix
.sizeimage
= q_data
->sizeimage
;
752 f
->fmt
.pix
.colorspace
= ctx
->colorspace
;
753 f
->fmt
.pix
.xfer_func
= ctx
->xfer_func
;
754 f
->fmt
.pix
.ycbcr_enc
= ctx
->ycbcr_enc
;
755 f
->fmt
.pix
.quantization
= ctx
->quant
;
760 static int vidioc_g_fmt_vid_out(struct file
*file
, void *priv
,
761 struct v4l2_format
*f
)
763 return vidioc_g_fmt(file2ctx(file
), f
);
766 static int vidioc_g_fmt_vid_cap(struct file
*file
, void *priv
,
767 struct v4l2_format
*f
)
769 return vidioc_g_fmt(file2ctx(file
), f
);
772 static int vidioc_try_fmt(struct v4l2_format
*f
, struct vim2m_fmt
*fmt
)
776 * V4L2 specification specifies the driver corrects the
777 * format struct if any of the dimensions is unsupported
779 if (f
->fmt
.pix
.height
< MIN_H
)
780 f
->fmt
.pix
.height
= MIN_H
;
781 else if (f
->fmt
.pix
.height
> MAX_H
)
782 f
->fmt
.pix
.height
= MAX_H
;
784 if (f
->fmt
.pix
.width
< MIN_W
)
785 f
->fmt
.pix
.width
= MIN_W
;
786 else if (f
->fmt
.pix
.width
> MAX_W
)
787 f
->fmt
.pix
.width
= MAX_W
;
789 get_alignment(f
->fmt
.pix
.pixelformat
, &walign
, &halign
);
790 f
->fmt
.pix
.width
&= ~(walign
- 1);
791 f
->fmt
.pix
.height
&= ~(halign
- 1);
792 f
->fmt
.pix
.bytesperline
= (f
->fmt
.pix
.width
* fmt
->depth
) >> 3;
793 f
->fmt
.pix
.sizeimage
= f
->fmt
.pix
.height
* f
->fmt
.pix
.bytesperline
;
794 f
->fmt
.pix
.field
= V4L2_FIELD_NONE
;
799 static int vidioc_try_fmt_vid_cap(struct file
*file
, void *priv
,
800 struct v4l2_format
*f
)
802 struct vim2m_fmt
*fmt
;
803 struct vim2m_ctx
*ctx
= file2ctx(file
);
805 fmt
= find_format(f
->fmt
.pix
.pixelformat
);
807 f
->fmt
.pix
.pixelformat
= formats
[0].fourcc
;
808 fmt
= find_format(f
->fmt
.pix
.pixelformat
);
810 if (!(fmt
->types
& MEM2MEM_CAPTURE
)) {
811 v4l2_err(&ctx
->dev
->v4l2_dev
,
812 "Fourcc format (0x%08x) invalid.\n",
813 f
->fmt
.pix
.pixelformat
);
816 f
->fmt
.pix
.colorspace
= ctx
->colorspace
;
817 f
->fmt
.pix
.xfer_func
= ctx
->xfer_func
;
818 f
->fmt
.pix
.ycbcr_enc
= ctx
->ycbcr_enc
;
819 f
->fmt
.pix
.quantization
= ctx
->quant
;
821 return vidioc_try_fmt(f
, fmt
);
824 static int vidioc_try_fmt_vid_out(struct file
*file
, void *priv
,
825 struct v4l2_format
*f
)
827 struct vim2m_fmt
*fmt
;
828 struct vim2m_ctx
*ctx
= file2ctx(file
);
830 fmt
= find_format(f
->fmt
.pix
.pixelformat
);
832 f
->fmt
.pix
.pixelformat
= formats
[0].fourcc
;
833 fmt
= find_format(f
->fmt
.pix
.pixelformat
);
835 if (!(fmt
->types
& MEM2MEM_OUTPUT
)) {
836 v4l2_err(&ctx
->dev
->v4l2_dev
,
837 "Fourcc format (0x%08x) invalid.\n",
838 f
->fmt
.pix
.pixelformat
);
841 if (!f
->fmt
.pix
.colorspace
)
842 f
->fmt
.pix
.colorspace
= V4L2_COLORSPACE_REC709
;
844 return vidioc_try_fmt(f
, fmt
);
847 static int vidioc_s_fmt(struct vim2m_ctx
*ctx
, struct v4l2_format
*f
)
849 struct vim2m_q_data
*q_data
;
850 struct vb2_queue
*vq
;
852 vq
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
, f
->type
);
856 q_data
= get_q_data(ctx
, f
->type
);
860 if (vb2_is_busy(vq
)) {
861 v4l2_err(&ctx
->dev
->v4l2_dev
, "%s queue busy\n", __func__
);
865 q_data
->fmt
= find_format(f
->fmt
.pix
.pixelformat
);
866 q_data
->width
= f
->fmt
.pix
.width
;
867 q_data
->height
= f
->fmt
.pix
.height
;
868 q_data
->sizeimage
= q_data
->width
* q_data
->height
869 * q_data
->fmt
->depth
>> 3;
872 "Format for type %s: %dx%d (%d bpp), fmt: %c%c%c%c\n",
873 type_name(f
->type
), q_data
->width
, q_data
->height
,
875 (q_data
->fmt
->fourcc
& 0xff),
876 (q_data
->fmt
->fourcc
>> 8) & 0xff,
877 (q_data
->fmt
->fourcc
>> 16) & 0xff,
878 (q_data
->fmt
->fourcc
>> 24) & 0xff);
883 static int vidioc_s_fmt_vid_cap(struct file
*file
, void *priv
,
884 struct v4l2_format
*f
)
888 ret
= vidioc_try_fmt_vid_cap(file
, priv
, f
);
892 return vidioc_s_fmt(file2ctx(file
), f
);
895 static int vidioc_s_fmt_vid_out(struct file
*file
, void *priv
,
896 struct v4l2_format
*f
)
898 struct vim2m_ctx
*ctx
= file2ctx(file
);
901 ret
= vidioc_try_fmt_vid_out(file
, priv
, f
);
905 ret
= vidioc_s_fmt(file2ctx(file
), f
);
907 ctx
->colorspace
= f
->fmt
.pix
.colorspace
;
908 ctx
->xfer_func
= f
->fmt
.pix
.xfer_func
;
909 ctx
->ycbcr_enc
= f
->fmt
.pix
.ycbcr_enc
;
910 ctx
->quant
= f
->fmt
.pix
.quantization
;
915 static int vim2m_s_ctrl(struct v4l2_ctrl
*ctrl
)
917 struct vim2m_ctx
*ctx
=
918 container_of(ctrl
->handler
, struct vim2m_ctx
, hdl
);
923 ctx
->mode
|= MEM2MEM_HFLIP
;
925 ctx
->mode
&= ~MEM2MEM_HFLIP
;
930 ctx
->mode
|= MEM2MEM_VFLIP
;
932 ctx
->mode
&= ~MEM2MEM_VFLIP
;
935 case V4L2_CID_TRANS_TIME_MSEC
:
936 ctx
->transtime
= ctrl
->val
;
937 if (ctx
->transtime
< 1)
941 case V4L2_CID_TRANS_NUM_BUFS
:
942 ctx
->translen
= ctrl
->val
;
946 v4l2_err(&ctx
->dev
->v4l2_dev
, "Invalid control\n");
953 static const struct v4l2_ctrl_ops vim2m_ctrl_ops
= {
954 .s_ctrl
= vim2m_s_ctrl
,
957 static const struct v4l2_ioctl_ops vim2m_ioctl_ops
= {
958 .vidioc_querycap
= vidioc_querycap
,
960 .vidioc_enum_fmt_vid_cap
= vidioc_enum_fmt_vid_cap
,
961 .vidioc_enum_framesizes
= vidioc_enum_framesizes
,
962 .vidioc_g_fmt_vid_cap
= vidioc_g_fmt_vid_cap
,
963 .vidioc_try_fmt_vid_cap
= vidioc_try_fmt_vid_cap
,
964 .vidioc_s_fmt_vid_cap
= vidioc_s_fmt_vid_cap
,
966 .vidioc_enum_fmt_vid_out
= vidioc_enum_fmt_vid_out
,
967 .vidioc_g_fmt_vid_out
= vidioc_g_fmt_vid_out
,
968 .vidioc_try_fmt_vid_out
= vidioc_try_fmt_vid_out
,
969 .vidioc_s_fmt_vid_out
= vidioc_s_fmt_vid_out
,
971 .vidioc_reqbufs
= v4l2_m2m_ioctl_reqbufs
,
972 .vidioc_querybuf
= v4l2_m2m_ioctl_querybuf
,
973 .vidioc_qbuf
= v4l2_m2m_ioctl_qbuf
,
974 .vidioc_dqbuf
= v4l2_m2m_ioctl_dqbuf
,
975 .vidioc_prepare_buf
= v4l2_m2m_ioctl_prepare_buf
,
976 .vidioc_create_bufs
= v4l2_m2m_ioctl_create_bufs
,
977 .vidioc_expbuf
= v4l2_m2m_ioctl_expbuf
,
979 .vidioc_streamon
= v4l2_m2m_ioctl_streamon
,
980 .vidioc_streamoff
= v4l2_m2m_ioctl_streamoff
,
982 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
983 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
990 static int vim2m_queue_setup(struct vb2_queue
*vq
,
991 unsigned int *nbuffers
,
992 unsigned int *nplanes
,
993 unsigned int sizes
[],
994 struct device
*alloc_devs
[])
996 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(vq
);
997 struct vim2m_q_data
*q_data
;
998 unsigned int size
, count
= *nbuffers
;
1000 q_data
= get_q_data(ctx
, vq
->type
);
1004 size
= q_data
->width
* q_data
->height
* q_data
->fmt
->depth
>> 3;
1006 while (size
* count
> MEM2MEM_VID_MEM_LIMIT
)
1011 return sizes
[0] < size
? -EINVAL
: 0;
1016 dprintk(ctx
->dev
, 1, "%s: get %d buffer(s) of size %d each.\n",
1017 type_name(vq
->type
), count
, size
);
1022 static int vim2m_buf_out_validate(struct vb2_buffer
*vb
)
1024 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1025 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1027 if (vbuf
->field
== V4L2_FIELD_ANY
)
1028 vbuf
->field
= V4L2_FIELD_NONE
;
1029 if (vbuf
->field
!= V4L2_FIELD_NONE
) {
1030 dprintk(ctx
->dev
, 1, "%s field isn't supported\n", __func__
);
1037 static int vim2m_buf_prepare(struct vb2_buffer
*vb
)
1039 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1040 struct vim2m_q_data
*q_data
;
1042 dprintk(ctx
->dev
, 2, "type: %s\n", type_name(vb
->vb2_queue
->type
));
1044 q_data
= get_q_data(ctx
, vb
->vb2_queue
->type
);
1047 if (vb2_plane_size(vb
, 0) < q_data
->sizeimage
) {
1048 dprintk(ctx
->dev
, 1,
1049 "%s data will not fit into plane (%lu < %lu)\n",
1050 __func__
, vb2_plane_size(vb
, 0),
1051 (long)q_data
->sizeimage
);
1055 vb2_set_plane_payload(vb
, 0, q_data
->sizeimage
);
1060 static void vim2m_buf_queue(struct vb2_buffer
*vb
)
1062 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1063 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1065 v4l2_m2m_buf_queue(ctx
->fh
.m2m_ctx
, vbuf
);
1068 static int vim2m_start_streaming(struct vb2_queue
*q
, unsigned int count
)
1070 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(q
);
1071 struct vim2m_q_data
*q_data
= get_q_data(ctx
, q
->type
);
1076 if (V4L2_TYPE_IS_OUTPUT(q
->type
))
1079 q_data
->sequence
= 0;
1083 static void vim2m_stop_streaming(struct vb2_queue
*q
)
1085 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(q
);
1086 struct vb2_v4l2_buffer
*vbuf
;
1087 unsigned long flags
;
1089 cancel_delayed_work_sync(&ctx
->work_run
);
1092 if (V4L2_TYPE_IS_OUTPUT(q
->type
))
1093 vbuf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
1095 vbuf
= v4l2_m2m_dst_buf_remove(ctx
->fh
.m2m_ctx
);
1098 v4l2_ctrl_request_complete(vbuf
->vb2_buf
.req_obj
.req
,
1100 spin_lock_irqsave(&ctx
->irqlock
, flags
);
1101 v4l2_m2m_buf_done(vbuf
, VB2_BUF_STATE_ERROR
);
1102 spin_unlock_irqrestore(&ctx
->irqlock
, flags
);
1106 static void vim2m_buf_request_complete(struct vb2_buffer
*vb
)
1108 struct vim2m_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1110 v4l2_ctrl_request_complete(vb
->req_obj
.req
, &ctx
->hdl
);
1113 static const struct vb2_ops vim2m_qops
= {
1114 .queue_setup
= vim2m_queue_setup
,
1115 .buf_out_validate
= vim2m_buf_out_validate
,
1116 .buf_prepare
= vim2m_buf_prepare
,
1117 .buf_queue
= vim2m_buf_queue
,
1118 .start_streaming
= vim2m_start_streaming
,
1119 .stop_streaming
= vim2m_stop_streaming
,
1120 .wait_prepare
= vb2_ops_wait_prepare
,
1121 .wait_finish
= vb2_ops_wait_finish
,
1122 .buf_request_complete
= vim2m_buf_request_complete
,
1125 static int queue_init(void *priv
, struct vb2_queue
*src_vq
,
1126 struct vb2_queue
*dst_vq
)
1128 struct vim2m_ctx
*ctx
= priv
;
1131 src_vq
->type
= V4L2_BUF_TYPE_VIDEO_OUTPUT
;
1132 src_vq
->io_modes
= VB2_MMAP
| VB2_USERPTR
| VB2_DMABUF
;
1133 src_vq
->drv_priv
= ctx
;
1134 src_vq
->buf_struct_size
= sizeof(struct v4l2_m2m_buffer
);
1135 src_vq
->ops
= &vim2m_qops
;
1136 src_vq
->mem_ops
= &vb2_vmalloc_memops
;
1137 src_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1138 src_vq
->lock
= &ctx
->vb_mutex
;
1139 src_vq
->supports_requests
= true;
1141 ret
= vb2_queue_init(src_vq
);
1145 dst_vq
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1146 dst_vq
->io_modes
= VB2_MMAP
| VB2_USERPTR
| VB2_DMABUF
;
1147 dst_vq
->drv_priv
= ctx
;
1148 dst_vq
->buf_struct_size
= sizeof(struct v4l2_m2m_buffer
);
1149 dst_vq
->ops
= &vim2m_qops
;
1150 dst_vq
->mem_ops
= &vb2_vmalloc_memops
;
1151 dst_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1152 dst_vq
->lock
= &ctx
->vb_mutex
;
1154 return vb2_queue_init(dst_vq
);
1157 static struct v4l2_ctrl_config vim2m_ctrl_trans_time_msec
= {
1158 .ops
= &vim2m_ctrl_ops
,
1159 .id
= V4L2_CID_TRANS_TIME_MSEC
,
1160 .name
= "Transaction Time (msec)",
1161 .type
= V4L2_CTRL_TYPE_INTEGER
,
1167 static const struct v4l2_ctrl_config vim2m_ctrl_trans_num_bufs
= {
1168 .ops
= &vim2m_ctrl_ops
,
1169 .id
= V4L2_CID_TRANS_NUM_BUFS
,
1170 .name
= "Buffers Per Transaction",
1171 .type
= V4L2_CTRL_TYPE_INTEGER
,
1174 .max
= MEM2MEM_DEF_NUM_BUFS
,
1181 static int vim2m_open(struct file
*file
)
1183 struct vim2m_dev
*dev
= video_drvdata(file
);
1184 struct vim2m_ctx
*ctx
= NULL
;
1185 struct v4l2_ctrl_handler
*hdl
;
1188 if (mutex_lock_interruptible(&dev
->dev_mutex
))
1189 return -ERESTARTSYS
;
1190 ctx
= kzalloc(sizeof(*ctx
), GFP_KERNEL
);
1196 v4l2_fh_init(&ctx
->fh
, video_devdata(file
));
1197 file
->private_data
= &ctx
->fh
;
1200 v4l2_ctrl_handler_init(hdl
, 4);
1201 v4l2_ctrl_new_std(hdl
, &vim2m_ctrl_ops
, V4L2_CID_HFLIP
, 0, 1, 1, 0);
1202 v4l2_ctrl_new_std(hdl
, &vim2m_ctrl_ops
, V4L2_CID_VFLIP
, 0, 1, 1, 0);
1204 vim2m_ctrl_trans_time_msec
.def
= default_transtime
;
1205 v4l2_ctrl_new_custom(hdl
, &vim2m_ctrl_trans_time_msec
, NULL
);
1206 v4l2_ctrl_new_custom(hdl
, &vim2m_ctrl_trans_num_bufs
, NULL
);
1209 v4l2_ctrl_handler_free(hdl
);
1213 ctx
->fh
.ctrl_handler
= hdl
;
1214 v4l2_ctrl_handler_setup(hdl
);
1216 ctx
->q_data
[V4L2_M2M_SRC
].fmt
= &formats
[0];
1217 ctx
->q_data
[V4L2_M2M_SRC
].width
= 640;
1218 ctx
->q_data
[V4L2_M2M_SRC
].height
= 480;
1219 ctx
->q_data
[V4L2_M2M_SRC
].sizeimage
=
1220 ctx
->q_data
[V4L2_M2M_SRC
].width
*
1221 ctx
->q_data
[V4L2_M2M_SRC
].height
*
1222 (ctx
->q_data
[V4L2_M2M_SRC
].fmt
->depth
>> 3);
1223 ctx
->q_data
[V4L2_M2M_DST
] = ctx
->q_data
[V4L2_M2M_SRC
];
1224 ctx
->colorspace
= V4L2_COLORSPACE_REC709
;
1226 ctx
->fh
.m2m_ctx
= v4l2_m2m_ctx_init(dev
->m2m_dev
, ctx
, &queue_init
);
1228 mutex_init(&ctx
->vb_mutex
);
1229 spin_lock_init(&ctx
->irqlock
);
1230 INIT_DELAYED_WORK(&ctx
->work_run
, device_work
);
1232 if (IS_ERR(ctx
->fh
.m2m_ctx
)) {
1233 rc
= PTR_ERR(ctx
->fh
.m2m_ctx
);
1235 v4l2_ctrl_handler_free(hdl
);
1236 v4l2_fh_exit(&ctx
->fh
);
1241 v4l2_fh_add(&ctx
->fh
);
1242 atomic_inc(&dev
->num_inst
);
1244 dprintk(dev
, 1, "Created instance: %p, m2m_ctx: %p\n",
1245 ctx
, ctx
->fh
.m2m_ctx
);
1248 mutex_unlock(&dev
->dev_mutex
);
1252 static int vim2m_release(struct file
*file
)
1254 struct vim2m_dev
*dev
= video_drvdata(file
);
1255 struct vim2m_ctx
*ctx
= file2ctx(file
);
1257 dprintk(dev
, 1, "Releasing instance %p\n", ctx
);
1259 v4l2_fh_del(&ctx
->fh
);
1260 v4l2_fh_exit(&ctx
->fh
);
1261 v4l2_ctrl_handler_free(&ctx
->hdl
);
1262 mutex_lock(&dev
->dev_mutex
);
1263 v4l2_m2m_ctx_release(ctx
->fh
.m2m_ctx
);
1264 mutex_unlock(&dev
->dev_mutex
);
1267 atomic_dec(&dev
->num_inst
);
1272 static void vim2m_device_release(struct video_device
*vdev
)
1274 struct vim2m_dev
*dev
= container_of(vdev
, struct vim2m_dev
, vfd
);
1276 v4l2_device_unregister(&dev
->v4l2_dev
);
1277 v4l2_m2m_release(dev
->m2m_dev
);
1278 #ifdef CONFIG_MEDIA_CONTROLLER
1279 media_device_cleanup(&dev
->mdev
);
1284 static const struct v4l2_file_operations vim2m_fops
= {
1285 .owner
= THIS_MODULE
,
1287 .release
= vim2m_release
,
1288 .poll
= v4l2_m2m_fop_poll
,
1289 .unlocked_ioctl
= video_ioctl2
,
1290 .mmap
= v4l2_m2m_fop_mmap
,
1293 static const struct video_device vim2m_videodev
= {
1294 .name
= MEM2MEM_NAME
,
1295 .vfl_dir
= VFL_DIR_M2M
,
1296 .fops
= &vim2m_fops
,
1297 .ioctl_ops
= &vim2m_ioctl_ops
,
1299 .release
= vim2m_device_release
,
1300 .device_caps
= V4L2_CAP_VIDEO_M2M
| V4L2_CAP_STREAMING
,
1303 static const struct v4l2_m2m_ops m2m_ops
= {
1304 .device_run
= device_run
,
1305 .job_ready
= job_ready
,
1306 .job_abort
= job_abort
,
1309 static const struct media_device_ops m2m_media_ops
= {
1310 .req_validate
= vb2_request_validate
,
1311 .req_queue
= v4l2_m2m_request_queue
,
1314 static int vim2m_probe(struct platform_device
*pdev
)
1316 struct vim2m_dev
*dev
;
1317 struct video_device
*vfd
;
1320 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
1324 ret
= v4l2_device_register(&pdev
->dev
, &dev
->v4l2_dev
);
1328 atomic_set(&dev
->num_inst
, 0);
1329 mutex_init(&dev
->dev_mutex
);
1331 dev
->vfd
= vim2m_videodev
;
1333 vfd
->lock
= &dev
->dev_mutex
;
1334 vfd
->v4l2_dev
= &dev
->v4l2_dev
;
1336 ret
= video_register_device(vfd
, VFL_TYPE_GRABBER
, 0);
1338 v4l2_err(&dev
->v4l2_dev
, "Failed to register video device\n");
1342 video_set_drvdata(vfd
, dev
);
1343 v4l2_info(&dev
->v4l2_dev
,
1344 "Device registered as /dev/video%d\n", vfd
->num
);
1346 platform_set_drvdata(pdev
, dev
);
1348 dev
->m2m_dev
= v4l2_m2m_init(&m2m_ops
);
1349 if (IS_ERR(dev
->m2m_dev
)) {
1350 v4l2_err(&dev
->v4l2_dev
, "Failed to init mem2mem device\n");
1351 ret
= PTR_ERR(dev
->m2m_dev
);
1352 dev
->m2m_dev
= NULL
;
1356 #ifdef CONFIG_MEDIA_CONTROLLER
1357 dev
->mdev
.dev
= &pdev
->dev
;
1358 strscpy(dev
->mdev
.model
, "vim2m", sizeof(dev
->mdev
.model
));
1359 strscpy(dev
->mdev
.bus_info
, "platform:vim2m",
1360 sizeof(dev
->mdev
.bus_info
));
1361 media_device_init(&dev
->mdev
);
1362 dev
->mdev
.ops
= &m2m_media_ops
;
1363 dev
->v4l2_dev
.mdev
= &dev
->mdev
;
1365 ret
= v4l2_m2m_register_media_controller(dev
->m2m_dev
, vfd
,
1366 MEDIA_ENT_F_PROC_VIDEO_SCALER
);
1368 v4l2_err(&dev
->v4l2_dev
, "Failed to init mem2mem media controller\n");
1372 ret
= media_device_register(&dev
->mdev
);
1374 v4l2_err(&dev
->v4l2_dev
, "Failed to register mem2mem media device\n");
1380 #ifdef CONFIG_MEDIA_CONTROLLER
1382 v4l2_m2m_unregister_media_controller(dev
->m2m_dev
);
1385 video_unregister_device(&dev
->vfd
);
1386 /* vim2m_device_release called by video_unregister_device to release various objects */
1389 v4l2_device_unregister(&dev
->v4l2_dev
);
1396 static int vim2m_remove(struct platform_device
*pdev
)
1398 struct vim2m_dev
*dev
= platform_get_drvdata(pdev
);
1400 v4l2_info(&dev
->v4l2_dev
, "Removing " MEM2MEM_NAME
);
1402 #ifdef CONFIG_MEDIA_CONTROLLER
1403 media_device_unregister(&dev
->mdev
);
1404 v4l2_m2m_unregister_media_controller(dev
->m2m_dev
);
1406 video_unregister_device(&dev
->vfd
);
1411 static struct platform_driver vim2m_pdrv
= {
1412 .probe
= vim2m_probe
,
1413 .remove
= vim2m_remove
,
1415 .name
= MEM2MEM_NAME
,
1419 static void __exit
vim2m_exit(void)
1421 platform_driver_unregister(&vim2m_pdrv
);
1422 platform_device_unregister(&vim2m_pdev
);
1425 static int __init
vim2m_init(void)
1429 ret
= platform_device_register(&vim2m_pdev
);
1433 ret
= platform_driver_register(&vim2m_pdrv
);
1435 platform_device_unregister(&vim2m_pdev
);
1440 module_init(vim2m_init
);
1441 module_exit(vim2m_exit
);