1 // SPDX-License-Identifier: GPL-2.0-only
3 * A virtual codec example device.
5 * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
7 * This is a virtual codec device driver for testing the codec framework.
8 * It simulates a device that uses memory buffers for both source and
9 * destination and encodes or decodes the data.
12 #include <linux/module.h>
13 #include <linux/delay.h>
15 #include <linux/sched.h>
16 #include <linux/slab.h>
18 #include <linux/platform_device.h>
19 #include <media/v4l2-mem2mem.h>
20 #include <media/v4l2-device.h>
21 #include <media/v4l2-ioctl.h>
22 #include <media/v4l2-ctrls.h>
23 #include <media/v4l2-event.h>
24 #include <media/videobuf2-vmalloc.h>
26 #include "vicodec-codec.h"
28 MODULE_DESCRIPTION("Virtual codec device");
29 MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
30 MODULE_LICENSE("GPL v2");
32 static bool multiplanar
;
33 module_param(multiplanar
, bool, 0444);
34 MODULE_PARM_DESC(multiplanar
,
35 " use multi-planar API instead of single-planar API");
37 static unsigned int debug
;
38 module_param(debug
, uint
, 0644);
39 MODULE_PARM_DESC(debug
, " activates debug info");
41 #define VICODEC_NAME "vicodec"
42 #define MAX_WIDTH 4096U
43 #define MIN_WIDTH 640U
44 #define MAX_HEIGHT 2160U
45 #define MIN_HEIGHT 480U
47 #define dprintk(dev, fmt, arg...) \
48 v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
51 static void vicodec_dev_release(struct device
*dev
)
55 static struct platform_device vicodec_pdev
= {
57 .dev
.release
= vicodec_dev_release
,
60 /* Per-queue, driver-specific private data */
61 struct vicodec_q_data
{
65 unsigned int sizeimage
;
66 unsigned int sequence
;
76 struct v4l2_device v4l2_dev
;
77 struct video_device enc_vfd
;
78 struct video_device dec_vfd
;
79 #ifdef CONFIG_MEDIA_CONTROLLER
80 struct media_device mdev
;
83 struct mutex enc_mutex
;
84 struct mutex dec_mutex
;
88 struct v4l2_m2m_dev
*enc_dev
;
89 struct v4l2_m2m_dev
*dec_dev
;
94 struct vicodec_dev
*dev
;
98 struct v4l2_ctrl_handler hdl
;
99 struct v4l2_ctrl
*ctrl_gop_size
;
100 unsigned int gop_size
;
101 unsigned int gop_cnt
;
103 /* Abort requested by m2m */
105 struct vb2_v4l2_buffer
*last_src_buf
;
106 struct vb2_v4l2_buffer
*last_dst_buf
;
108 enum v4l2_colorspace colorspace
;
109 enum v4l2_ycbcr_encoding ycbcr_enc
;
110 enum v4l2_xfer_func xfer_func
;
111 enum v4l2_quantization quantization
;
113 /* Source and destination queue data */
114 struct vicodec_q_data q_data
[2];
115 struct raw_frame ref_frame
;
116 u8
*compressed_frame
;
123 bool comp_has_next_frame
;
126 static const u32 pixfmts_yuv
[] = {
133 static inline struct vicodec_ctx
*file2ctx(struct file
*file
)
135 return container_of(file
->private_data
, struct vicodec_ctx
, fh
);
138 static struct vicodec_q_data
*get_q_data(struct vicodec_ctx
*ctx
,
139 enum v4l2_buf_type type
)
142 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
143 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
144 return &ctx
->q_data
[V4L2_M2M_SRC
];
145 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
146 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
147 return &ctx
->q_data
[V4L2_M2M_DST
];
155 static void encode(struct vicodec_ctx
*ctx
,
156 struct vicodec_q_data
*q_data
,
159 unsigned int size
= q_data
->width
* q_data
->height
;
160 struct cframe_hdr
*p_hdr
;
165 rf
.width
= q_data
->width
;
166 rf
.height
= q_data
->height
;
169 switch (q_data
->fourcc
) {
170 case V4L2_PIX_FMT_YUV420
:
171 rf
.cb
= rf
.luma
+ size
;
172 rf
.cr
= rf
.cb
+ size
/ 4;
175 case V4L2_PIX_FMT_YVU420
:
176 rf
.cr
= rf
.luma
+ size
;
177 rf
.cb
= rf
.cr
+ size
/ 4;
180 case V4L2_PIX_FMT_NV12
:
181 rf
.cb
= rf
.luma
+ size
;
185 case V4L2_PIX_FMT_NV21
:
186 rf
.cr
= rf
.luma
+ size
;
192 cf
.width
= q_data
->width
;
193 cf
.height
= q_data
->height
;
194 cf
.rlc_data
= (__be16
*)(p_out
+ sizeof(*p_hdr
));
196 encoding
= encode_frame(&rf
, &ctx
->ref_frame
, &cf
, !ctx
->gop_cnt
,
197 ctx
->gop_cnt
== ctx
->gop_size
- 1);
198 if (encoding
!= FRAME_PCODED
)
200 if (++ctx
->gop_cnt
== ctx
->gop_size
)
203 p_hdr
= (struct cframe_hdr
*)p_out
;
204 p_hdr
->magic1
= VICODEC_MAGIC1
;
205 p_hdr
->magic2
= VICODEC_MAGIC2
;
206 p_hdr
->version
= htonl(VICODEC_VERSION
);
207 p_hdr
->width
= htonl(cf
.width
);
208 p_hdr
->height
= htonl(cf
.height
);
209 p_hdr
->flags
= htonl(q_data
->flags
);
210 if (encoding
& LUMA_UNENCODED
)
211 p_hdr
->flags
|= htonl(VICODEC_FL_LUMA_IS_UNCOMPRESSED
);
212 if (encoding
& CB_UNENCODED
)
213 p_hdr
->flags
|= htonl(VICODEC_FL_CB_IS_UNCOMPRESSED
);
214 if (encoding
& CR_UNENCODED
)
215 p_hdr
->flags
|= htonl(VICODEC_FL_CR_IS_UNCOMPRESSED
);
216 p_hdr
->colorspace
= htonl(ctx
->colorspace
);
217 p_hdr
->xfer_func
= htonl(ctx
->xfer_func
);
218 p_hdr
->ycbcr_enc
= htonl(ctx
->ycbcr_enc
);
219 p_hdr
->quantization
= htonl(ctx
->quantization
);
220 p_hdr
->size
= htonl(cf
.size
);
221 ctx
->ref_frame
.width
= cf
.width
;
222 ctx
->ref_frame
.height
= cf
.height
;
225 static int decode(struct vicodec_ctx
*ctx
,
226 struct vicodec_q_data
*q_data
,
229 unsigned int size
= q_data
->width
* q_data
->height
;
231 struct cframe_hdr
*p_hdr
;
235 p_hdr
= (struct cframe_hdr
*)p_in
;
236 cf
.width
= ntohl(p_hdr
->width
);
237 cf
.height
= ntohl(p_hdr
->height
);
238 q_data
->flags
= ntohl(p_hdr
->flags
);
239 ctx
->colorspace
= ntohl(p_hdr
->colorspace
);
240 ctx
->xfer_func
= ntohl(p_hdr
->xfer_func
);
241 ctx
->ycbcr_enc
= ntohl(p_hdr
->ycbcr_enc
);
242 ctx
->quantization
= ntohl(p_hdr
->quantization
);
243 cf
.rlc_data
= (__be16
*)(p_in
+ sizeof(*p_hdr
));
245 if (p_hdr
->magic1
!= VICODEC_MAGIC1
||
246 p_hdr
->magic2
!= VICODEC_MAGIC2
||
247 ntohl(p_hdr
->version
) != VICODEC_VERSION
||
248 cf
.width
< VICODEC_MIN_WIDTH
||
249 cf
.width
> VICODEC_MAX_WIDTH
||
250 cf
.height
< VICODEC_MIN_HEIGHT
||
251 cf
.height
> VICODEC_MAX_HEIGHT
||
252 (cf
.width
& 7) || (cf
.height
& 7))
255 /* TODO: support resolution changes */
256 if (cf
.width
!= q_data
->width
|| cf
.height
!= q_data
->height
)
259 decode_frame(&cf
, &ctx
->ref_frame
, q_data
->flags
);
260 memcpy(p_out
, ctx
->ref_frame
.luma
, size
);
263 switch (q_data
->fourcc
) {
264 case V4L2_PIX_FMT_YUV420
:
265 memcpy(p_out
, ctx
->ref_frame
.cb
, size
/ 4);
267 memcpy(p_out
, ctx
->ref_frame
.cr
, size
/ 4);
269 case V4L2_PIX_FMT_YVU420
:
270 memcpy(p_out
, ctx
->ref_frame
.cr
, size
/ 4);
272 memcpy(p_out
, ctx
->ref_frame
.cb
, size
/ 4);
274 case V4L2_PIX_FMT_NV12
:
275 for (i
= 0, p
= p_out
; i
< size
/ 4; i
++, p
+= 2)
276 *p
= ctx
->ref_frame
.cb
[i
];
277 for (i
= 0, p
= p_out
+ 1; i
< size
/ 4; i
++, p
+= 2)
278 *p
= ctx
->ref_frame
.cr
[i
];
280 case V4L2_PIX_FMT_NV21
:
281 for (i
= 0, p
= p_out
; i
< size
/ 4; i
++, p
+= 2)
282 *p
= ctx
->ref_frame
.cr
[i
];
283 for (i
= 0, p
= p_out
+ 1; i
< size
/ 4; i
++, p
+= 2)
284 *p
= ctx
->ref_frame
.cb
[i
];
290 static int device_process(struct vicodec_ctx
*ctx
,
291 struct vb2_v4l2_buffer
*in_vb
,
292 struct vb2_v4l2_buffer
*out_vb
)
294 struct vicodec_dev
*dev
= ctx
->dev
;
295 struct vicodec_q_data
*q_out
, *q_cap
;
299 q_out
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_OUTPUT
);
300 q_cap
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_CAPTURE
);
302 p_in
= vb2_plane_vaddr(&in_vb
->vb2_buf
, 0);
304 p_in
= ctx
->compressed_frame
;
305 p_out
= vb2_plane_vaddr(&out_vb
->vb2_buf
, 0);
306 if (!p_in
|| !p_out
) {
307 v4l2_err(&dev
->v4l2_dev
,
308 "Acquiring kernel pointers to buffers failed\n");
313 struct cframe_hdr
*p_hdr
= (struct cframe_hdr
*)p_out
;
315 encode(ctx
, q_out
, p_in
, p_out
);
316 vb2_set_plane_payload(&out_vb
->vb2_buf
, 0,
317 sizeof(*p_hdr
) + ntohl(p_hdr
->size
));
319 ret
= decode(ctx
, q_cap
, p_in
, p_out
);
322 vb2_set_plane_payload(&out_vb
->vb2_buf
, 0,
323 q_cap
->width
* q_cap
->height
* 3 / 2);
326 out_vb
->sequence
= q_cap
->sequence
++;
327 out_vb
->vb2_buf
.timestamp
= in_vb
->vb2_buf
.timestamp
;
329 if (in_vb
->flags
& V4L2_BUF_FLAG_TIMECODE
)
330 out_vb
->timecode
= in_vb
->timecode
;
331 out_vb
->field
= in_vb
->field
;
332 out_vb
->flags
&= ~V4L2_BUF_FLAG_LAST
;
333 out_vb
->flags
|= in_vb
->flags
&
334 (V4L2_BUF_FLAG_TIMECODE
|
335 V4L2_BUF_FLAG_KEYFRAME
|
336 V4L2_BUF_FLAG_PFRAME
|
337 V4L2_BUF_FLAG_BFRAME
|
338 V4L2_BUF_FLAG_TSTAMP_SRC_MASK
);
347 /* device_run() - prepares and starts the device */
348 static void device_run(void *priv
)
350 static const struct v4l2_event eos_event
= {
351 .type
= V4L2_EVENT_EOS
353 struct vicodec_ctx
*ctx
= priv
;
354 struct vicodec_dev
*dev
= ctx
->dev
;
355 struct vb2_v4l2_buffer
*src_buf
, *dst_buf
;
356 struct vicodec_q_data
*q_out
;
359 src_buf
= v4l2_m2m_next_src_buf(ctx
->fh
.m2m_ctx
);
360 dst_buf
= v4l2_m2m_dst_buf_remove(ctx
->fh
.m2m_ctx
);
361 q_out
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_OUTPUT
);
363 state
= VB2_BUF_STATE_DONE
;
364 if (device_process(ctx
, src_buf
, dst_buf
))
365 state
= VB2_BUF_STATE_ERROR
;
366 ctx
->last_dst_buf
= dst_buf
;
368 spin_lock(ctx
->lock
);
369 if (!ctx
->comp_has_next_frame
&& src_buf
== ctx
->last_src_buf
) {
370 dst_buf
->flags
|= V4L2_BUF_FLAG_LAST
;
371 v4l2_event_queue_fh(&ctx
->fh
, &eos_event
);
374 src_buf
->sequence
= q_out
->sequence
++;
375 src_buf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
376 v4l2_m2m_buf_done(src_buf
, state
);
377 } else if (vb2_get_plane_payload(&src_buf
->vb2_buf
, 0) == ctx
->cur_buf_offset
) {
378 src_buf
->sequence
= q_out
->sequence
++;
379 src_buf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
380 v4l2_m2m_buf_done(src_buf
, state
);
381 ctx
->cur_buf_offset
= 0;
382 ctx
->comp_has_next_frame
= false;
384 v4l2_m2m_buf_done(dst_buf
, state
);
386 ctx
->comp_magic_cnt
= 0;
387 ctx
->comp_has_frame
= false;
388 spin_unlock(ctx
->lock
);
391 v4l2_m2m_job_finish(dev
->enc_dev
, ctx
->fh
.m2m_ctx
);
393 v4l2_m2m_job_finish(dev
->dec_dev
, ctx
->fh
.m2m_ctx
);
396 static void job_remove_out_buf(struct vicodec_ctx
*ctx
, u32 state
)
398 struct vb2_v4l2_buffer
*src_buf
;
399 struct vicodec_q_data
*q_out
;
401 q_out
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_OUTPUT
);
402 spin_lock(ctx
->lock
);
403 src_buf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
404 src_buf
->sequence
= q_out
->sequence
++;
405 v4l2_m2m_buf_done(src_buf
, state
);
406 ctx
->cur_buf_offset
= 0;
407 spin_unlock(ctx
->lock
);
410 static int job_ready(void *priv
)
412 static const u8 magic
[] = {
413 0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
415 struct vicodec_ctx
*ctx
= priv
;
416 struct vb2_v4l2_buffer
*src_buf
;
422 if (ctx
->is_enc
|| ctx
->comp_has_frame
)
426 ctx
->comp_has_next_frame
= false;
427 src_buf
= v4l2_m2m_next_src_buf(ctx
->fh
.m2m_ctx
);
430 p_out
= vb2_plane_vaddr(&src_buf
->vb2_buf
, 0);
431 sz
= vb2_get_plane_payload(&src_buf
->vb2_buf
, 0);
432 p
= p_out
+ ctx
->cur_buf_offset
;
434 state
= VB2_BUF_STATE_DONE
;
436 if (!ctx
->comp_size
) {
437 state
= VB2_BUF_STATE_ERROR
;
438 for (; p
< p_out
+ sz
; p
++) {
441 p
= memchr(p
, magic
[ctx
->comp_magic_cnt
], sz
);
443 ctx
->comp_magic_cnt
= 0;
446 copy
= sizeof(magic
) - ctx
->comp_magic_cnt
;
447 if (p_out
+ sz
- p
< copy
)
448 copy
= p_out
+ sz
- p
;
449 memcpy(ctx
->compressed_frame
+ ctx
->comp_magic_cnt
,
451 ctx
->comp_magic_cnt
+= copy
;
452 if (!memcmp(ctx
->compressed_frame
, magic
, ctx
->comp_magic_cnt
)) {
454 state
= VB2_BUF_STATE_DONE
;
457 ctx
->comp_magic_cnt
= 0;
459 if (ctx
->comp_magic_cnt
< sizeof(magic
)) {
460 job_remove_out_buf(ctx
, state
);
463 ctx
->comp_size
= sizeof(magic
);
465 if (ctx
->comp_size
< sizeof(struct cframe_hdr
)) {
466 struct cframe_hdr
*p_hdr
= (struct cframe_hdr
*)ctx
->compressed_frame
;
467 u32 copy
= sizeof(struct cframe_hdr
) - ctx
->comp_size
;
469 if (copy
> p_out
+ sz
- p
)
470 copy
= p_out
+ sz
- p
;
471 memcpy(ctx
->compressed_frame
+ ctx
->comp_size
,
474 ctx
->comp_size
+= copy
;
475 if (ctx
->comp_size
< sizeof(struct cframe_hdr
)) {
476 job_remove_out_buf(ctx
, state
);
479 ctx
->comp_frame_size
= ntohl(p_hdr
->size
) + sizeof(*p_hdr
);
480 if (ctx
->comp_frame_size
> ctx
->comp_max_size
)
481 ctx
->comp_frame_size
= ctx
->comp_max_size
;
483 if (ctx
->comp_size
< ctx
->comp_frame_size
) {
484 u32 copy
= ctx
->comp_frame_size
- ctx
->comp_size
;
486 if (copy
> p_out
+ sz
- p
)
487 copy
= p_out
+ sz
- p
;
488 memcpy(ctx
->compressed_frame
+ ctx
->comp_size
,
491 ctx
->comp_size
+= copy
;
492 if (ctx
->comp_size
< ctx
->comp_frame_size
) {
493 job_remove_out_buf(ctx
, state
);
497 ctx
->cur_buf_offset
= p
- p_out
;
498 ctx
->comp_has_frame
= true;
499 ctx
->comp_has_next_frame
= false;
500 if (sz
- ctx
->cur_buf_offset
>= sizeof(struct cframe_hdr
)) {
501 struct cframe_hdr
*p_hdr
= (struct cframe_hdr
*)p
;
502 u32 frame_size
= ntohl(p_hdr
->size
);
503 u32 remaining
= sz
- ctx
->cur_buf_offset
- sizeof(*p_hdr
);
505 if (!memcmp(p
, magic
, sizeof(magic
)))
506 ctx
->comp_has_next_frame
= remaining
>= frame_size
;
511 static void job_abort(void *priv
)
513 struct vicodec_ctx
*ctx
= priv
;
515 /* Will cancel the transaction in the next interrupt handler */
523 static u32
find_fmt(u32 fmt
)
527 for (i
= 0; i
< ARRAY_SIZE(pixfmts_yuv
); i
++)
528 if (pixfmts_yuv
[i
] == fmt
)
530 return pixfmts_yuv
[0];
533 static int vidioc_querycap(struct file
*file
, void *priv
,
534 struct v4l2_capability
*cap
)
536 strncpy(cap
->driver
, VICODEC_NAME
, sizeof(cap
->driver
) - 1);
537 strncpy(cap
->card
, VICODEC_NAME
, sizeof(cap
->card
) - 1);
538 snprintf(cap
->bus_info
, sizeof(cap
->bus_info
),
539 "platform:%s", VICODEC_NAME
);
540 cap
->device_caps
= V4L2_CAP_STREAMING
|
542 V4L2_CAP_VIDEO_M2M_MPLANE
:
544 cap
->capabilities
= cap
->device_caps
| V4L2_CAP_DEVICE_CAPS
;
548 static int enum_fmt(struct v4l2_fmtdesc
*f
, bool is_enc
, bool is_out
)
550 bool is_yuv
= (is_enc
&& is_out
) || (!is_enc
&& !is_out
);
552 if (V4L2_TYPE_IS_MULTIPLANAR(f
->type
) && !multiplanar
)
554 if (!V4L2_TYPE_IS_MULTIPLANAR(f
->type
) && multiplanar
)
556 if (f
->index
>= (is_yuv
? ARRAY_SIZE(pixfmts_yuv
) : 1))
560 f
->pixelformat
= pixfmts_yuv
[f
->index
];
562 f
->pixelformat
= V4L2_PIX_FMT_FWHT
;
566 static int vidioc_enum_fmt_vid_cap(struct file
*file
, void *priv
,
567 struct v4l2_fmtdesc
*f
)
569 struct vicodec_ctx
*ctx
= file2ctx(file
);
571 return enum_fmt(f
, ctx
->is_enc
, false);
574 static int vidioc_enum_fmt_vid_out(struct file
*file
, void *priv
,
575 struct v4l2_fmtdesc
*f
)
577 struct vicodec_ctx
*ctx
= file2ctx(file
);
579 return enum_fmt(f
, ctx
->is_enc
, true);
582 static int vidioc_g_fmt(struct vicodec_ctx
*ctx
, struct v4l2_format
*f
)
584 struct vb2_queue
*vq
;
585 struct vicodec_q_data
*q_data
;
586 struct v4l2_pix_format_mplane
*pix_mp
;
587 struct v4l2_pix_format
*pix
;
589 vq
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
, f
->type
);
593 q_data
= get_q_data(ctx
, f
->type
);
596 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
597 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
601 pix
->width
= q_data
->width
;
602 pix
->height
= q_data
->height
;
603 pix
->field
= V4L2_FIELD_NONE
;
604 pix
->pixelformat
= q_data
->fourcc
;
605 if (q_data
->fourcc
== V4L2_PIX_FMT_FWHT
)
606 pix
->bytesperline
= 0;
608 pix
->bytesperline
= q_data
->width
;
609 pix
->sizeimage
= q_data
->sizeimage
;
610 pix
->colorspace
= ctx
->colorspace
;
611 pix
->xfer_func
= ctx
->xfer_func
;
612 pix
->ycbcr_enc
= ctx
->ycbcr_enc
;
613 pix
->quantization
= ctx
->quantization
;
616 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
617 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
620 pix_mp
= &f
->fmt
.pix_mp
;
621 pix_mp
->width
= q_data
->width
;
622 pix_mp
->height
= q_data
->height
;
623 pix_mp
->field
= V4L2_FIELD_NONE
;
624 pix_mp
->pixelformat
= q_data
->fourcc
;
625 pix_mp
->num_planes
= 1;
626 if (q_data
->fourcc
== V4L2_PIX_FMT_FWHT
)
627 pix_mp
->plane_fmt
[0].bytesperline
= 0;
629 pix_mp
->plane_fmt
[0].bytesperline
= q_data
->width
;
630 pix_mp
->plane_fmt
[0].sizeimage
= q_data
->sizeimage
;
631 pix_mp
->colorspace
= ctx
->colorspace
;
632 pix_mp
->xfer_func
= ctx
->xfer_func
;
633 pix_mp
->ycbcr_enc
= ctx
->ycbcr_enc
;
634 pix_mp
->quantization
= ctx
->quantization
;
635 memset(pix_mp
->reserved
, 0, sizeof(pix_mp
->reserved
));
636 memset(pix_mp
->plane_fmt
[0].reserved
, 0,
637 sizeof(pix_mp
->plane_fmt
[0].reserved
));
645 static int vidioc_g_fmt_vid_out(struct file
*file
, void *priv
,
646 struct v4l2_format
*f
)
648 return vidioc_g_fmt(file2ctx(file
), f
);
651 static int vidioc_g_fmt_vid_cap(struct file
*file
, void *priv
,
652 struct v4l2_format
*f
)
654 return vidioc_g_fmt(file2ctx(file
), f
);
657 static int vidioc_try_fmt(struct vicodec_ctx
*ctx
, struct v4l2_format
*f
)
659 struct v4l2_pix_format_mplane
*pix_mp
;
660 struct v4l2_pix_format
*pix
;
663 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
664 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
666 pix
->width
= clamp(pix
->width
, MIN_WIDTH
, MAX_WIDTH
) & ~7;
667 pix
->height
= clamp(pix
->height
, MIN_HEIGHT
, MAX_HEIGHT
) & ~7;
668 pix
->bytesperline
= pix
->width
;
669 pix
->sizeimage
= pix
->width
* pix
->height
* 3 / 2;
670 pix
->field
= V4L2_FIELD_NONE
;
671 if (pix
->pixelformat
== V4L2_PIX_FMT_FWHT
) {
672 pix
->bytesperline
= 0;
673 pix
->sizeimage
+= sizeof(struct cframe_hdr
);
676 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
677 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
678 pix_mp
= &f
->fmt
.pix_mp
;
679 pix_mp
->width
= clamp(pix_mp
->width
, MIN_WIDTH
, MAX_WIDTH
) & ~7;
681 clamp(pix_mp
->height
, MIN_HEIGHT
, MAX_HEIGHT
) & ~7;
682 pix_mp
->plane_fmt
[0].bytesperline
= pix_mp
->width
;
683 pix_mp
->plane_fmt
[0].sizeimage
=
684 pix_mp
->width
* pix_mp
->height
* 3 / 2;
685 pix_mp
->field
= V4L2_FIELD_NONE
;
686 pix_mp
->num_planes
= 1;
687 if (pix_mp
->pixelformat
== V4L2_PIX_FMT_FWHT
) {
688 pix_mp
->plane_fmt
[0].bytesperline
= 0;
689 pix_mp
->plane_fmt
[0].sizeimage
+=
690 sizeof(struct cframe_hdr
);
692 memset(pix_mp
->reserved
, 0, sizeof(pix_mp
->reserved
));
693 memset(pix_mp
->plane_fmt
[0].reserved
, 0,
694 sizeof(pix_mp
->plane_fmt
[0].reserved
));
703 static int vidioc_try_fmt_vid_cap(struct file
*file
, void *priv
,
704 struct v4l2_format
*f
)
706 struct vicodec_ctx
*ctx
= file2ctx(file
);
707 struct v4l2_pix_format_mplane
*pix_mp
;
708 struct v4l2_pix_format
*pix
;
711 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
715 pix
->pixelformat
= ctx
->is_enc
? V4L2_PIX_FMT_FWHT
:
716 find_fmt(f
->fmt
.pix
.pixelformat
);
717 pix
->colorspace
= ctx
->colorspace
;
718 pix
->xfer_func
= ctx
->xfer_func
;
719 pix
->ycbcr_enc
= ctx
->ycbcr_enc
;
720 pix
->quantization
= ctx
->quantization
;
722 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
725 pix_mp
= &f
->fmt
.pix_mp
;
726 pix_mp
->pixelformat
= ctx
->is_enc
? V4L2_PIX_FMT_FWHT
:
727 find_fmt(pix_mp
->pixelformat
);
728 pix_mp
->colorspace
= ctx
->colorspace
;
729 pix_mp
->xfer_func
= ctx
->xfer_func
;
730 pix_mp
->ycbcr_enc
= ctx
->ycbcr_enc
;
731 pix_mp
->quantization
= ctx
->quantization
;
732 memset(pix_mp
->reserved
, 0, sizeof(pix_mp
->reserved
));
733 memset(pix_mp
->plane_fmt
[0].reserved
, 0,
734 sizeof(pix_mp
->plane_fmt
[0].reserved
));
740 return vidioc_try_fmt(ctx
, f
);
743 static int vidioc_try_fmt_vid_out(struct file
*file
, void *priv
,
744 struct v4l2_format
*f
)
746 struct vicodec_ctx
*ctx
= file2ctx(file
);
747 struct v4l2_pix_format_mplane
*pix_mp
;
748 struct v4l2_pix_format
*pix
;
751 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
755 pix
->pixelformat
= !ctx
->is_enc
? V4L2_PIX_FMT_FWHT
:
756 find_fmt(pix
->pixelformat
);
757 if (!pix
->colorspace
)
758 pix
->colorspace
= V4L2_COLORSPACE_REC709
;
760 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
763 pix_mp
= &f
->fmt
.pix_mp
;
764 pix_mp
->pixelformat
= !ctx
->is_enc
? V4L2_PIX_FMT_FWHT
:
765 find_fmt(pix_mp
->pixelformat
);
766 if (!pix_mp
->colorspace
)
767 pix_mp
->colorspace
= V4L2_COLORSPACE_REC709
;
773 return vidioc_try_fmt(ctx
, f
);
776 static int vidioc_s_fmt(struct vicodec_ctx
*ctx
, struct v4l2_format
*f
)
778 struct vicodec_q_data
*q_data
;
779 struct vb2_queue
*vq
;
780 bool fmt_changed
= true;
781 struct v4l2_pix_format_mplane
*pix_mp
;
782 struct v4l2_pix_format
*pix
;
784 vq
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
, f
->type
);
788 q_data
= get_q_data(ctx
, f
->type
);
793 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
794 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
796 if (ctx
->is_enc
&& V4L2_TYPE_IS_OUTPUT(f
->type
))
798 q_data
->fourcc
!= pix
->pixelformat
||
799 q_data
->width
!= pix
->width
||
800 q_data
->height
!= pix
->height
;
802 if (vb2_is_busy(vq
) && fmt_changed
)
805 q_data
->fourcc
= pix
->pixelformat
;
806 q_data
->width
= pix
->width
;
807 q_data
->height
= pix
->height
;
808 q_data
->sizeimage
= pix
->sizeimage
;
810 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
811 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
812 pix_mp
= &f
->fmt
.pix_mp
;
813 if (ctx
->is_enc
&& V4L2_TYPE_IS_OUTPUT(f
->type
))
815 q_data
->fourcc
!= pix_mp
->pixelformat
||
816 q_data
->width
!= pix_mp
->width
||
817 q_data
->height
!= pix_mp
->height
;
819 if (vb2_is_busy(vq
) && fmt_changed
)
822 q_data
->fourcc
= pix_mp
->pixelformat
;
823 q_data
->width
= pix_mp
->width
;
824 q_data
->height
= pix_mp
->height
;
825 q_data
->sizeimage
= pix_mp
->plane_fmt
[0].sizeimage
;
832 "Setting format for type %d, wxh: %dx%d, fourcc: %08x\n",
833 f
->type
, q_data
->width
, q_data
->height
, q_data
->fourcc
);
838 static int vidioc_s_fmt_vid_cap(struct file
*file
, void *priv
,
839 struct v4l2_format
*f
)
843 ret
= vidioc_try_fmt_vid_cap(file
, priv
, f
);
847 return vidioc_s_fmt(file2ctx(file
), f
);
850 static int vidioc_s_fmt_vid_out(struct file
*file
, void *priv
,
851 struct v4l2_format
*f
)
853 struct vicodec_ctx
*ctx
= file2ctx(file
);
854 struct v4l2_pix_format_mplane
*pix_mp
;
855 struct v4l2_pix_format
*pix
;
858 ret
= vidioc_try_fmt_vid_out(file
, priv
, f
);
862 ret
= vidioc_s_fmt(file2ctx(file
), f
);
865 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
866 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
868 ctx
->colorspace
= pix
->colorspace
;
869 ctx
->xfer_func
= pix
->xfer_func
;
870 ctx
->ycbcr_enc
= pix
->ycbcr_enc
;
871 ctx
->quantization
= pix
->quantization
;
873 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
874 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
875 pix_mp
= &f
->fmt
.pix_mp
;
876 ctx
->colorspace
= pix_mp
->colorspace
;
877 ctx
->xfer_func
= pix_mp
->xfer_func
;
878 ctx
->ycbcr_enc
= pix_mp
->ycbcr_enc
;
879 ctx
->quantization
= pix_mp
->quantization
;
888 static void vicodec_mark_last_buf(struct vicodec_ctx
*ctx
)
890 static const struct v4l2_event eos_event
= {
891 .type
= V4L2_EVENT_EOS
894 spin_lock(ctx
->lock
);
895 ctx
->last_src_buf
= v4l2_m2m_last_src_buf(ctx
->fh
.m2m_ctx
);
896 if (!ctx
->last_src_buf
&& ctx
->last_dst_buf
) {
897 ctx
->last_dst_buf
->flags
|= V4L2_BUF_FLAG_LAST
;
898 v4l2_event_queue_fh(&ctx
->fh
, &eos_event
);
900 spin_unlock(ctx
->lock
);
903 static int vicodec_try_encoder_cmd(struct file
*file
, void *fh
,
904 struct v4l2_encoder_cmd
*ec
)
906 if (ec
->cmd
!= V4L2_ENC_CMD_STOP
)
909 if (ec
->flags
& V4L2_ENC_CMD_STOP_AT_GOP_END
)
915 static int vicodec_encoder_cmd(struct file
*file
, void *fh
,
916 struct v4l2_encoder_cmd
*ec
)
918 struct vicodec_ctx
*ctx
= file2ctx(file
);
921 ret
= vicodec_try_encoder_cmd(file
, fh
, ec
);
925 vicodec_mark_last_buf(ctx
);
929 static int vicodec_try_decoder_cmd(struct file
*file
, void *fh
,
930 struct v4l2_decoder_cmd
*dc
)
932 if (dc
->cmd
!= V4L2_DEC_CMD_STOP
)
935 if (dc
->flags
& V4L2_DEC_CMD_STOP_TO_BLACK
)
938 if (!(dc
->flags
& V4L2_DEC_CMD_STOP_IMMEDIATELY
) && (dc
->stop
.pts
!= 0))
944 static int vicodec_decoder_cmd(struct file
*file
, void *fh
,
945 struct v4l2_decoder_cmd
*dc
)
947 struct vicodec_ctx
*ctx
= file2ctx(file
);
950 ret
= vicodec_try_decoder_cmd(file
, fh
, dc
);
954 vicodec_mark_last_buf(ctx
);
958 static int vicodec_enum_framesizes(struct file
*file
, void *fh
,
959 struct v4l2_frmsizeenum
*fsize
)
961 switch (fsize
->pixel_format
) {
962 case V4L2_PIX_FMT_FWHT
:
965 if (find_fmt(fsize
->pixel_format
) == fsize
->pixel_format
)
973 fsize
->type
= V4L2_FRMSIZE_TYPE_STEPWISE
;
975 fsize
->stepwise
.min_width
= MIN_WIDTH
;
976 fsize
->stepwise
.max_width
= MAX_WIDTH
;
977 fsize
->stepwise
.step_width
= 8;
978 fsize
->stepwise
.min_height
= MIN_HEIGHT
;
979 fsize
->stepwise
.max_height
= MAX_HEIGHT
;
980 fsize
->stepwise
.step_height
= 8;
985 static int vicodec_subscribe_event(struct v4l2_fh
*fh
,
986 const struct v4l2_event_subscription
*sub
)
990 return v4l2_event_subscribe(fh
, sub
, 0, NULL
);
992 return v4l2_ctrl_subscribe_event(fh
, sub
);
996 static const struct v4l2_ioctl_ops vicodec_ioctl_ops
= {
997 .vidioc_querycap
= vidioc_querycap
,
999 .vidioc_enum_fmt_vid_cap
= vidioc_enum_fmt_vid_cap
,
1000 .vidioc_g_fmt_vid_cap
= vidioc_g_fmt_vid_cap
,
1001 .vidioc_try_fmt_vid_cap
= vidioc_try_fmt_vid_cap
,
1002 .vidioc_s_fmt_vid_cap
= vidioc_s_fmt_vid_cap
,
1004 .vidioc_enum_fmt_vid_cap_mplane
= vidioc_enum_fmt_vid_cap
,
1005 .vidioc_g_fmt_vid_cap_mplane
= vidioc_g_fmt_vid_cap
,
1006 .vidioc_try_fmt_vid_cap_mplane
= vidioc_try_fmt_vid_cap
,
1007 .vidioc_s_fmt_vid_cap_mplane
= vidioc_s_fmt_vid_cap
,
1009 .vidioc_enum_fmt_vid_out
= vidioc_enum_fmt_vid_out
,
1010 .vidioc_g_fmt_vid_out
= vidioc_g_fmt_vid_out
,
1011 .vidioc_try_fmt_vid_out
= vidioc_try_fmt_vid_out
,
1012 .vidioc_s_fmt_vid_out
= vidioc_s_fmt_vid_out
,
1014 .vidioc_enum_fmt_vid_out_mplane
= vidioc_enum_fmt_vid_out
,
1015 .vidioc_g_fmt_vid_out_mplane
= vidioc_g_fmt_vid_out
,
1016 .vidioc_try_fmt_vid_out_mplane
= vidioc_try_fmt_vid_out
,
1017 .vidioc_s_fmt_vid_out_mplane
= vidioc_s_fmt_vid_out
,
1019 .vidioc_reqbufs
= v4l2_m2m_ioctl_reqbufs
,
1020 .vidioc_querybuf
= v4l2_m2m_ioctl_querybuf
,
1021 .vidioc_qbuf
= v4l2_m2m_ioctl_qbuf
,
1022 .vidioc_dqbuf
= v4l2_m2m_ioctl_dqbuf
,
1023 .vidioc_prepare_buf
= v4l2_m2m_ioctl_prepare_buf
,
1024 .vidioc_create_bufs
= v4l2_m2m_ioctl_create_bufs
,
1025 .vidioc_expbuf
= v4l2_m2m_ioctl_expbuf
,
1027 .vidioc_streamon
= v4l2_m2m_ioctl_streamon
,
1028 .vidioc_streamoff
= v4l2_m2m_ioctl_streamoff
,
1030 .vidioc_try_encoder_cmd
= vicodec_try_encoder_cmd
,
1031 .vidioc_encoder_cmd
= vicodec_encoder_cmd
,
1032 .vidioc_try_decoder_cmd
= vicodec_try_decoder_cmd
,
1033 .vidioc_decoder_cmd
= vicodec_decoder_cmd
,
1034 .vidioc_enum_framesizes
= vicodec_enum_framesizes
,
1036 .vidioc_subscribe_event
= vicodec_subscribe_event
,
1037 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
1045 static int vicodec_queue_setup(struct vb2_queue
*vq
, unsigned int *nbuffers
,
1046 unsigned int *nplanes
, unsigned int sizes
[],
1047 struct device
*alloc_devs
[])
1049 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(vq
);
1050 struct vicodec_q_data
*q_data
= get_q_data(ctx
, vq
->type
);
1051 unsigned int size
= q_data
->sizeimage
;
1054 return sizes
[0] < size
? -EINVAL
: 0;
1061 static int vicodec_buf_prepare(struct vb2_buffer
*vb
)
1063 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1064 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1065 struct vicodec_q_data
*q_data
;
1067 dprintk(ctx
->dev
, "type: %d\n", vb
->vb2_queue
->type
);
1069 q_data
= get_q_data(ctx
, vb
->vb2_queue
->type
);
1070 if (V4L2_TYPE_IS_OUTPUT(vb
->vb2_queue
->type
)) {
1071 if (vbuf
->field
== V4L2_FIELD_ANY
)
1072 vbuf
->field
= V4L2_FIELD_NONE
;
1073 if (vbuf
->field
!= V4L2_FIELD_NONE
) {
1074 dprintk(ctx
->dev
, "%s field isn't supported\n",
1080 if (vb2_plane_size(vb
, 0) < q_data
->sizeimage
) {
1082 "%s data will not fit into plane (%lu < %lu)\n",
1083 __func__
, vb2_plane_size(vb
, 0),
1084 (long)q_data
->sizeimage
);
1091 static void vicodec_buf_queue(struct vb2_buffer
*vb
)
1093 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1094 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1096 v4l2_m2m_buf_queue(ctx
->fh
.m2m_ctx
, vbuf
);
1099 static void vicodec_return_bufs(struct vb2_queue
*q
, u32 state
)
1101 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(q
);
1102 struct vb2_v4l2_buffer
*vbuf
;
1105 if (V4L2_TYPE_IS_OUTPUT(q
->type
))
1106 vbuf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
1108 vbuf
= v4l2_m2m_dst_buf_remove(ctx
->fh
.m2m_ctx
);
1111 spin_lock(ctx
->lock
);
1112 v4l2_m2m_buf_done(vbuf
, state
);
1113 spin_unlock(ctx
->lock
);
1117 static int vicodec_start_streaming(struct vb2_queue
*q
,
1120 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(q
);
1121 struct vicodec_q_data
*q_data
= get_q_data(ctx
, q
->type
);
1122 unsigned int size
= q_data
->width
* q_data
->height
;
1124 q_data
->sequence
= 0;
1126 if (!V4L2_TYPE_IS_OUTPUT(q
->type
))
1129 ctx
->ref_frame
.width
= ctx
->ref_frame
.height
= 0;
1130 ctx
->ref_frame
.luma
= kvmalloc(size
* 3 / 2, GFP_KERNEL
);
1131 ctx
->comp_max_size
= size
* 3 / 2 + sizeof(struct cframe_hdr
);
1132 ctx
->compressed_frame
= kvmalloc(ctx
->comp_max_size
, GFP_KERNEL
);
1133 if (!ctx
->ref_frame
.luma
|| !ctx
->compressed_frame
) {
1134 kvfree(ctx
->ref_frame
.luma
);
1135 kvfree(ctx
->compressed_frame
);
1136 vicodec_return_bufs(q
, VB2_BUF_STATE_QUEUED
);
1139 ctx
->ref_frame
.cb
= ctx
->ref_frame
.luma
+ size
;
1140 ctx
->ref_frame
.cr
= ctx
->ref_frame
.cb
+ size
/ 4;
1141 ctx
->last_src_buf
= NULL
;
1142 ctx
->last_dst_buf
= NULL
;
1143 v4l2_ctrl_grab(ctx
->ctrl_gop_size
, true);
1144 ctx
->gop_size
= v4l2_ctrl_g_ctrl(ctx
->ctrl_gop_size
);
1146 ctx
->cur_buf_offset
= 0;
1148 ctx
->comp_magic_cnt
= 0;
1149 ctx
->comp_has_frame
= false;
1154 static void vicodec_stop_streaming(struct vb2_queue
*q
)
1156 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(q
);
1158 vicodec_return_bufs(q
, VB2_BUF_STATE_ERROR
);
1160 if (!V4L2_TYPE_IS_OUTPUT(q
->type
))
1163 kvfree(ctx
->ref_frame
.luma
);
1164 kvfree(ctx
->compressed_frame
);
1165 v4l2_ctrl_grab(ctx
->ctrl_gop_size
, false);
1168 static const struct vb2_ops vicodec_qops
= {
1169 .queue_setup
= vicodec_queue_setup
,
1170 .buf_prepare
= vicodec_buf_prepare
,
1171 .buf_queue
= vicodec_buf_queue
,
1172 .start_streaming
= vicodec_start_streaming
,
1173 .stop_streaming
= vicodec_stop_streaming
,
1174 .wait_prepare
= vb2_ops_wait_prepare
,
1175 .wait_finish
= vb2_ops_wait_finish
,
1178 static int queue_init(void *priv
, struct vb2_queue
*src_vq
,
1179 struct vb2_queue
*dst_vq
)
1181 struct vicodec_ctx
*ctx
= priv
;
1184 src_vq
->type
= (multiplanar
?
1185 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
1186 V4L2_BUF_TYPE_VIDEO_OUTPUT
);
1187 src_vq
->io_modes
= VB2_MMAP
| VB2_USERPTR
| VB2_DMABUF
;
1188 src_vq
->drv_priv
= ctx
;
1189 src_vq
->buf_struct_size
= sizeof(struct v4l2_m2m_buffer
);
1190 src_vq
->ops
= &vicodec_qops
;
1191 src_vq
->mem_ops
= &vb2_vmalloc_memops
;
1192 src_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1193 src_vq
->lock
= ctx
->is_enc
? &ctx
->dev
->enc_mutex
:
1194 &ctx
->dev
->dec_mutex
;
1196 ret
= vb2_queue_init(src_vq
);
1200 dst_vq
->type
= (multiplanar
?
1201 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
1202 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
1203 dst_vq
->io_modes
= VB2_MMAP
| VB2_USERPTR
| VB2_DMABUF
;
1204 dst_vq
->drv_priv
= ctx
;
1205 dst_vq
->buf_struct_size
= sizeof(struct v4l2_m2m_buffer
);
1206 dst_vq
->ops
= &vicodec_qops
;
1207 dst_vq
->mem_ops
= &vb2_vmalloc_memops
;
1208 dst_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1209 dst_vq
->lock
= src_vq
->lock
;
1211 return vb2_queue_init(dst_vq
);
1217 static int vicodec_open(struct file
*file
)
1219 struct video_device
*vfd
= video_devdata(file
);
1220 struct vicodec_dev
*dev
= video_drvdata(file
);
1221 struct vicodec_ctx
*ctx
= NULL
;
1222 struct v4l2_ctrl_handler
*hdl
;
1226 if (mutex_lock_interruptible(vfd
->lock
))
1227 return -ERESTARTSYS
;
1228 ctx
= kzalloc(sizeof(*ctx
), GFP_KERNEL
);
1234 if (vfd
== &dev
->enc_vfd
)
1237 v4l2_fh_init(&ctx
->fh
, video_devdata(file
));
1238 file
->private_data
= &ctx
->fh
;
1241 v4l2_ctrl_handler_init(hdl
, 4);
1242 ctx
->ctrl_gop_size
= v4l2_ctrl_new_std(hdl
, NULL
,
1243 V4L2_CID_MPEG_VIDEO_GOP_SIZE
,
1247 v4l2_ctrl_handler_free(hdl
);
1251 ctx
->fh
.ctrl_handler
= hdl
;
1252 v4l2_ctrl_handler_setup(hdl
);
1254 ctx
->q_data
[V4L2_M2M_SRC
].fourcc
=
1255 ctx
->is_enc
? V4L2_PIX_FMT_YUV420
: V4L2_PIX_FMT_FWHT
;
1256 ctx
->q_data
[V4L2_M2M_SRC
].width
= 1280;
1257 ctx
->q_data
[V4L2_M2M_SRC
].height
= 720;
1258 size
= 1280 * 720 * 3 / 2;
1259 ctx
->q_data
[V4L2_M2M_SRC
].sizeimage
= size
;
1260 ctx
->q_data
[V4L2_M2M_DST
] = ctx
->q_data
[V4L2_M2M_SRC
];
1261 ctx
->q_data
[V4L2_M2M_DST
].fourcc
=
1262 ctx
->is_enc
? V4L2_PIX_FMT_FWHT
: V4L2_PIX_FMT_YUV420
;
1263 ctx
->colorspace
= V4L2_COLORSPACE_REC709
;
1265 size
+= sizeof(struct cframe_hdr
);
1267 ctx
->q_data
[V4L2_M2M_DST
].sizeimage
= size
;
1268 ctx
->fh
.m2m_ctx
= v4l2_m2m_ctx_init(dev
->enc_dev
, ctx
,
1270 ctx
->lock
= &dev
->enc_lock
;
1272 ctx
->q_data
[V4L2_M2M_SRC
].sizeimage
= size
;
1273 ctx
->fh
.m2m_ctx
= v4l2_m2m_ctx_init(dev
->dec_dev
, ctx
,
1275 ctx
->lock
= &dev
->dec_lock
;
1278 if (IS_ERR(ctx
->fh
.m2m_ctx
)) {
1279 rc
= PTR_ERR(ctx
->fh
.m2m_ctx
);
1281 v4l2_ctrl_handler_free(hdl
);
1282 v4l2_fh_exit(&ctx
->fh
);
1287 v4l2_fh_add(&ctx
->fh
);
1290 mutex_unlock(vfd
->lock
);
1294 static int vicodec_release(struct file
*file
)
1296 struct video_device
*vfd
= video_devdata(file
);
1297 struct vicodec_ctx
*ctx
= file2ctx(file
);
1299 v4l2_fh_del(&ctx
->fh
);
1300 v4l2_fh_exit(&ctx
->fh
);
1301 v4l2_ctrl_handler_free(&ctx
->hdl
);
1302 mutex_lock(vfd
->lock
);
1303 v4l2_m2m_ctx_release(ctx
->fh
.m2m_ctx
);
1304 mutex_unlock(vfd
->lock
);
1310 static const struct v4l2_file_operations vicodec_fops
= {
1311 .owner
= THIS_MODULE
,
1312 .open
= vicodec_open
,
1313 .release
= vicodec_release
,
1314 .poll
= v4l2_m2m_fop_poll
,
1315 .unlocked_ioctl
= video_ioctl2
,
1316 .mmap
= v4l2_m2m_fop_mmap
,
1319 static const struct video_device vicodec_videodev
= {
1320 .name
= VICODEC_NAME
,
1321 .vfl_dir
= VFL_DIR_M2M
,
1322 .fops
= &vicodec_fops
,
1323 .ioctl_ops
= &vicodec_ioctl_ops
,
1325 .release
= video_device_release_empty
,
1328 static const struct v4l2_m2m_ops m2m_ops
= {
1329 .device_run
= device_run
,
1330 .job_abort
= job_abort
,
1331 .job_ready
= job_ready
,
1334 static int vicodec_probe(struct platform_device
*pdev
)
1336 struct vicodec_dev
*dev
;
1337 struct video_device
*vfd
;
1340 dev
= devm_kzalloc(&pdev
->dev
, sizeof(*dev
), GFP_KERNEL
);
1344 spin_lock_init(&dev
->enc_lock
);
1345 spin_lock_init(&dev
->dec_lock
);
1347 ret
= v4l2_device_register(&pdev
->dev
, &dev
->v4l2_dev
);
1351 #ifdef CONFIG_MEDIA_CONTROLLER
1352 dev
->mdev
.dev
= &pdev
->dev
;
1353 strlcpy(dev
->mdev
.model
, "vicodec", sizeof(dev
->mdev
.model
));
1354 media_device_init(&dev
->mdev
);
1355 dev
->v4l2_dev
.mdev
= &dev
->mdev
;
1358 mutex_init(&dev
->enc_mutex
);
1359 mutex_init(&dev
->dec_mutex
);
1361 platform_set_drvdata(pdev
, dev
);
1363 dev
->enc_dev
= v4l2_m2m_init(&m2m_ops
);
1364 if (IS_ERR(dev
->enc_dev
)) {
1365 v4l2_err(&dev
->v4l2_dev
, "Failed to init vicodec device\n");
1366 ret
= PTR_ERR(dev
->enc_dev
);
1370 dev
->dec_dev
= v4l2_m2m_init(&m2m_ops
);
1371 if (IS_ERR(dev
->dec_dev
)) {
1372 v4l2_err(&dev
->v4l2_dev
, "Failed to init vicodec device\n");
1373 ret
= PTR_ERR(dev
->dec_dev
);
1377 dev
->enc_vfd
= vicodec_videodev
;
1378 vfd
= &dev
->enc_vfd
;
1379 vfd
->lock
= &dev
->enc_mutex
;
1380 vfd
->v4l2_dev
= &dev
->v4l2_dev
;
1381 strlcpy(vfd
->name
, "vicodec-enc", sizeof(vfd
->name
));
1382 v4l2_disable_ioctl(vfd
, VIDIOC_DECODER_CMD
);
1383 v4l2_disable_ioctl(vfd
, VIDIOC_TRY_DECODER_CMD
);
1384 video_set_drvdata(vfd
, dev
);
1386 ret
= video_register_device(vfd
, VFL_TYPE_GRABBER
, 0);
1388 v4l2_err(&dev
->v4l2_dev
, "Failed to register video device\n");
1391 v4l2_info(&dev
->v4l2_dev
,
1392 "Device registered as /dev/video%d\n", vfd
->num
);
1394 dev
->dec_vfd
= vicodec_videodev
;
1395 vfd
= &dev
->dec_vfd
;
1396 vfd
->lock
= &dev
->dec_mutex
;
1397 vfd
->v4l2_dev
= &dev
->v4l2_dev
;
1398 strlcpy(vfd
->name
, "vicodec-dec", sizeof(vfd
->name
));
1399 v4l2_disable_ioctl(vfd
, VIDIOC_ENCODER_CMD
);
1400 v4l2_disable_ioctl(vfd
, VIDIOC_TRY_ENCODER_CMD
);
1401 video_set_drvdata(vfd
, dev
);
1403 ret
= video_register_device(vfd
, VFL_TYPE_GRABBER
, 0);
1405 v4l2_err(&dev
->v4l2_dev
, "Failed to register video device\n");
1408 v4l2_info(&dev
->v4l2_dev
,
1409 "Device registered as /dev/video%d\n", vfd
->num
);
1411 #ifdef CONFIG_MEDIA_CONTROLLER
1412 ret
= v4l2_m2m_register_media_controller(dev
->enc_dev
,
1413 &dev
->enc_vfd
, MEDIA_ENT_F_PROC_VIDEO_ENCODER
);
1415 v4l2_err(&dev
->v4l2_dev
, "Failed to init mem2mem media controller\n");
1419 ret
= v4l2_m2m_register_media_controller(dev
->dec_dev
,
1420 &dev
->dec_vfd
, MEDIA_ENT_F_PROC_VIDEO_DECODER
);
1422 v4l2_err(&dev
->v4l2_dev
, "Failed to init mem2mem media controller\n");
1423 goto unreg_m2m_enc_mc
;
1426 ret
= media_device_register(&dev
->mdev
);
1428 v4l2_err(&dev
->v4l2_dev
, "Failed to register mem2mem media device\n");
1429 goto unreg_m2m_dec_mc
;
1434 #ifdef CONFIG_MEDIA_CONTROLLER
1436 v4l2_m2m_unregister_media_controller(dev
->dec_dev
);
1438 v4l2_m2m_unregister_media_controller(dev
->enc_dev
);
1440 video_unregister_device(&dev
->dec_vfd
);
1443 video_unregister_device(&dev
->enc_vfd
);
1445 v4l2_m2m_release(dev
->dec_dev
);
1447 v4l2_m2m_release(dev
->enc_dev
);
1449 v4l2_device_unregister(&dev
->v4l2_dev
);
1454 static int vicodec_remove(struct platform_device
*pdev
)
1456 struct vicodec_dev
*dev
= platform_get_drvdata(pdev
);
1458 v4l2_info(&dev
->v4l2_dev
, "Removing " VICODEC_NAME
);
1460 #ifdef CONFIG_MEDIA_CONTROLLER
1461 media_device_unregister(&dev
->mdev
);
1462 v4l2_m2m_unregister_media_controller(dev
->enc_dev
);
1463 v4l2_m2m_unregister_media_controller(dev
->dec_dev
);
1464 media_device_cleanup(&dev
->mdev
);
1467 v4l2_m2m_release(dev
->enc_dev
);
1468 v4l2_m2m_release(dev
->dec_dev
);
1469 video_unregister_device(&dev
->enc_vfd
);
1470 video_unregister_device(&dev
->dec_vfd
);
1471 v4l2_device_unregister(&dev
->v4l2_dev
);
1476 static struct platform_driver vicodec_pdrv
= {
1477 .probe
= vicodec_probe
,
1478 .remove
= vicodec_remove
,
1480 .name
= VICODEC_NAME
,
1484 static void __exit
vicodec_exit(void)
1486 platform_driver_unregister(&vicodec_pdrv
);
1487 platform_device_unregister(&vicodec_pdev
);
1490 static int __init
vicodec_init(void)
1494 ret
= platform_device_register(&vicodec_pdev
);
1498 ret
= platform_driver_register(&vicodec_pdrv
);
1500 platform_device_unregister(&vicodec_pdev
);
1505 module_init(vicodec_init
);
1506 module_exit(vicodec_exit
);