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 "codec-v4l2-fwht.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 360U
47 #define dprintk(dev, fmt, arg...) \
48 v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
53 unsigned int bytesperline_mult
;
54 unsigned int sizeimage_mult
;
55 unsigned int sizeimage_div
;
56 unsigned int luma_step
;
57 unsigned int chroma_step
;
58 /* Chroma plane subsampling */
59 unsigned int width_div
;
60 unsigned int height_div
;
63 static const struct v4l2_fwht_pixfmt_info pixfmt_fwht
= {
64 V4L2_PIX_FMT_FWHT
, 0, 3, 1, 1, 1, 1, 1, 0, 1
67 static const struct v4l2_fwht_pixfmt_info pixfmt_stateless_fwht
= {
68 V4L2_PIX_FMT_FWHT_STATELESS
, 0, 3, 1, 1, 1, 1, 1, 0, 1
71 static void vicodec_dev_release(struct device
*dev
)
75 static struct platform_device vicodec_pdev
= {
77 .dev
.release
= vicodec_dev_release
,
80 /* Per-queue, driver-specific private data */
81 struct vicodec_q_data
{
82 unsigned int coded_width
;
83 unsigned int coded_height
;
84 unsigned int visible_width
;
85 unsigned int visible_height
;
86 unsigned int sizeimage
;
87 unsigned int vb2_sizeimage
;
88 unsigned int sequence
;
89 const struct v4l2_fwht_pixfmt_info
*info
;
97 struct vicodec_dev_instance
{
98 struct video_device vfd
;
101 struct v4l2_m2m_dev
*m2m_dev
;
105 struct v4l2_device v4l2_dev
;
106 struct vicodec_dev_instance stateful_enc
;
107 struct vicodec_dev_instance stateful_dec
;
108 struct vicodec_dev_instance stateless_dec
;
109 #ifdef CONFIG_MEDIA_CONTROLLER
110 struct media_device mdev
;
117 struct vicodec_dev
*dev
;
125 struct v4l2_ctrl_handler hdl
;
127 struct vb2_v4l2_buffer
*last_src_buf
;
129 /* Source and destination queue data */
130 struct vicodec_q_data q_data
[2];
131 struct v4l2_fwht_state state
;
139 bool comp_has_next_frame
;
140 bool first_source_change_sent
;
144 static const struct v4l2_event vicodec_eos_event
= {
145 .type
= V4L2_EVENT_EOS
148 static inline struct vicodec_ctx
*file2ctx(struct file
*file
)
150 return container_of(file
->private_data
, struct vicodec_ctx
, fh
);
153 static struct vicodec_q_data
*get_q_data(struct vicodec_ctx
*ctx
,
154 enum v4l2_buf_type type
)
157 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
158 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
159 return &ctx
->q_data
[V4L2_M2M_SRC
];
160 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
161 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
162 return &ctx
->q_data
[V4L2_M2M_DST
];
169 static void copy_cap_to_ref(const u8
*cap
, const struct v4l2_fwht_pixfmt_info
*info
,
170 struct v4l2_fwht_state
*state
)
173 u8
*p_ref
= state
->ref_frame
.buf
;
174 unsigned int cap_stride
= state
->stride
;
175 unsigned int ref_stride
= state
->ref_stride
;
177 for (plane_idx
= 0; plane_idx
< info
->planes_num
; plane_idx
++) {
179 unsigned int h_div
= (plane_idx
== 1 || plane_idx
== 2) ?
180 info
->height_div
: 1;
181 const u8
*row_cap
= cap
;
184 if (info
->planes_num
== 3 && plane_idx
== 1) {
189 if (plane_idx
== 1 &&
190 (info
->id
== V4L2_PIX_FMT_NV24
||
191 info
->id
== V4L2_PIX_FMT_NV42
)) {
196 for (i
= 0; i
< state
->visible_height
/ h_div
; i
++) {
197 memcpy(row_ref
, row_cap
, ref_stride
);
198 row_ref
+= ref_stride
;
199 row_cap
+= cap_stride
;
201 cap
+= cap_stride
* (state
->coded_height
/ h_div
);
202 p_ref
+= ref_stride
* (state
->coded_height
/ h_div
);
206 static bool validate_by_version(unsigned int flags
, unsigned int version
)
208 if (!version
|| version
> FWHT_VERSION
)
212 unsigned int components_num
= 1 +
213 ((flags
& FWHT_FL_COMPONENTS_NUM_MSK
) >>
214 FWHT_FL_COMPONENTS_NUM_OFFSET
);
215 unsigned int pixenc
= flags
& FWHT_FL_PIXENC_MSK
;
217 if (components_num
== 0 || components_num
> 4 || !pixenc
)
223 static bool validate_stateless_params_flags(const struct v4l2_ctrl_fwht_params
*params
,
224 const struct v4l2_fwht_pixfmt_info
*cur_info
)
226 unsigned int width_div
=
227 (params
->flags
& FWHT_FL_CHROMA_FULL_WIDTH
) ? 1 : 2;
228 unsigned int height_div
=
229 (params
->flags
& FWHT_FL_CHROMA_FULL_HEIGHT
) ? 1 : 2;
230 unsigned int components_num
= 3;
231 unsigned int pixenc
= 0;
233 if (params
->version
< 3)
236 components_num
= 1 + ((params
->flags
& FWHT_FL_COMPONENTS_NUM_MSK
) >>
237 FWHT_FL_COMPONENTS_NUM_OFFSET
);
238 pixenc
= (params
->flags
& FWHT_FL_PIXENC_MSK
);
239 if (v4l2_fwht_validate_fmt(cur_info
, width_div
, height_div
,
240 components_num
, pixenc
))
246 static void update_state_from_header(struct vicodec_ctx
*ctx
)
248 const struct fwht_cframe_hdr
*p_hdr
= &ctx
->state
.header
;
250 ctx
->state
.visible_width
= ntohl(p_hdr
->width
);
251 ctx
->state
.visible_height
= ntohl(p_hdr
->height
);
252 ctx
->state
.colorspace
= ntohl(p_hdr
->colorspace
);
253 ctx
->state
.xfer_func
= ntohl(p_hdr
->xfer_func
);
254 ctx
->state
.ycbcr_enc
= ntohl(p_hdr
->ycbcr_enc
);
255 ctx
->state
.quantization
= ntohl(p_hdr
->quantization
);
258 static int device_process(struct vicodec_ctx
*ctx
,
259 struct vb2_v4l2_buffer
*src_vb
,
260 struct vb2_v4l2_buffer
*dst_vb
)
262 struct vicodec_dev
*dev
= ctx
->dev
;
263 struct v4l2_fwht_state
*state
= &ctx
->state
;
267 if (ctx
->is_enc
|| ctx
->is_stateless
)
268 p_src
= vb2_plane_vaddr(&src_vb
->vb2_buf
, 0);
270 p_src
= state
->compressed_frame
;
272 if (ctx
->is_stateless
) {
273 struct media_request
*src_req
= src_vb
->vb2_buf
.req_obj
.req
;
275 ret
= v4l2_ctrl_request_setup(src_req
, &ctx
->hdl
);
278 update_state_from_header(ctx
);
280 ctx
->state
.header
.size
=
281 htonl(vb2_get_plane_payload(&src_vb
->vb2_buf
, 0));
283 * set the reference buffer from the reference timestamp
284 * only if this is a P-frame
286 if (!(ntohl(ctx
->state
.header
.flags
) & FWHT_FL_I_FRAME
)) {
287 struct vb2_buffer
*ref_vb2_buf
;
289 struct vb2_queue
*vq_cap
=
290 v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
,
291 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
293 ref_buf_idx
= vb2_find_timestamp(vq_cap
,
294 ctx
->state
.ref_frame_ts
, 0);
298 ref_vb2_buf
= vq_cap
->bufs
[ref_buf_idx
];
299 if (ref_vb2_buf
->state
== VB2_BUF_STATE_ERROR
)
301 ctx
->state
.ref_frame
.buf
=
302 vb2_plane_vaddr(ref_vb2_buf
, 0);
304 ctx
->state
.ref_frame
.buf
= NULL
;
307 p_dst
= vb2_plane_vaddr(&dst_vb
->vb2_buf
, 0);
308 if (!p_src
|| !p_dst
) {
309 v4l2_err(&dev
->v4l2_dev
,
310 "Acquiring kernel pointers to buffers failed\n");
315 struct vicodec_q_data
*q_src
;
316 int comp_sz_or_errcode
;
318 q_src
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_OUTPUT
);
319 state
->info
= q_src
->info
;
320 comp_sz_or_errcode
= v4l2_fwht_encode(state
, p_src
, p_dst
);
321 if (comp_sz_or_errcode
< 0)
322 return comp_sz_or_errcode
;
323 vb2_set_plane_payload(&dst_vb
->vb2_buf
, 0, comp_sz_or_errcode
);
325 struct vicodec_q_data
*q_dst
;
326 unsigned int comp_frame_size
= ntohl(ctx
->state
.header
.size
);
328 q_dst
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_CAPTURE
);
329 if (comp_frame_size
> ctx
->comp_max_size
)
331 state
->info
= q_dst
->info
;
332 ret
= v4l2_fwht_decode(state
, p_src
, p_dst
);
335 if (!ctx
->is_stateless
)
336 copy_cap_to_ref(p_dst
, ctx
->state
.info
, &ctx
->state
);
338 vb2_set_plane_payload(&dst_vb
->vb2_buf
, 0, q_dst
->sizeimage
);
339 if (ntohl(ctx
->state
.header
.flags
) & FWHT_FL_I_FRAME
)
340 dst_vb
->flags
|= V4L2_BUF_FLAG_KEYFRAME
;
342 dst_vb
->flags
|= V4L2_BUF_FLAG_PFRAME
;
350 static enum vb2_buffer_state
get_next_header(struct vicodec_ctx
*ctx
,
353 static const u8 magic
[] = {
354 0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
358 u8
*header
= (u8
*)&ctx
->state
.header
;
360 state
= VB2_BUF_STATE_DONE
;
362 if (!ctx
->header_size
) {
363 state
= VB2_BUF_STATE_ERROR
;
364 for (; p
< *pp
+ sz
; p
++) {
367 p
= memchr(p
, magic
[ctx
->comp_magic_cnt
],
370 ctx
->comp_magic_cnt
= 0;
374 copy
= sizeof(magic
) - ctx
->comp_magic_cnt
;
375 if (*pp
+ sz
- p
< copy
)
378 memcpy(header
+ ctx
->comp_magic_cnt
, p
, copy
);
379 ctx
->comp_magic_cnt
+= copy
;
380 if (!memcmp(header
, magic
, ctx
->comp_magic_cnt
)) {
382 state
= VB2_BUF_STATE_DONE
;
385 ctx
->comp_magic_cnt
= 0;
387 if (ctx
->comp_magic_cnt
< sizeof(magic
)) {
391 ctx
->header_size
= sizeof(magic
);
394 if (ctx
->header_size
< sizeof(struct fwht_cframe_hdr
)) {
395 u32 copy
= sizeof(struct fwht_cframe_hdr
) - ctx
->header_size
;
397 if (*pp
+ sz
- p
< copy
)
400 memcpy(header
+ ctx
->header_size
, p
, copy
);
402 ctx
->header_size
+= copy
;
408 /* device_run() - prepares and starts the device */
409 static void device_run(void *priv
)
411 struct vicodec_ctx
*ctx
= priv
;
412 struct vicodec_dev
*dev
= ctx
->dev
;
413 struct vb2_v4l2_buffer
*src_buf
, *dst_buf
;
414 struct vicodec_q_data
*q_src
, *q_dst
;
416 struct media_request
*src_req
;
418 src_buf
= v4l2_m2m_next_src_buf(ctx
->fh
.m2m_ctx
);
419 dst_buf
= v4l2_m2m_dst_buf_remove(ctx
->fh
.m2m_ctx
);
420 src_req
= src_buf
->vb2_buf
.req_obj
.req
;
422 q_src
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_OUTPUT
);
423 q_dst
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_CAPTURE
);
425 state
= VB2_BUF_STATE_DONE
;
426 if (device_process(ctx
, src_buf
, dst_buf
))
427 state
= VB2_BUF_STATE_ERROR
;
429 dst_buf
->sequence
= q_dst
->sequence
++;
430 dst_buf
->flags
&= ~V4L2_BUF_FLAG_LAST
;
431 v4l2_m2m_buf_copy_metadata(src_buf
, dst_buf
, false);
433 spin_lock(ctx
->lock
);
434 if (!ctx
->comp_has_next_frame
&& src_buf
== ctx
->last_src_buf
) {
435 dst_buf
->flags
|= V4L2_BUF_FLAG_LAST
;
436 v4l2_event_queue_fh(&ctx
->fh
, &vicodec_eos_event
);
437 ctx
->is_draining
= false;
438 ctx
->has_stopped
= true;
440 if (ctx
->is_enc
|| ctx
->is_stateless
) {
441 src_buf
->sequence
= q_src
->sequence
++;
442 src_buf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
443 v4l2_m2m_buf_done(src_buf
, state
);
444 } else if (vb2_get_plane_payload(&src_buf
->vb2_buf
, 0) == ctx
->cur_buf_offset
) {
445 src_buf
->sequence
= q_src
->sequence
++;
446 src_buf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
447 v4l2_m2m_buf_done(src_buf
, state
);
448 ctx
->cur_buf_offset
= 0;
449 ctx
->comp_has_next_frame
= false;
451 v4l2_m2m_buf_done(dst_buf
, state
);
454 ctx
->header_size
= 0;
455 ctx
->comp_magic_cnt
= 0;
456 ctx
->comp_has_frame
= false;
457 spin_unlock(ctx
->lock
);
458 if (ctx
->is_stateless
&& src_req
)
459 v4l2_ctrl_request_complete(src_req
, &ctx
->hdl
);
462 v4l2_m2m_job_finish(dev
->stateful_enc
.m2m_dev
, ctx
->fh
.m2m_ctx
);
463 else if (ctx
->is_stateless
)
464 v4l2_m2m_job_finish(dev
->stateless_dec
.m2m_dev
,
467 v4l2_m2m_job_finish(dev
->stateful_dec
.m2m_dev
, ctx
->fh
.m2m_ctx
);
470 static void job_remove_src_buf(struct vicodec_ctx
*ctx
, u32 state
)
472 struct vb2_v4l2_buffer
*src_buf
;
473 struct vicodec_q_data
*q_src
;
475 q_src
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_OUTPUT
);
476 spin_lock(ctx
->lock
);
477 src_buf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
478 src_buf
->sequence
= q_src
->sequence
++;
479 v4l2_m2m_buf_done(src_buf
, state
);
480 ctx
->cur_buf_offset
= 0;
481 spin_unlock(ctx
->lock
);
484 static const struct v4l2_fwht_pixfmt_info
*
485 info_from_header(const struct fwht_cframe_hdr
*p_hdr
)
487 unsigned int flags
= ntohl(p_hdr
->flags
);
488 unsigned int width_div
= (flags
& FWHT_FL_CHROMA_FULL_WIDTH
) ? 1 : 2;
489 unsigned int height_div
= (flags
& FWHT_FL_CHROMA_FULL_HEIGHT
) ? 1 : 2;
490 unsigned int components_num
= 3;
491 unsigned int pixenc
= 0;
492 unsigned int version
= ntohl(p_hdr
->version
);
495 components_num
= 1 + ((flags
& FWHT_FL_COMPONENTS_NUM_MSK
) >>
496 FWHT_FL_COMPONENTS_NUM_OFFSET
);
497 pixenc
= (flags
& FWHT_FL_PIXENC_MSK
);
499 return v4l2_fwht_find_nth_fmt(width_div
, height_div
,
500 components_num
, pixenc
, 0);
503 static bool is_header_valid(const struct fwht_cframe_hdr
*p_hdr
)
505 const struct v4l2_fwht_pixfmt_info
*info
;
506 unsigned int w
= ntohl(p_hdr
->width
);
507 unsigned int h
= ntohl(p_hdr
->height
);
508 unsigned int version
= ntohl(p_hdr
->version
);
509 unsigned int flags
= ntohl(p_hdr
->flags
);
511 if (w
< MIN_WIDTH
|| w
> MAX_WIDTH
|| h
< MIN_HEIGHT
|| h
> MAX_HEIGHT
)
514 if (!validate_by_version(flags
, version
))
517 info
= info_from_header(p_hdr
);
523 static void update_capture_data_from_header(struct vicodec_ctx
*ctx
)
525 struct vicodec_q_data
*q_dst
= get_q_data(ctx
,
526 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
527 const struct fwht_cframe_hdr
*p_hdr
= &ctx
->state
.header
;
528 const struct v4l2_fwht_pixfmt_info
*info
= info_from_header(p_hdr
);
529 unsigned int flags
= ntohl(p_hdr
->flags
);
530 unsigned int hdr_width_div
= (flags
& FWHT_FL_CHROMA_FULL_WIDTH
) ? 1 : 2;
531 unsigned int hdr_height_div
= (flags
& FWHT_FL_CHROMA_FULL_HEIGHT
) ? 1 : 2;
534 * This function should not be used by a stateless codec since
535 * it changes values in q_data that are not request specific
537 WARN_ON(ctx
->is_stateless
);
540 q_dst
->visible_width
= ntohl(p_hdr
->width
);
541 q_dst
->visible_height
= ntohl(p_hdr
->height
);
542 q_dst
->coded_width
= vic_round_dim(q_dst
->visible_width
, hdr_width_div
);
543 q_dst
->coded_height
= vic_round_dim(q_dst
->visible_height
,
546 q_dst
->sizeimage
= q_dst
->coded_width
* q_dst
->coded_height
*
547 q_dst
->info
->sizeimage_mult
/ q_dst
->info
->sizeimage_div
;
548 ctx
->state
.colorspace
= ntohl(p_hdr
->colorspace
);
550 ctx
->state
.xfer_func
= ntohl(p_hdr
->xfer_func
);
551 ctx
->state
.ycbcr_enc
= ntohl(p_hdr
->ycbcr_enc
);
552 ctx
->state
.quantization
= ntohl(p_hdr
->quantization
);
555 static void set_last_buffer(struct vb2_v4l2_buffer
*dst_buf
,
556 const struct vb2_v4l2_buffer
*src_buf
,
557 struct vicodec_ctx
*ctx
)
559 struct vicodec_q_data
*q_dst
= get_q_data(ctx
,
560 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
562 vb2_set_plane_payload(&dst_buf
->vb2_buf
, 0, 0);
563 dst_buf
->sequence
= q_dst
->sequence
++;
565 v4l2_m2m_buf_copy_metadata(src_buf
, dst_buf
, !ctx
->is_enc
);
566 dst_buf
->flags
|= V4L2_BUF_FLAG_LAST
;
567 v4l2_m2m_buf_done(dst_buf
, VB2_BUF_STATE_DONE
);
570 static int job_ready(void *priv
)
572 static const u8 magic
[] = {
573 0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
575 struct vicodec_ctx
*ctx
= priv
;
576 struct vb2_v4l2_buffer
*src_buf
;
581 struct vicodec_q_data
*q_dst
= get_q_data(ctx
,
582 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
584 unsigned int hdr_width_div
;
585 unsigned int hdr_height_div
;
586 unsigned int max_to_copy
;
587 unsigned int comp_frame_size
;
589 if (ctx
->has_stopped
)
591 if (ctx
->source_changed
)
593 if (ctx
->is_stateless
|| ctx
->is_enc
|| ctx
->comp_has_frame
)
597 ctx
->comp_has_next_frame
= false;
598 src_buf
= v4l2_m2m_next_src_buf(ctx
->fh
.m2m_ctx
);
601 p_src
= vb2_plane_vaddr(&src_buf
->vb2_buf
, 0);
602 sz
= vb2_get_plane_payload(&src_buf
->vb2_buf
, 0);
603 p
= p_src
+ ctx
->cur_buf_offset
;
605 state
= VB2_BUF_STATE_DONE
;
607 if (ctx
->header_size
< sizeof(struct fwht_cframe_hdr
)) {
608 state
= get_next_header(ctx
, &p
, p_src
+ sz
- p
);
609 if (ctx
->header_size
< sizeof(struct fwht_cframe_hdr
)) {
610 if (ctx
->is_draining
&& src_buf
== ctx
->last_src_buf
)
612 job_remove_src_buf(ctx
, state
);
617 comp_frame_size
= ntohl(ctx
->state
.header
.size
);
620 * The current scanned frame might be the first frame of a new
621 * resolution so its size might be larger than ctx->comp_max_size.
622 * In that case it is copied up to the current buffer capacity and
623 * the copy will continue after allocating new large enough buffer
626 max_to_copy
= min(comp_frame_size
, ctx
->comp_max_size
);
628 if (ctx
->comp_size
< max_to_copy
) {
629 u32 copy
= max_to_copy
- ctx
->comp_size
;
631 if (copy
> p_src
+ sz
- p
)
632 copy
= p_src
+ sz
- p
;
634 memcpy(ctx
->state
.compressed_frame
+ ctx
->comp_size
,
637 ctx
->comp_size
+= copy
;
638 if (ctx
->comp_size
< max_to_copy
) {
639 if (ctx
->is_draining
&& src_buf
== ctx
->last_src_buf
)
641 job_remove_src_buf(ctx
, state
);
645 ctx
->cur_buf_offset
= p
- p_src
;
646 if (ctx
->comp_size
== comp_frame_size
)
647 ctx
->comp_has_frame
= true;
648 ctx
->comp_has_next_frame
= false;
649 if (ctx
->comp_has_frame
&& sz
- ctx
->cur_buf_offset
>=
650 sizeof(struct fwht_cframe_hdr
)) {
651 struct fwht_cframe_hdr
*p_hdr
= (struct fwht_cframe_hdr
*)p
;
652 u32 frame_size
= ntohl(p_hdr
->size
);
653 u32 remaining
= sz
- ctx
->cur_buf_offset
- sizeof(*p_hdr
);
655 if (!memcmp(p
, magic
, sizeof(magic
)))
656 ctx
->comp_has_next_frame
= remaining
>= frame_size
;
659 * if the header is invalid the device_run will just drop the frame
662 if (!is_header_valid(&ctx
->state
.header
) && ctx
->comp_has_frame
)
664 flags
= ntohl(ctx
->state
.header
.flags
);
665 hdr_width_div
= (flags
& FWHT_FL_CHROMA_FULL_WIDTH
) ? 1 : 2;
666 hdr_height_div
= (flags
& FWHT_FL_CHROMA_FULL_HEIGHT
) ? 1 : 2;
668 if (ntohl(ctx
->state
.header
.width
) != q_dst
->visible_width
||
669 ntohl(ctx
->state
.header
.height
) != q_dst
->visible_height
||
671 hdr_width_div
!= q_dst
->info
->width_div
||
672 hdr_height_div
!= q_dst
->info
->height_div
) {
673 static const struct v4l2_event rs_event
= {
674 .type
= V4L2_EVENT_SOURCE_CHANGE
,
675 .u
.src_change
.changes
= V4L2_EVENT_SRC_CH_RESOLUTION
,
678 struct vb2_v4l2_buffer
*dst_buf
=
679 v4l2_m2m_dst_buf_remove(ctx
->fh
.m2m_ctx
);
681 update_capture_data_from_header(ctx
);
682 v4l2_event_queue_fh(&ctx
->fh
, &rs_event
);
683 set_last_buffer(dst_buf
, src_buf
, ctx
);
684 ctx
->source_changed
= true;
694 static const struct v4l2_fwht_pixfmt_info
*find_fmt(u32 fmt
)
696 const struct v4l2_fwht_pixfmt_info
*info
=
697 v4l2_fwht_find_pixfmt(fmt
);
700 info
= v4l2_fwht_get_pixfmt(0);
704 static int vidioc_querycap(struct file
*file
, void *priv
,
705 struct v4l2_capability
*cap
)
707 strscpy(cap
->driver
, VICODEC_NAME
, sizeof(cap
->driver
));
708 strscpy(cap
->card
, VICODEC_NAME
, sizeof(cap
->card
));
709 snprintf(cap
->bus_info
, sizeof(cap
->bus_info
),
710 "platform:%s", VICODEC_NAME
);
714 static int enum_fmt(struct v4l2_fmtdesc
*f
, struct vicodec_ctx
*ctx
,
717 bool is_uncomp
= (ctx
->is_enc
&& is_out
) || (!ctx
->is_enc
&& !is_out
);
719 if (V4L2_TYPE_IS_MULTIPLANAR(f
->type
) && !multiplanar
)
721 if (!V4L2_TYPE_IS_MULTIPLANAR(f
->type
) && multiplanar
)
725 const struct v4l2_fwht_pixfmt_info
*info
=
726 get_q_data(ctx
, f
->type
)->info
;
729 !vb2_is_streaming(&ctx
->fh
.m2m_ctx
->cap_q_ctx
.q
))
730 info
= v4l2_fwht_get_pixfmt(f
->index
);
732 info
= v4l2_fwht_find_nth_fmt(info
->width_div
,
734 info
->components_num
,
739 f
->pixelformat
= info
->id
;
743 f
->pixelformat
= ctx
->is_stateless
?
744 V4L2_PIX_FMT_FWHT_STATELESS
: V4L2_PIX_FMT_FWHT
;
745 if (!ctx
->is_enc
&& !ctx
->is_stateless
)
746 f
->flags
= V4L2_FMT_FLAG_DYN_RESOLUTION
|
747 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM
;
752 static int vidioc_enum_fmt_vid_cap(struct file
*file
, void *priv
,
753 struct v4l2_fmtdesc
*f
)
755 struct vicodec_ctx
*ctx
= file2ctx(file
);
757 return enum_fmt(f
, ctx
, false);
760 static int vidioc_enum_fmt_vid_out(struct file
*file
, void *priv
,
761 struct v4l2_fmtdesc
*f
)
763 struct vicodec_ctx
*ctx
= file2ctx(file
);
765 return enum_fmt(f
, ctx
, true);
768 static int vidioc_g_fmt(struct vicodec_ctx
*ctx
, struct v4l2_format
*f
)
770 struct vb2_queue
*vq
;
771 struct vicodec_q_data
*q_data
;
772 struct v4l2_pix_format_mplane
*pix_mp
;
773 struct v4l2_pix_format
*pix
;
774 const struct v4l2_fwht_pixfmt_info
*info
;
776 vq
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
, f
->type
);
780 q_data
= get_q_data(ctx
, f
->type
);
784 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
785 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
789 pix
->width
= q_data
->coded_width
;
790 pix
->height
= q_data
->coded_height
;
791 pix
->field
= V4L2_FIELD_NONE
;
792 pix
->pixelformat
= info
->id
;
793 pix
->bytesperline
= q_data
->coded_width
*
794 info
->bytesperline_mult
;
795 pix
->sizeimage
= q_data
->sizeimage
;
796 pix
->colorspace
= ctx
->state
.colorspace
;
797 pix
->xfer_func
= ctx
->state
.xfer_func
;
798 pix
->ycbcr_enc
= ctx
->state
.ycbcr_enc
;
799 pix
->quantization
= ctx
->state
.quantization
;
802 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
803 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
806 pix_mp
= &f
->fmt
.pix_mp
;
807 pix_mp
->width
= q_data
->coded_width
;
808 pix_mp
->height
= q_data
->coded_height
;
809 pix_mp
->field
= V4L2_FIELD_NONE
;
810 pix_mp
->pixelformat
= info
->id
;
811 pix_mp
->num_planes
= 1;
812 pix_mp
->plane_fmt
[0].bytesperline
=
813 q_data
->coded_width
* info
->bytesperline_mult
;
814 pix_mp
->plane_fmt
[0].sizeimage
= q_data
->sizeimage
;
815 pix_mp
->colorspace
= ctx
->state
.colorspace
;
816 pix_mp
->xfer_func
= ctx
->state
.xfer_func
;
817 pix_mp
->ycbcr_enc
= ctx
->state
.ycbcr_enc
;
818 pix_mp
->quantization
= ctx
->state
.quantization
;
819 memset(pix_mp
->reserved
, 0, sizeof(pix_mp
->reserved
));
820 memset(pix_mp
->plane_fmt
[0].reserved
, 0,
821 sizeof(pix_mp
->plane_fmt
[0].reserved
));
829 static int vidioc_g_fmt_vid_out(struct file
*file
, void *priv
,
830 struct v4l2_format
*f
)
832 return vidioc_g_fmt(file2ctx(file
), f
);
835 static int vidioc_g_fmt_vid_cap(struct file
*file
, void *priv
,
836 struct v4l2_format
*f
)
838 return vidioc_g_fmt(file2ctx(file
), f
);
841 static int vidioc_try_fmt(struct vicodec_ctx
*ctx
, struct v4l2_format
*f
)
843 struct v4l2_pix_format_mplane
*pix_mp
;
844 struct v4l2_pix_format
*pix
;
845 struct v4l2_plane_pix_format
*plane
;
846 const struct v4l2_fwht_pixfmt_info
*info
= ctx
->is_stateless
?
847 &pixfmt_stateless_fwht
: &pixfmt_fwht
;
850 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
851 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
853 if (pix
->pixelformat
!= V4L2_PIX_FMT_FWHT
&&
854 pix
->pixelformat
!= V4L2_PIX_FMT_FWHT_STATELESS
)
855 info
= find_fmt(pix
->pixelformat
);
857 pix
->width
= clamp(pix
->width
, MIN_WIDTH
, MAX_WIDTH
);
858 pix
->width
= vic_round_dim(pix
->width
, info
->width_div
);
860 pix
->height
= clamp(pix
->height
, MIN_HEIGHT
, MAX_HEIGHT
);
861 pix
->height
= vic_round_dim(pix
->height
, info
->height_div
);
863 pix
->field
= V4L2_FIELD_NONE
;
865 pix
->width
* info
->bytesperline_mult
;
866 pix
->sizeimage
= pix
->width
* pix
->height
*
867 info
->sizeimage_mult
/ info
->sizeimage_div
;
868 if (pix
->pixelformat
== V4L2_PIX_FMT_FWHT
)
869 pix
->sizeimage
+= sizeof(struct fwht_cframe_hdr
);
871 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
872 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
873 pix_mp
= &f
->fmt
.pix_mp
;
874 plane
= pix_mp
->plane_fmt
;
875 if (pix_mp
->pixelformat
!= V4L2_PIX_FMT_FWHT
&&
876 pix_mp
->pixelformat
!= V4L2_PIX_FMT_FWHT_STATELESS
)
877 info
= find_fmt(pix_mp
->pixelformat
);
878 pix_mp
->num_planes
= 1;
880 pix_mp
->width
= clamp(pix_mp
->width
, MIN_WIDTH
, MAX_WIDTH
);
881 pix_mp
->width
= vic_round_dim(pix_mp
->width
, info
->width_div
);
883 pix_mp
->height
= clamp(pix_mp
->height
, MIN_HEIGHT
, MAX_HEIGHT
);
884 pix_mp
->height
= vic_round_dim(pix_mp
->height
,
887 pix_mp
->field
= V4L2_FIELD_NONE
;
888 plane
->bytesperline
=
889 pix_mp
->width
* info
->bytesperline_mult
;
890 plane
->sizeimage
= pix_mp
->width
* pix_mp
->height
*
891 info
->sizeimage_mult
/ info
->sizeimage_div
;
892 if (pix_mp
->pixelformat
== V4L2_PIX_FMT_FWHT
)
893 plane
->sizeimage
+= sizeof(struct fwht_cframe_hdr
);
894 memset(pix_mp
->reserved
, 0, sizeof(pix_mp
->reserved
));
895 memset(plane
->reserved
, 0, sizeof(plane
->reserved
));
904 static int vidioc_try_fmt_vid_cap(struct file
*file
, void *priv
,
905 struct v4l2_format
*f
)
907 struct vicodec_ctx
*ctx
= file2ctx(file
);
908 struct v4l2_pix_format_mplane
*pix_mp
;
909 struct v4l2_pix_format
*pix
;
912 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
916 pix
->pixelformat
= ctx
->is_enc
? V4L2_PIX_FMT_FWHT
:
917 find_fmt(f
->fmt
.pix
.pixelformat
)->id
;
918 pix
->colorspace
= ctx
->state
.colorspace
;
919 pix
->xfer_func
= ctx
->state
.xfer_func
;
920 pix
->ycbcr_enc
= ctx
->state
.ycbcr_enc
;
921 pix
->quantization
= ctx
->state
.quantization
;
923 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
926 pix_mp
= &f
->fmt
.pix_mp
;
927 pix_mp
->pixelformat
= ctx
->is_enc
? V4L2_PIX_FMT_FWHT
:
928 find_fmt(pix_mp
->pixelformat
)->id
;
929 pix_mp
->colorspace
= ctx
->state
.colorspace
;
930 pix_mp
->xfer_func
= ctx
->state
.xfer_func
;
931 pix_mp
->ycbcr_enc
= ctx
->state
.ycbcr_enc
;
932 pix_mp
->quantization
= ctx
->state
.quantization
;
938 return vidioc_try_fmt(ctx
, f
);
941 static int vidioc_try_fmt_vid_out(struct file
*file
, void *priv
,
942 struct v4l2_format
*f
)
944 struct vicodec_ctx
*ctx
= file2ctx(file
);
945 struct v4l2_pix_format_mplane
*pix_mp
;
946 struct v4l2_pix_format
*pix
;
949 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
954 pix
->pixelformat
= find_fmt(pix
->pixelformat
)->id
;
955 else if (ctx
->is_stateless
)
956 pix
->pixelformat
= V4L2_PIX_FMT_FWHT_STATELESS
;
958 pix
->pixelformat
= V4L2_PIX_FMT_FWHT
;
959 if (!pix
->colorspace
)
960 pix
->colorspace
= V4L2_COLORSPACE_REC709
;
962 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
965 pix_mp
= &f
->fmt
.pix_mp
;
967 pix_mp
->pixelformat
= find_fmt(pix_mp
->pixelformat
)->id
;
968 else if (ctx
->is_stateless
)
969 pix_mp
->pixelformat
= V4L2_PIX_FMT_FWHT_STATELESS
;
971 pix_mp
->pixelformat
= V4L2_PIX_FMT_FWHT
;
972 if (!pix_mp
->colorspace
)
973 pix_mp
->colorspace
= V4L2_COLORSPACE_REC709
;
979 return vidioc_try_fmt(ctx
, f
);
982 static int vidioc_s_fmt(struct vicodec_ctx
*ctx
, struct v4l2_format
*f
)
984 struct vicodec_q_data
*q_data
;
985 struct vb2_queue
*vq
;
986 bool fmt_changed
= true;
987 struct v4l2_pix_format_mplane
*pix_mp
;
988 struct v4l2_pix_format
*pix
;
990 vq
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
, f
->type
);
994 q_data
= get_q_data(ctx
, f
->type
);
999 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
1000 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
1002 if (ctx
->is_enc
&& V4L2_TYPE_IS_OUTPUT(f
->type
))
1005 q_data
->info
->id
!= pix
->pixelformat
||
1006 q_data
->coded_width
!= pix
->width
||
1007 q_data
->coded_height
!= pix
->height
;
1009 if (vb2_is_busy(vq
) && fmt_changed
)
1012 if (pix
->pixelformat
== V4L2_PIX_FMT_FWHT
)
1013 q_data
->info
= &pixfmt_fwht
;
1014 else if (pix
->pixelformat
== V4L2_PIX_FMT_FWHT_STATELESS
)
1015 q_data
->info
= &pixfmt_stateless_fwht
;
1017 q_data
->info
= find_fmt(pix
->pixelformat
);
1018 q_data
->coded_width
= pix
->width
;
1019 q_data
->coded_height
= pix
->height
;
1020 q_data
->sizeimage
= pix
->sizeimage
;
1022 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
1023 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
1024 pix_mp
= &f
->fmt
.pix_mp
;
1025 if (ctx
->is_enc
&& V4L2_TYPE_IS_OUTPUT(f
->type
))
1028 q_data
->info
->id
!= pix_mp
->pixelformat
||
1029 q_data
->coded_width
!= pix_mp
->width
||
1030 q_data
->coded_height
!= pix_mp
->height
;
1032 if (vb2_is_busy(vq
) && fmt_changed
)
1035 if (pix_mp
->pixelformat
== V4L2_PIX_FMT_FWHT
)
1036 q_data
->info
= &pixfmt_fwht
;
1037 else if (pix_mp
->pixelformat
== V4L2_PIX_FMT_FWHT_STATELESS
)
1038 q_data
->info
= &pixfmt_stateless_fwht
;
1040 q_data
->info
= find_fmt(pix_mp
->pixelformat
);
1041 q_data
->coded_width
= pix_mp
->width
;
1042 q_data
->coded_height
= pix_mp
->height
;
1043 q_data
->sizeimage
= pix_mp
->plane_fmt
[0].sizeimage
;
1050 "Setting format for type %d, coded wxh: %dx%d, fourcc: 0x%08x\n",
1051 f
->type
, q_data
->coded_width
, q_data
->coded_height
,
1057 static int vidioc_s_fmt_vid_cap(struct file
*file
, void *priv
,
1058 struct v4l2_format
*f
)
1062 ret
= vidioc_try_fmt_vid_cap(file
, priv
, f
);
1066 return vidioc_s_fmt(file2ctx(file
), f
);
1069 static int vidioc_s_fmt_vid_out(struct file
*file
, void *priv
,
1070 struct v4l2_format
*f
)
1072 struct vicodec_ctx
*ctx
= file2ctx(file
);
1073 struct vicodec_q_data
*q_data
;
1074 struct vicodec_q_data
*q_data_cap
;
1075 struct v4l2_pix_format
*pix
;
1076 struct v4l2_pix_format_mplane
*pix_mp
;
1077 u32 coded_w
= 0, coded_h
= 0;
1078 unsigned int size
= 0;
1081 q_data
= get_q_data(ctx
, f
->type
);
1082 q_data_cap
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_CAPTURE
);
1084 ret
= vidioc_try_fmt_vid_out(file
, priv
, f
);
1089 struct vb2_queue
*vq
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
, f
->type
);
1090 struct vb2_queue
*vq_cap
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
,
1091 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
1092 const struct v4l2_fwht_pixfmt_info
*info
= ctx
->is_stateless
?
1093 &pixfmt_stateless_fwht
: &pixfmt_fwht
;
1095 if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT
) {
1096 coded_w
= f
->fmt
.pix
.width
;
1097 coded_h
= f
->fmt
.pix
.height
;
1099 coded_w
= f
->fmt
.pix_mp
.width
;
1100 coded_h
= f
->fmt
.pix_mp
.height
;
1102 if (vb2_is_busy(vq
) && (coded_w
!= q_data
->coded_width
||
1103 coded_h
!= q_data
->coded_height
))
1105 size
= coded_w
* coded_h
*
1106 info
->sizeimage_mult
/ info
->sizeimage_div
;
1107 if (!ctx
->is_stateless
)
1108 size
+= sizeof(struct fwht_cframe_hdr
);
1110 if (vb2_is_busy(vq_cap
) && size
> q_data_cap
->sizeimage
)
1114 ret
= vidioc_s_fmt(file2ctx(file
), f
);
1117 q_data
->visible_width
= coded_w
;
1118 q_data
->visible_height
= coded_h
;
1119 q_data_cap
->coded_width
= coded_w
;
1120 q_data_cap
->coded_height
= coded_h
;
1121 q_data_cap
->sizeimage
= size
;
1125 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
1127 ctx
->state
.colorspace
= pix
->colorspace
;
1128 ctx
->state
.xfer_func
= pix
->xfer_func
;
1129 ctx
->state
.ycbcr_enc
= pix
->ycbcr_enc
;
1130 ctx
->state
.quantization
= pix
->quantization
;
1132 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
1133 pix_mp
= &f
->fmt
.pix_mp
;
1134 ctx
->state
.colorspace
= pix_mp
->colorspace
;
1135 ctx
->state
.xfer_func
= pix_mp
->xfer_func
;
1136 ctx
->state
.ycbcr_enc
= pix_mp
->ycbcr_enc
;
1137 ctx
->state
.quantization
= pix_mp
->quantization
;
1146 static int vidioc_g_selection(struct file
*file
, void *priv
,
1147 struct v4l2_selection
*s
)
1149 struct vicodec_ctx
*ctx
= file2ctx(file
);
1150 struct vicodec_q_data
*q_data
;
1152 q_data
= get_q_data(ctx
, s
->type
);
1156 * encoder supports only cropping on the OUTPUT buffer
1157 * decoder supports only composing on the CAPTURE buffer
1159 if (ctx
->is_enc
&& s
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT
) {
1160 switch (s
->target
) {
1161 case V4L2_SEL_TGT_CROP
:
1164 s
->r
.width
= q_data
->visible_width
;
1165 s
->r
.height
= q_data
->visible_height
;
1167 case V4L2_SEL_TGT_CROP_DEFAULT
:
1168 case V4L2_SEL_TGT_CROP_BOUNDS
:
1171 s
->r
.width
= q_data
->coded_width
;
1172 s
->r
.height
= q_data
->coded_height
;
1175 } else if (!ctx
->is_enc
&& s
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
1176 switch (s
->target
) {
1177 case V4L2_SEL_TGT_COMPOSE
:
1180 s
->r
.width
= q_data
->visible_width
;
1181 s
->r
.height
= q_data
->visible_height
;
1183 case V4L2_SEL_TGT_COMPOSE_DEFAULT
:
1184 case V4L2_SEL_TGT_COMPOSE_BOUNDS
:
1187 s
->r
.width
= q_data
->coded_width
;
1188 s
->r
.height
= q_data
->coded_height
;
1195 static int vidioc_s_selection(struct file
*file
, void *priv
,
1196 struct v4l2_selection
*s
)
1198 struct vicodec_ctx
*ctx
= file2ctx(file
);
1199 struct vicodec_q_data
*q_data
;
1201 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT
)
1204 q_data
= get_q_data(ctx
, s
->type
);
1208 if (!ctx
->is_enc
|| s
->target
!= V4L2_SEL_TGT_CROP
)
1213 q_data
->visible_width
= clamp(s
->r
.width
, MIN_WIDTH
,
1214 q_data
->coded_width
);
1215 s
->r
.width
= q_data
->visible_width
;
1216 q_data
->visible_height
= clamp(s
->r
.height
, MIN_HEIGHT
,
1217 q_data
->coded_height
);
1218 s
->r
.height
= q_data
->visible_height
;
1222 static int vicodec_mark_last_buf(struct vicodec_ctx
*ctx
)
1224 struct vb2_v4l2_buffer
*next_dst_buf
;
1227 spin_lock(ctx
->lock
);
1228 if (ctx
->is_draining
) {
1232 if (ctx
->has_stopped
)
1235 ctx
->last_src_buf
= v4l2_m2m_last_src_buf(ctx
->fh
.m2m_ctx
);
1236 ctx
->is_draining
= true;
1237 if (ctx
->last_src_buf
)
1240 next_dst_buf
= v4l2_m2m_dst_buf_remove(ctx
->fh
.m2m_ctx
);
1241 if (!next_dst_buf
) {
1242 ctx
->next_is_last
= true;
1246 next_dst_buf
->flags
|= V4L2_BUF_FLAG_LAST
;
1247 vb2_buffer_done(&next_dst_buf
->vb2_buf
, VB2_BUF_STATE_DONE
);
1248 ctx
->is_draining
= false;
1249 ctx
->has_stopped
= true;
1250 v4l2_event_queue_fh(&ctx
->fh
, &vicodec_eos_event
);
1253 spin_unlock(ctx
->lock
);
1257 static int vicodec_encoder_cmd(struct file
*file
, void *fh
,
1258 struct v4l2_encoder_cmd
*ec
)
1260 struct vicodec_ctx
*ctx
= file2ctx(file
);
1263 ret
= v4l2_m2m_ioctl_try_encoder_cmd(file
, fh
, ec
);
1267 if (!vb2_is_streaming(&ctx
->fh
.m2m_ctx
->cap_q_ctx
.q
) ||
1268 !vb2_is_streaming(&ctx
->fh
.m2m_ctx
->out_q_ctx
.q
))
1271 if (ec
->cmd
== V4L2_ENC_CMD_STOP
)
1272 return vicodec_mark_last_buf(ctx
);
1274 spin_lock(ctx
->lock
);
1275 if (ctx
->is_draining
) {
1277 } else if (ctx
->has_stopped
) {
1278 ctx
->has_stopped
= false;
1279 vb2_clear_last_buffer_dequeued(&ctx
->fh
.m2m_ctx
->cap_q_ctx
.q
);
1281 spin_unlock(ctx
->lock
);
1285 static int vicodec_decoder_cmd(struct file
*file
, void *fh
,
1286 struct v4l2_decoder_cmd
*dc
)
1288 struct vicodec_ctx
*ctx
= file2ctx(file
);
1291 ret
= v4l2_m2m_ioctl_try_decoder_cmd(file
, fh
, dc
);
1295 if (!vb2_is_streaming(&ctx
->fh
.m2m_ctx
->cap_q_ctx
.q
) ||
1296 !vb2_is_streaming(&ctx
->fh
.m2m_ctx
->out_q_ctx
.q
))
1299 if (dc
->cmd
== V4L2_DEC_CMD_STOP
)
1300 return vicodec_mark_last_buf(ctx
);
1302 spin_lock(ctx
->lock
);
1303 if (ctx
->is_draining
) {
1305 } else if (ctx
->has_stopped
) {
1306 ctx
->has_stopped
= false;
1307 vb2_clear_last_buffer_dequeued(&ctx
->fh
.m2m_ctx
->cap_q_ctx
.q
);
1309 spin_unlock(ctx
->lock
);
1313 static int vicodec_enum_framesizes(struct file
*file
, void *fh
,
1314 struct v4l2_frmsizeenum
*fsize
)
1316 switch (fsize
->pixel_format
) {
1317 case V4L2_PIX_FMT_FWHT_STATELESS
:
1319 case V4L2_PIX_FMT_FWHT
:
1322 if (find_fmt(fsize
->pixel_format
)->id
== fsize
->pixel_format
)
1330 fsize
->type
= V4L2_FRMSIZE_TYPE_STEPWISE
;
1332 fsize
->stepwise
.min_width
= MIN_WIDTH
;
1333 fsize
->stepwise
.max_width
= MAX_WIDTH
;
1334 fsize
->stepwise
.step_width
= 8;
1335 fsize
->stepwise
.min_height
= MIN_HEIGHT
;
1336 fsize
->stepwise
.max_height
= MAX_HEIGHT
;
1337 fsize
->stepwise
.step_height
= 8;
1342 static int vicodec_subscribe_event(struct v4l2_fh
*fh
,
1343 const struct v4l2_event_subscription
*sub
)
1345 struct vicodec_ctx
*ctx
= container_of(fh
, struct vicodec_ctx
, fh
);
1347 switch (sub
->type
) {
1348 case V4L2_EVENT_SOURCE_CHANGE
:
1352 case V4L2_EVENT_EOS
:
1353 if (ctx
->is_stateless
)
1355 return v4l2_event_subscribe(fh
, sub
, 0, NULL
);
1357 return v4l2_ctrl_subscribe_event(fh
, sub
);
1361 static const struct v4l2_ioctl_ops vicodec_ioctl_ops
= {
1362 .vidioc_querycap
= vidioc_querycap
,
1364 .vidioc_enum_fmt_vid_cap
= vidioc_enum_fmt_vid_cap
,
1365 .vidioc_g_fmt_vid_cap
= vidioc_g_fmt_vid_cap
,
1366 .vidioc_try_fmt_vid_cap
= vidioc_try_fmt_vid_cap
,
1367 .vidioc_s_fmt_vid_cap
= vidioc_s_fmt_vid_cap
,
1369 .vidioc_g_fmt_vid_cap_mplane
= vidioc_g_fmt_vid_cap
,
1370 .vidioc_try_fmt_vid_cap_mplane
= vidioc_try_fmt_vid_cap
,
1371 .vidioc_s_fmt_vid_cap_mplane
= vidioc_s_fmt_vid_cap
,
1373 .vidioc_enum_fmt_vid_out
= vidioc_enum_fmt_vid_out
,
1374 .vidioc_g_fmt_vid_out
= vidioc_g_fmt_vid_out
,
1375 .vidioc_try_fmt_vid_out
= vidioc_try_fmt_vid_out
,
1376 .vidioc_s_fmt_vid_out
= vidioc_s_fmt_vid_out
,
1378 .vidioc_g_fmt_vid_out_mplane
= vidioc_g_fmt_vid_out
,
1379 .vidioc_try_fmt_vid_out_mplane
= vidioc_try_fmt_vid_out
,
1380 .vidioc_s_fmt_vid_out_mplane
= vidioc_s_fmt_vid_out
,
1382 .vidioc_reqbufs
= v4l2_m2m_ioctl_reqbufs
,
1383 .vidioc_querybuf
= v4l2_m2m_ioctl_querybuf
,
1384 .vidioc_qbuf
= v4l2_m2m_ioctl_qbuf
,
1385 .vidioc_dqbuf
= v4l2_m2m_ioctl_dqbuf
,
1386 .vidioc_prepare_buf
= v4l2_m2m_ioctl_prepare_buf
,
1387 .vidioc_create_bufs
= v4l2_m2m_ioctl_create_bufs
,
1388 .vidioc_expbuf
= v4l2_m2m_ioctl_expbuf
,
1390 .vidioc_streamon
= v4l2_m2m_ioctl_streamon
,
1391 .vidioc_streamoff
= v4l2_m2m_ioctl_streamoff
,
1393 .vidioc_g_selection
= vidioc_g_selection
,
1394 .vidioc_s_selection
= vidioc_s_selection
,
1396 .vidioc_try_encoder_cmd
= v4l2_m2m_ioctl_try_encoder_cmd
,
1397 .vidioc_encoder_cmd
= vicodec_encoder_cmd
,
1398 .vidioc_try_decoder_cmd
= v4l2_m2m_ioctl_try_decoder_cmd
,
1399 .vidioc_decoder_cmd
= vicodec_decoder_cmd
,
1400 .vidioc_enum_framesizes
= vicodec_enum_framesizes
,
1402 .vidioc_subscribe_event
= vicodec_subscribe_event
,
1403 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
1411 static int vicodec_queue_setup(struct vb2_queue
*vq
, unsigned int *nbuffers
,
1412 unsigned int *nplanes
, unsigned int sizes
[],
1413 struct device
*alloc_devs
[])
1415 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(vq
);
1416 struct vicodec_q_data
*q_data
= get_q_data(ctx
, vq
->type
);
1417 unsigned int size
= q_data
->sizeimage
;
1420 return sizes
[0] < size
? -EINVAL
: 0;
1424 q_data
->vb2_sizeimage
= size
;
1428 static int vicodec_buf_out_validate(struct vb2_buffer
*vb
)
1430 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1432 vbuf
->field
= V4L2_FIELD_NONE
;
1436 static int vicodec_buf_prepare(struct vb2_buffer
*vb
)
1438 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1439 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1440 struct vicodec_q_data
*q_data
;
1442 dprintk(ctx
->dev
, "type: %d\n", vb
->vb2_queue
->type
);
1444 q_data
= get_q_data(ctx
, vb
->vb2_queue
->type
);
1445 if (V4L2_TYPE_IS_OUTPUT(vb
->vb2_queue
->type
)) {
1446 if (vbuf
->field
== V4L2_FIELD_ANY
)
1447 vbuf
->field
= V4L2_FIELD_NONE
;
1448 if (vbuf
->field
!= V4L2_FIELD_NONE
) {
1449 dprintk(ctx
->dev
, "%s field isn't supported\n",
1455 if (vb2_plane_size(vb
, 0) < q_data
->vb2_sizeimage
) {
1457 "%s data will not fit into plane (%lu < %lu)\n",
1458 __func__
, vb2_plane_size(vb
, 0),
1459 (long)q_data
->vb2_sizeimage
);
1466 static void vicodec_buf_queue(struct vb2_buffer
*vb
)
1468 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1469 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1470 unsigned int sz
= vb2_get_plane_payload(&vbuf
->vb2_buf
, 0);
1471 u8
*p_src
= vb2_plane_vaddr(&vbuf
->vb2_buf
, 0);
1473 struct vb2_queue
*vq_out
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
,
1474 V4L2_BUF_TYPE_VIDEO_OUTPUT
);
1475 struct vb2_queue
*vq_cap
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
,
1476 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
1477 bool header_valid
= false;
1478 static const struct v4l2_event rs_event
= {
1479 .type
= V4L2_EVENT_SOURCE_CHANGE
,
1480 .u
.src_change
.changes
= V4L2_EVENT_SRC_CH_RESOLUTION
,
1483 if (vb2_is_streaming(vq_cap
)) {
1484 if (!V4L2_TYPE_IS_OUTPUT(vb
->vb2_queue
->type
) &&
1485 ctx
->next_is_last
) {
1488 for (i
= 0; i
< vb
->num_planes
; i
++)
1489 vb
->planes
[i
].bytesused
= 0;
1490 vbuf
->flags
= V4L2_BUF_FLAG_LAST
;
1491 vbuf
->field
= V4L2_FIELD_NONE
;
1492 vbuf
->sequence
= get_q_data(ctx
, vb
->vb2_queue
->type
)->sequence
++;
1493 vb2_buffer_done(vb
, VB2_BUF_STATE_DONE
);
1494 ctx
->is_draining
= false;
1495 ctx
->has_stopped
= true;
1496 ctx
->next_is_last
= false;
1497 v4l2_event_queue_fh(&ctx
->fh
, &vicodec_eos_event
);
1502 /* buf_queue handles only the first source change event */
1503 if (ctx
->first_source_change_sent
) {
1504 v4l2_m2m_buf_queue(ctx
->fh
.m2m_ctx
, vbuf
);
1509 * if both queues are streaming, the source change event is
1510 * handled in job_ready
1512 if (vb2_is_streaming(vq_cap
) && vb2_is_streaming(vq_out
)) {
1513 v4l2_m2m_buf_queue(ctx
->fh
.m2m_ctx
, vbuf
);
1518 * source change event is relevant only for the stateful decoder
1519 * in the compressed stream
1521 if (ctx
->is_stateless
|| ctx
->is_enc
||
1522 !V4L2_TYPE_IS_OUTPUT(vb
->vb2_queue
->type
)) {
1523 v4l2_m2m_buf_queue(ctx
->fh
.m2m_ctx
, vbuf
);
1528 enum vb2_buffer_state state
=
1529 get_next_header(ctx
, &p
, p_src
+ sz
- p
);
1531 if (ctx
->header_size
< sizeof(struct fwht_cframe_hdr
)) {
1532 v4l2_m2m_buf_done(vbuf
, state
);
1535 header_valid
= is_header_valid(&ctx
->state
.header
);
1537 * p points right after the end of the header in the
1538 * buffer. If the header is invalid we set p to point
1539 * to the next byte after the start of the header
1541 if (!header_valid
) {
1542 p
= p
- sizeof(struct fwht_cframe_hdr
) + 1;
1545 ctx
->header_size
= 0;
1546 ctx
->comp_magic_cnt
= 0;
1549 } while (!header_valid
);
1551 ctx
->cur_buf_offset
= p
- p_src
;
1552 update_capture_data_from_header(ctx
);
1553 ctx
->first_source_change_sent
= true;
1554 v4l2_event_queue_fh(&ctx
->fh
, &rs_event
);
1555 v4l2_m2m_buf_queue(ctx
->fh
.m2m_ctx
, vbuf
);
1558 static void vicodec_return_bufs(struct vb2_queue
*q
, u32 state
)
1560 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(q
);
1561 struct vb2_v4l2_buffer
*vbuf
;
1564 if (V4L2_TYPE_IS_OUTPUT(q
->type
))
1565 vbuf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
1567 vbuf
= v4l2_m2m_dst_buf_remove(ctx
->fh
.m2m_ctx
);
1570 v4l2_ctrl_request_complete(vbuf
->vb2_buf
.req_obj
.req
,
1572 spin_lock(ctx
->lock
);
1573 v4l2_m2m_buf_done(vbuf
, state
);
1574 spin_unlock(ctx
->lock
);
1578 static unsigned int total_frame_size(struct vicodec_q_data
*q_data
)
1581 unsigned int chroma_div
;
1583 if (!q_data
->info
) {
1587 size
= q_data
->coded_width
* q_data
->coded_height
;
1588 chroma_div
= q_data
->info
->width_div
* q_data
->info
->height_div
;
1590 if (q_data
->info
->components_num
== 4)
1591 return 2 * size
+ 2 * (size
/ chroma_div
);
1592 else if (q_data
->info
->components_num
== 3)
1593 return size
+ 2 * (size
/ chroma_div
);
1597 static int vicodec_start_streaming(struct vb2_queue
*q
,
1600 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(q
);
1601 struct vicodec_q_data
*q_data
= get_q_data(ctx
, q
->type
);
1602 struct v4l2_fwht_state
*state
= &ctx
->state
;
1603 const struct v4l2_fwht_pixfmt_info
*info
= q_data
->info
;
1604 unsigned int size
= q_data
->coded_width
* q_data
->coded_height
;
1605 unsigned int chroma_div
;
1606 unsigned int total_planes_size
;
1607 u8
*new_comp_frame
= NULL
;
1609 chroma_div
= info
->width_div
* info
->height_div
;
1610 q_data
->sequence
= 0;
1612 if (V4L2_TYPE_IS_OUTPUT(q
->type
))
1613 ctx
->last_src_buf
= NULL
;
1617 if ((V4L2_TYPE_IS_OUTPUT(q
->type
) && !ctx
->is_enc
) ||
1618 (!V4L2_TYPE_IS_OUTPUT(q
->type
) && ctx
->is_enc
))
1621 if (info
->id
== V4L2_PIX_FMT_FWHT
||
1622 info
->id
== V4L2_PIX_FMT_FWHT_STATELESS
) {
1623 vicodec_return_bufs(q
, VB2_BUF_STATE_QUEUED
);
1626 total_planes_size
= total_frame_size(q_data
);
1627 ctx
->comp_max_size
= total_planes_size
;
1629 state
->visible_width
= q_data
->visible_width
;
1630 state
->visible_height
= q_data
->visible_height
;
1631 state
->coded_width
= q_data
->coded_width
;
1632 state
->coded_height
= q_data
->coded_height
;
1633 state
->stride
= q_data
->coded_width
*
1634 info
->bytesperline_mult
;
1636 if (ctx
->is_stateless
) {
1637 state
->ref_stride
= state
->stride
;
1640 state
->ref_stride
= q_data
->coded_width
* info
->luma_alpha_step
;
1642 state
->ref_frame
.buf
= kvmalloc(total_planes_size
, GFP_KERNEL
);
1643 state
->ref_frame
.luma
= state
->ref_frame
.buf
;
1644 new_comp_frame
= kvmalloc(ctx
->comp_max_size
, GFP_KERNEL
);
1646 if (!state
->ref_frame
.luma
|| !new_comp_frame
) {
1647 kvfree(state
->ref_frame
.luma
);
1648 kvfree(new_comp_frame
);
1649 vicodec_return_bufs(q
, VB2_BUF_STATE_QUEUED
);
1653 * if state->compressed_frame was already allocated then
1654 * it contain data of the first frame of the new resolution
1656 if (state
->compressed_frame
) {
1657 if (ctx
->comp_size
> ctx
->comp_max_size
)
1658 ctx
->comp_size
= ctx
->comp_max_size
;
1660 memcpy(new_comp_frame
,
1661 state
->compressed_frame
, ctx
->comp_size
);
1664 kvfree(state
->compressed_frame
);
1665 state
->compressed_frame
= new_comp_frame
;
1667 if (info
->components_num
< 3) {
1668 state
->ref_frame
.cb
= NULL
;
1669 state
->ref_frame
.cr
= NULL
;
1670 state
->ref_frame
.alpha
= NULL
;
1674 state
->ref_frame
.cb
= state
->ref_frame
.luma
+ size
;
1675 state
->ref_frame
.cr
= state
->ref_frame
.cb
+ size
/ chroma_div
;
1677 if (info
->components_num
== 4)
1678 state
->ref_frame
.alpha
=
1679 state
->ref_frame
.cr
+ size
/ chroma_div
;
1681 state
->ref_frame
.alpha
= NULL
;
1686 static void vicodec_stop_streaming(struct vb2_queue
*q
)
1688 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(q
);
1690 vicodec_return_bufs(q
, VB2_BUF_STATE_ERROR
);
1692 if (V4L2_TYPE_IS_OUTPUT(q
->type
)) {
1693 if (ctx
->is_draining
) {
1694 struct vb2_v4l2_buffer
*next_dst_buf
;
1696 spin_lock(ctx
->lock
);
1697 ctx
->last_src_buf
= NULL
;
1698 next_dst_buf
= v4l2_m2m_dst_buf_remove(ctx
->fh
.m2m_ctx
);
1699 if (!next_dst_buf
) {
1700 ctx
->next_is_last
= true;
1702 next_dst_buf
->flags
|= V4L2_BUF_FLAG_LAST
;
1703 vb2_buffer_done(&next_dst_buf
->vb2_buf
, VB2_BUF_STATE_DONE
);
1704 ctx
->is_draining
= false;
1705 ctx
->has_stopped
= true;
1706 v4l2_event_queue_fh(&ctx
->fh
, &vicodec_eos_event
);
1708 spin_unlock(ctx
->lock
);
1711 ctx
->is_draining
= false;
1712 ctx
->has_stopped
= false;
1713 ctx
->next_is_last
= false;
1715 if (!ctx
->is_enc
&& V4L2_TYPE_IS_OUTPUT(q
->type
))
1716 ctx
->first_source_change_sent
= false;
1718 if ((!V4L2_TYPE_IS_OUTPUT(q
->type
) && !ctx
->is_enc
) ||
1719 (V4L2_TYPE_IS_OUTPUT(q
->type
) && ctx
->is_enc
)) {
1720 if (!ctx
->is_stateless
)
1721 kvfree(ctx
->state
.ref_frame
.buf
);
1722 ctx
->state
.ref_frame
.buf
= NULL
;
1723 ctx
->state
.ref_frame
.luma
= NULL
;
1724 ctx
->comp_max_size
= 0;
1725 ctx
->source_changed
= false;
1727 if (V4L2_TYPE_IS_OUTPUT(q
->type
) && !ctx
->is_enc
) {
1728 ctx
->cur_buf_offset
= 0;
1730 ctx
->header_size
= 0;
1731 ctx
->comp_magic_cnt
= 0;
1732 ctx
->comp_has_frame
= 0;
1733 ctx
->comp_has_next_frame
= 0;
1737 static void vicodec_buf_request_complete(struct vb2_buffer
*vb
)
1739 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1741 v4l2_ctrl_request_complete(vb
->req_obj
.req
, &ctx
->hdl
);
1745 static const struct vb2_ops vicodec_qops
= {
1746 .queue_setup
= vicodec_queue_setup
,
1747 .buf_out_validate
= vicodec_buf_out_validate
,
1748 .buf_prepare
= vicodec_buf_prepare
,
1749 .buf_queue
= vicodec_buf_queue
,
1750 .buf_request_complete
= vicodec_buf_request_complete
,
1751 .start_streaming
= vicodec_start_streaming
,
1752 .stop_streaming
= vicodec_stop_streaming
,
1753 .wait_prepare
= vb2_ops_wait_prepare
,
1754 .wait_finish
= vb2_ops_wait_finish
,
1757 static int queue_init(void *priv
, struct vb2_queue
*src_vq
,
1758 struct vb2_queue
*dst_vq
)
1760 struct vicodec_ctx
*ctx
= priv
;
1763 src_vq
->type
= (multiplanar
?
1764 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
1765 V4L2_BUF_TYPE_VIDEO_OUTPUT
);
1766 src_vq
->io_modes
= VB2_MMAP
| VB2_USERPTR
| VB2_DMABUF
;
1767 src_vq
->drv_priv
= ctx
;
1768 src_vq
->buf_struct_size
= sizeof(struct v4l2_m2m_buffer
);
1769 src_vq
->ops
= &vicodec_qops
;
1770 src_vq
->mem_ops
= &vb2_vmalloc_memops
;
1771 src_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1773 src_vq
->lock
= &ctx
->dev
->stateful_enc
.mutex
;
1774 else if (ctx
->is_stateless
)
1775 src_vq
->lock
= &ctx
->dev
->stateless_dec
.mutex
;
1777 src_vq
->lock
= &ctx
->dev
->stateful_dec
.mutex
;
1778 src_vq
->supports_requests
= ctx
->is_stateless
;
1779 src_vq
->requires_requests
= ctx
->is_stateless
;
1780 ret
= vb2_queue_init(src_vq
);
1784 dst_vq
->type
= (multiplanar
?
1785 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
1786 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
1787 dst_vq
->io_modes
= VB2_MMAP
| VB2_USERPTR
| VB2_DMABUF
;
1788 dst_vq
->drv_priv
= ctx
;
1789 dst_vq
->buf_struct_size
= sizeof(struct v4l2_m2m_buffer
);
1790 dst_vq
->ops
= &vicodec_qops
;
1791 dst_vq
->mem_ops
= &vb2_vmalloc_memops
;
1792 dst_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1793 dst_vq
->lock
= src_vq
->lock
;
1795 return vb2_queue_init(dst_vq
);
1798 static int vicodec_try_ctrl(struct v4l2_ctrl
*ctrl
)
1800 struct vicodec_ctx
*ctx
= container_of(ctrl
->handler
,
1801 struct vicodec_ctx
, hdl
);
1802 const struct v4l2_ctrl_fwht_params
*params
;
1803 struct vicodec_q_data
*q_dst
= get_q_data(ctx
,
1804 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
1807 case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS
:
1810 params
= ctrl
->p_new
.p_fwht_params
;
1811 if (params
->width
> q_dst
->coded_width
||
1812 params
->width
< MIN_WIDTH
||
1813 params
->height
> q_dst
->coded_height
||
1814 params
->height
< MIN_HEIGHT
)
1816 if (!validate_by_version(params
->flags
, params
->version
))
1818 if (!validate_stateless_params_flags(params
, q_dst
->info
))
1827 static void update_header_from_stateless_params(struct vicodec_ctx
*ctx
,
1828 const struct v4l2_ctrl_fwht_params
*params
)
1830 struct fwht_cframe_hdr
*p_hdr
= &ctx
->state
.header
;
1832 p_hdr
->magic1
= FWHT_MAGIC1
;
1833 p_hdr
->magic2
= FWHT_MAGIC2
;
1834 p_hdr
->version
= htonl(params
->version
);
1835 p_hdr
->width
= htonl(params
->width
);
1836 p_hdr
->height
= htonl(params
->height
);
1837 p_hdr
->flags
= htonl(params
->flags
);
1838 p_hdr
->colorspace
= htonl(params
->colorspace
);
1839 p_hdr
->xfer_func
= htonl(params
->xfer_func
);
1840 p_hdr
->ycbcr_enc
= htonl(params
->ycbcr_enc
);
1841 p_hdr
->quantization
= htonl(params
->quantization
);
1844 static int vicodec_s_ctrl(struct v4l2_ctrl
*ctrl
)
1846 struct vicodec_ctx
*ctx
= container_of(ctrl
->handler
,
1847 struct vicodec_ctx
, hdl
);
1848 const struct v4l2_ctrl_fwht_params
*params
;
1851 case V4L2_CID_MPEG_VIDEO_GOP_SIZE
:
1852 ctx
->state
.gop_size
= ctrl
->val
;
1854 case V4L2_CID_FWHT_I_FRAME_QP
:
1855 ctx
->state
.i_frame_qp
= ctrl
->val
;
1857 case V4L2_CID_FWHT_P_FRAME_QP
:
1858 ctx
->state
.p_frame_qp
= ctrl
->val
;
1860 case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS
:
1861 params
= ctrl
->p_new
.p_fwht_params
;
1862 update_header_from_stateless_params(ctx
, params
);
1863 ctx
->state
.ref_frame_ts
= params
->backward_ref_ts
;
1869 static const struct v4l2_ctrl_ops vicodec_ctrl_ops
= {
1870 .s_ctrl
= vicodec_s_ctrl
,
1871 .try_ctrl
= vicodec_try_ctrl
,
1874 static const struct v4l2_ctrl_config vicodec_ctrl_stateless_state
= {
1875 .ops
= &vicodec_ctrl_ops
,
1876 .id
= V4L2_CID_MPEG_VIDEO_FWHT_PARAMS
,
1877 .elem_size
= sizeof(struct v4l2_ctrl_fwht_params
),
1883 static int vicodec_open(struct file
*file
)
1885 const struct v4l2_fwht_pixfmt_info
*info
= v4l2_fwht_get_pixfmt(0);
1886 struct video_device
*vfd
= video_devdata(file
);
1887 struct vicodec_dev
*dev
= video_drvdata(file
);
1888 struct vicodec_ctx
*ctx
= NULL
;
1889 struct v4l2_ctrl_handler
*hdl
;
1890 unsigned int raw_size
;
1891 unsigned int comp_size
;
1894 if (mutex_lock_interruptible(vfd
->lock
))
1895 return -ERESTARTSYS
;
1896 ctx
= kzalloc(sizeof(*ctx
), GFP_KERNEL
);
1902 if (vfd
== &dev
->stateful_enc
.vfd
)
1904 else if (vfd
== &dev
->stateless_dec
.vfd
)
1905 ctx
->is_stateless
= true;
1907 v4l2_fh_init(&ctx
->fh
, video_devdata(file
));
1908 file
->private_data
= &ctx
->fh
;
1911 v4l2_ctrl_handler_init(hdl
, 5);
1912 v4l2_ctrl_new_std(hdl
, &vicodec_ctrl_ops
, V4L2_CID_MPEG_VIDEO_GOP_SIZE
,
1914 v4l2_ctrl_new_std(hdl
, &vicodec_ctrl_ops
, V4L2_CID_FWHT_I_FRAME_QP
,
1916 v4l2_ctrl_new_std(hdl
, &vicodec_ctrl_ops
, V4L2_CID_FWHT_P_FRAME_QP
,
1919 v4l2_ctrl_new_std(hdl
, &vicodec_ctrl_ops
,
1920 V4L2_CID_MIN_BUFFERS_FOR_OUTPUT
, 1, 1, 1, 1);
1921 if (ctx
->is_stateless
)
1922 v4l2_ctrl_new_custom(hdl
, &vicodec_ctrl_stateless_state
, NULL
);
1925 v4l2_ctrl_handler_free(hdl
);
1929 ctx
->fh
.ctrl_handler
= hdl
;
1930 v4l2_ctrl_handler_setup(hdl
);
1933 ctx
->q_data
[V4L2_M2M_SRC
].info
= info
;
1934 else if (ctx
->is_stateless
)
1935 ctx
->q_data
[V4L2_M2M_SRC
].info
= &pixfmt_stateless_fwht
;
1937 ctx
->q_data
[V4L2_M2M_SRC
].info
= &pixfmt_fwht
;
1938 ctx
->q_data
[V4L2_M2M_SRC
].coded_width
= 1280;
1939 ctx
->q_data
[V4L2_M2M_SRC
].coded_height
= 720;
1940 ctx
->q_data
[V4L2_M2M_SRC
].visible_width
= 1280;
1941 ctx
->q_data
[V4L2_M2M_SRC
].visible_height
= 720;
1942 raw_size
= 1280 * 720 * info
->sizeimage_mult
/ info
->sizeimage_div
;
1943 comp_size
= 1280 * 720 * pixfmt_fwht
.sizeimage_mult
/
1944 pixfmt_fwht
.sizeimage_div
;
1946 ctx
->q_data
[V4L2_M2M_SRC
].sizeimage
= raw_size
;
1947 else if (ctx
->is_stateless
)
1948 ctx
->q_data
[V4L2_M2M_SRC
].sizeimage
= comp_size
;
1950 ctx
->q_data
[V4L2_M2M_SRC
].sizeimage
=
1951 comp_size
+ sizeof(struct fwht_cframe_hdr
);
1952 ctx
->q_data
[V4L2_M2M_DST
] = ctx
->q_data
[V4L2_M2M_SRC
];
1954 ctx
->q_data
[V4L2_M2M_DST
].info
= &pixfmt_fwht
;
1955 ctx
->q_data
[V4L2_M2M_DST
].sizeimage
=
1956 comp_size
+ sizeof(struct fwht_cframe_hdr
);
1958 ctx
->q_data
[V4L2_M2M_DST
].info
= info
;
1959 ctx
->q_data
[V4L2_M2M_DST
].sizeimage
= raw_size
;
1962 ctx
->state
.colorspace
= V4L2_COLORSPACE_REC709
;
1965 ctx
->fh
.m2m_ctx
= v4l2_m2m_ctx_init(dev
->stateful_enc
.m2m_dev
,
1967 ctx
->lock
= &dev
->stateful_enc
.lock
;
1968 } else if (ctx
->is_stateless
) {
1969 ctx
->fh
.m2m_ctx
= v4l2_m2m_ctx_init(dev
->stateless_dec
.m2m_dev
,
1971 ctx
->lock
= &dev
->stateless_dec
.lock
;
1973 ctx
->fh
.m2m_ctx
= v4l2_m2m_ctx_init(dev
->stateful_dec
.m2m_dev
,
1975 ctx
->lock
= &dev
->stateful_dec
.lock
;
1978 if (IS_ERR(ctx
->fh
.m2m_ctx
)) {
1979 rc
= PTR_ERR(ctx
->fh
.m2m_ctx
);
1981 v4l2_ctrl_handler_free(hdl
);
1982 v4l2_fh_exit(&ctx
->fh
);
1987 v4l2_fh_add(&ctx
->fh
);
1990 mutex_unlock(vfd
->lock
);
1994 static int vicodec_release(struct file
*file
)
1996 struct video_device
*vfd
= video_devdata(file
);
1997 struct vicodec_ctx
*ctx
= file2ctx(file
);
1999 mutex_lock(vfd
->lock
);
2000 v4l2_m2m_ctx_release(ctx
->fh
.m2m_ctx
);
2001 mutex_unlock(vfd
->lock
);
2002 v4l2_fh_del(&ctx
->fh
);
2003 v4l2_fh_exit(&ctx
->fh
);
2004 v4l2_ctrl_handler_free(&ctx
->hdl
);
2005 kvfree(ctx
->state
.compressed_frame
);
2011 static int vicodec_request_validate(struct media_request
*req
)
2013 struct media_request_object
*obj
;
2014 struct v4l2_ctrl_handler
*parent_hdl
, *hdl
;
2015 struct vicodec_ctx
*ctx
= NULL
;
2016 struct v4l2_ctrl
*ctrl
;
2019 list_for_each_entry(obj
, &req
->objects
, list
) {
2020 struct vb2_buffer
*vb
;
2022 if (vb2_request_object_is_buffer(obj
)) {
2023 vb
= container_of(obj
, struct vb2_buffer
, req_obj
);
2024 ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
2031 pr_err("No buffer was provided with the request\n");
2035 count
= vb2_request_buffer_cnt(req
);
2037 v4l2_info(&ctx
->dev
->v4l2_dev
,
2038 "No buffer was provided with the request\n");
2040 } else if (count
> 1) {
2041 v4l2_info(&ctx
->dev
->v4l2_dev
,
2042 "More than one buffer was provided with the request\n");
2046 parent_hdl
= &ctx
->hdl
;
2048 hdl
= v4l2_ctrl_request_hdl_find(req
, parent_hdl
);
2050 v4l2_info(&ctx
->dev
->v4l2_dev
, "Missing codec control\n");
2053 ctrl
= v4l2_ctrl_request_hdl_ctrl_find(hdl
,
2054 vicodec_ctrl_stateless_state
.id
);
2056 v4l2_info(&ctx
->dev
->v4l2_dev
,
2057 "Missing required codec control\n");
2061 return vb2_request_validate(req
);
2064 static const struct v4l2_file_operations vicodec_fops
= {
2065 .owner
= THIS_MODULE
,
2066 .open
= vicodec_open
,
2067 .release
= vicodec_release
,
2068 .poll
= v4l2_m2m_fop_poll
,
2069 .unlocked_ioctl
= video_ioctl2
,
2070 .mmap
= v4l2_m2m_fop_mmap
,
2073 static const struct video_device vicodec_videodev
= {
2074 .name
= VICODEC_NAME
,
2075 .vfl_dir
= VFL_DIR_M2M
,
2076 .fops
= &vicodec_fops
,
2077 .ioctl_ops
= &vicodec_ioctl_ops
,
2079 .release
= video_device_release_empty
,
2082 static const struct media_device_ops vicodec_m2m_media_ops
= {
2083 .req_validate
= vicodec_request_validate
,
2084 .req_queue
= v4l2_m2m_request_queue
,
2087 static const struct v4l2_m2m_ops m2m_ops
= {
2088 .device_run
= device_run
,
2089 .job_ready
= job_ready
,
2092 static int register_instance(struct vicodec_dev
*dev
,
2093 struct vicodec_dev_instance
*dev_instance
,
2094 const char *name
, bool is_enc
)
2096 struct video_device
*vfd
;
2099 spin_lock_init(&dev_instance
->lock
);
2100 mutex_init(&dev_instance
->mutex
);
2101 dev_instance
->m2m_dev
= v4l2_m2m_init(&m2m_ops
);
2102 if (IS_ERR(dev_instance
->m2m_dev
)) {
2103 v4l2_err(&dev
->v4l2_dev
, "Failed to init vicodec enc device\n");
2104 return PTR_ERR(dev_instance
->m2m_dev
);
2107 dev_instance
->vfd
= vicodec_videodev
;
2108 vfd
= &dev_instance
->vfd
;
2109 vfd
->lock
= &dev_instance
->mutex
;
2110 vfd
->v4l2_dev
= &dev
->v4l2_dev
;
2111 strscpy(vfd
->name
, name
, sizeof(vfd
->name
));
2112 vfd
->device_caps
= V4L2_CAP_STREAMING
|
2113 (multiplanar
? V4L2_CAP_VIDEO_M2M_MPLANE
: V4L2_CAP_VIDEO_M2M
);
2115 v4l2_disable_ioctl(vfd
, VIDIOC_DECODER_CMD
);
2116 v4l2_disable_ioctl(vfd
, VIDIOC_TRY_DECODER_CMD
);
2118 v4l2_disable_ioctl(vfd
, VIDIOC_ENCODER_CMD
);
2119 v4l2_disable_ioctl(vfd
, VIDIOC_TRY_ENCODER_CMD
);
2121 video_set_drvdata(vfd
, dev
);
2123 ret
= video_register_device(vfd
, VFL_TYPE_GRABBER
, 0);
2125 v4l2_err(&dev
->v4l2_dev
, "Failed to register video device '%s'\n", name
);
2126 v4l2_m2m_release(dev_instance
->m2m_dev
);
2129 v4l2_info(&dev
->v4l2_dev
, "Device '%s' registered as /dev/video%d\n",
2134 static void vicodec_v4l2_dev_release(struct v4l2_device
*v4l2_dev
)
2136 struct vicodec_dev
*dev
= container_of(v4l2_dev
, struct vicodec_dev
, v4l2_dev
);
2138 v4l2_device_unregister(&dev
->v4l2_dev
);
2139 v4l2_m2m_release(dev
->stateful_enc
.m2m_dev
);
2140 v4l2_m2m_release(dev
->stateful_dec
.m2m_dev
);
2141 v4l2_m2m_release(dev
->stateless_dec
.m2m_dev
);
2142 #ifdef CONFIG_MEDIA_CONTROLLER
2143 media_device_cleanup(&dev
->mdev
);
2148 static int vicodec_probe(struct platform_device
*pdev
)
2150 struct vicodec_dev
*dev
;
2153 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
2157 ret
= v4l2_device_register(&pdev
->dev
, &dev
->v4l2_dev
);
2161 dev
->v4l2_dev
.release
= vicodec_v4l2_dev_release
;
2163 #ifdef CONFIG_MEDIA_CONTROLLER
2164 dev
->mdev
.dev
= &pdev
->dev
;
2165 strscpy(dev
->mdev
.model
, "vicodec", sizeof(dev
->mdev
.model
));
2166 strscpy(dev
->mdev
.bus_info
, "platform:vicodec",
2167 sizeof(dev
->mdev
.bus_info
));
2168 media_device_init(&dev
->mdev
);
2169 dev
->mdev
.ops
= &vicodec_m2m_media_ops
;
2170 dev
->v4l2_dev
.mdev
= &dev
->mdev
;
2173 platform_set_drvdata(pdev
, dev
);
2175 if (register_instance(dev
, &dev
->stateful_enc
,
2176 "stateful-encoder", true))
2179 if (register_instance(dev
, &dev
->stateful_dec
,
2180 "stateful-decoder", false))
2183 if (register_instance(dev
, &dev
->stateless_dec
,
2184 "stateless-decoder", false))
2187 #ifdef CONFIG_MEDIA_CONTROLLER
2188 ret
= v4l2_m2m_register_media_controller(dev
->stateful_enc
.m2m_dev
,
2189 &dev
->stateful_enc
.vfd
,
2190 MEDIA_ENT_F_PROC_VIDEO_ENCODER
);
2192 v4l2_err(&dev
->v4l2_dev
, "Failed to init mem2mem media controller for enc\n");
2196 ret
= v4l2_m2m_register_media_controller(dev
->stateful_dec
.m2m_dev
,
2197 &dev
->stateful_dec
.vfd
,
2198 MEDIA_ENT_F_PROC_VIDEO_DECODER
);
2200 v4l2_err(&dev
->v4l2_dev
, "Failed to init mem2mem media controller for dec\n");
2201 goto unreg_m2m_sf_enc_mc
;
2204 ret
= v4l2_m2m_register_media_controller(dev
->stateless_dec
.m2m_dev
,
2205 &dev
->stateless_dec
.vfd
,
2206 MEDIA_ENT_F_PROC_VIDEO_DECODER
);
2208 v4l2_err(&dev
->v4l2_dev
, "Failed to init mem2mem media controller for stateless dec\n");
2209 goto unreg_m2m_sf_dec_mc
;
2212 ret
= media_device_register(&dev
->mdev
);
2214 v4l2_err(&dev
->v4l2_dev
, "Failed to register mem2mem media device\n");
2215 goto unreg_m2m_sl_dec_mc
;
2220 #ifdef CONFIG_MEDIA_CONTROLLER
2221 unreg_m2m_sl_dec_mc
:
2222 v4l2_m2m_unregister_media_controller(dev
->stateless_dec
.m2m_dev
);
2223 unreg_m2m_sf_dec_mc
:
2224 v4l2_m2m_unregister_media_controller(dev
->stateful_dec
.m2m_dev
);
2225 unreg_m2m_sf_enc_mc
:
2226 v4l2_m2m_unregister_media_controller(dev
->stateful_enc
.m2m_dev
);
2228 video_unregister_device(&dev
->stateless_dec
.vfd
);
2229 v4l2_m2m_release(dev
->stateless_dec
.m2m_dev
);
2232 video_unregister_device(&dev
->stateful_dec
.vfd
);
2233 v4l2_m2m_release(dev
->stateful_dec
.m2m_dev
);
2235 video_unregister_device(&dev
->stateful_enc
.vfd
);
2236 v4l2_m2m_release(dev
->stateful_enc
.m2m_dev
);
2238 v4l2_device_unregister(&dev
->v4l2_dev
);
2245 static int vicodec_remove(struct platform_device
*pdev
)
2247 struct vicodec_dev
*dev
= platform_get_drvdata(pdev
);
2249 v4l2_info(&dev
->v4l2_dev
, "Removing " VICODEC_NAME
);
2251 #ifdef CONFIG_MEDIA_CONTROLLER
2252 media_device_unregister(&dev
->mdev
);
2253 v4l2_m2m_unregister_media_controller(dev
->stateful_enc
.m2m_dev
);
2254 v4l2_m2m_unregister_media_controller(dev
->stateful_dec
.m2m_dev
);
2255 v4l2_m2m_unregister_media_controller(dev
->stateless_dec
.m2m_dev
);
2258 video_unregister_device(&dev
->stateful_enc
.vfd
);
2259 video_unregister_device(&dev
->stateful_dec
.vfd
);
2260 video_unregister_device(&dev
->stateless_dec
.vfd
);
2261 v4l2_device_put(&dev
->v4l2_dev
);
2266 static struct platform_driver vicodec_pdrv
= {
2267 .probe
= vicodec_probe
,
2268 .remove
= vicodec_remove
,
2270 .name
= VICODEC_NAME
,
2274 static void __exit
vicodec_exit(void)
2276 platform_driver_unregister(&vicodec_pdrv
);
2277 platform_device_unregister(&vicodec_pdev
);
2280 static int __init
vicodec_init(void)
2284 ret
= platform_device_register(&vicodec_pdev
);
2288 ret
= platform_driver_register(&vicodec_pdrv
);
2290 platform_device_unregister(&vicodec_pdev
);
2295 module_init(vicodec_init
);
2296 module_exit(vicodec_exit
);