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 <hansverk@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
46 /* Recommended number of buffers for the stateful codecs */
47 #define VICODEC_REC_BUFS 2
49 #define dprintk(dev, fmt, arg...) \
50 v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
55 unsigned int bytesperline_mult
;
56 unsigned int sizeimage_mult
;
57 unsigned int sizeimage_div
;
58 unsigned int luma_step
;
59 unsigned int chroma_step
;
60 /* Chroma plane subsampling */
61 unsigned int width_div
;
62 unsigned int height_div
;
65 static const struct v4l2_fwht_pixfmt_info pixfmt_fwht
= {
66 V4L2_PIX_FMT_FWHT
, 0, 3, 1, 1, 1, 1, 1, 0, 1
69 static const struct v4l2_fwht_pixfmt_info pixfmt_stateless_fwht
= {
70 V4L2_PIX_FMT_FWHT_STATELESS
, 0, 3, 1, 1, 1, 1, 1, 0, 1
73 static void vicodec_dev_release(struct device
*dev
)
77 static struct platform_device vicodec_pdev
= {
79 .dev
.release
= vicodec_dev_release
,
82 /* Per-queue, driver-specific private data */
83 struct vicodec_q_data
{
84 unsigned int coded_width
;
85 unsigned int coded_height
;
86 unsigned int visible_width
;
87 unsigned int visible_height
;
88 unsigned int sizeimage
;
89 unsigned int vb2_sizeimage
;
90 unsigned int sequence
;
91 const struct v4l2_fwht_pixfmt_info
*info
;
99 struct vicodec_dev_instance
{
100 struct video_device vfd
;
103 struct v4l2_m2m_dev
*m2m_dev
;
107 struct v4l2_device v4l2_dev
;
108 struct vicodec_dev_instance stateful_enc
;
109 struct vicodec_dev_instance stateful_dec
;
110 struct vicodec_dev_instance stateless_dec
;
111 #ifdef CONFIG_MEDIA_CONTROLLER
112 struct media_device mdev
;
119 struct vicodec_dev
*dev
;
124 struct v4l2_ctrl_handler hdl
;
126 /* Source and destination queue data */
127 struct vicodec_q_data q_data
[2];
128 struct v4l2_fwht_state state
;
136 bool comp_has_next_frame
;
137 bool first_source_change_sent
;
141 static const struct v4l2_event vicodec_eos_event
= {
142 .type
= V4L2_EVENT_EOS
145 static inline struct vicodec_ctx
*file2ctx(struct file
*file
)
147 return container_of(file
->private_data
, struct vicodec_ctx
, fh
);
150 static struct vicodec_q_data
*get_q_data(struct vicodec_ctx
*ctx
,
151 enum v4l2_buf_type type
)
154 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
155 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
156 return &ctx
->q_data
[V4L2_M2M_SRC
];
157 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
158 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
159 return &ctx
->q_data
[V4L2_M2M_DST
];
166 static void copy_cap_to_ref(const u8
*cap
, const struct v4l2_fwht_pixfmt_info
*info
,
167 struct v4l2_fwht_state
*state
)
170 u8
*p_ref
= state
->ref_frame
.buf
;
171 unsigned int cap_stride
= state
->stride
;
172 unsigned int ref_stride
= state
->ref_stride
;
174 for (plane_idx
= 0; plane_idx
< info
->planes_num
; plane_idx
++) {
176 unsigned int h_div
= (plane_idx
== 1 || plane_idx
== 2) ?
177 info
->height_div
: 1;
178 const u8
*row_cap
= cap
;
181 if (info
->planes_num
== 3 && plane_idx
== 1) {
186 if (plane_idx
== 1 &&
187 (info
->id
== V4L2_PIX_FMT_NV24
||
188 info
->id
== V4L2_PIX_FMT_NV42
)) {
193 for (i
= 0; i
< state
->visible_height
/ h_div
; i
++) {
194 memcpy(row_ref
, row_cap
, ref_stride
);
195 row_ref
+= ref_stride
;
196 row_cap
+= cap_stride
;
198 cap
+= cap_stride
* (state
->coded_height
/ h_div
);
199 p_ref
+= ref_stride
* (state
->coded_height
/ h_div
);
203 static bool validate_by_version(unsigned int flags
, unsigned int version
)
205 if (!version
|| version
> V4L2_FWHT_VERSION
)
209 unsigned int components_num
= 1 +
210 ((flags
& V4L2_FWHT_FL_COMPONENTS_NUM_MSK
) >>
211 V4L2_FWHT_FL_COMPONENTS_NUM_OFFSET
);
212 unsigned int pixenc
= flags
& V4L2_FWHT_FL_PIXENC_MSK
;
214 if (components_num
== 0 || components_num
> 4 || !pixenc
)
220 static bool validate_stateless_params_flags(const struct v4l2_ctrl_fwht_params
*params
,
221 const struct v4l2_fwht_pixfmt_info
*cur_info
)
223 unsigned int width_div
=
224 (params
->flags
& V4L2_FWHT_FL_CHROMA_FULL_WIDTH
) ? 1 : 2;
225 unsigned int height_div
=
226 (params
->flags
& V4L2_FWHT_FL_CHROMA_FULL_HEIGHT
) ? 1 : 2;
227 unsigned int components_num
= 3;
228 unsigned int pixenc
= 0;
230 if (params
->version
< 3)
233 components_num
= 1 + ((params
->flags
& V4L2_FWHT_FL_COMPONENTS_NUM_MSK
) >>
234 V4L2_FWHT_FL_COMPONENTS_NUM_OFFSET
);
235 pixenc
= (params
->flags
& V4L2_FWHT_FL_PIXENC_MSK
);
236 if (v4l2_fwht_validate_fmt(cur_info
, width_div
, height_div
,
237 components_num
, pixenc
))
243 static void update_state_from_header(struct vicodec_ctx
*ctx
)
245 const struct fwht_cframe_hdr
*p_hdr
= &ctx
->state
.header
;
247 ctx
->state
.visible_width
= ntohl(p_hdr
->width
);
248 ctx
->state
.visible_height
= ntohl(p_hdr
->height
);
249 ctx
->state
.colorspace
= ntohl(p_hdr
->colorspace
);
250 ctx
->state
.xfer_func
= ntohl(p_hdr
->xfer_func
);
251 ctx
->state
.ycbcr_enc
= ntohl(p_hdr
->ycbcr_enc
);
252 ctx
->state
.quantization
= ntohl(p_hdr
->quantization
);
255 static int device_process(struct vicodec_ctx
*ctx
,
256 struct vb2_v4l2_buffer
*src_vb
,
257 struct vb2_v4l2_buffer
*dst_vb
)
259 struct vicodec_dev
*dev
= ctx
->dev
;
260 struct v4l2_fwht_state
*state
= &ctx
->state
;
264 if (ctx
->is_enc
|| ctx
->is_stateless
)
265 p_src
= vb2_plane_vaddr(&src_vb
->vb2_buf
, 0);
267 p_src
= state
->compressed_frame
;
269 if (ctx
->is_stateless
) {
270 struct media_request
*src_req
= src_vb
->vb2_buf
.req_obj
.req
;
272 ret
= v4l2_ctrl_request_setup(src_req
, &ctx
->hdl
);
275 update_state_from_header(ctx
);
277 ctx
->state
.header
.size
=
278 htonl(vb2_get_plane_payload(&src_vb
->vb2_buf
, 0));
280 * set the reference buffer from the reference timestamp
281 * only if this is a P-frame
283 if (!(ntohl(ctx
->state
.header
.flags
) & V4L2_FWHT_FL_I_FRAME
)) {
284 struct vb2_buffer
*ref_vb2_buf
;
285 struct vb2_queue
*vq_cap
=
286 v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
,
287 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
289 ref_vb2_buf
= vb2_find_buffer(vq_cap
, ctx
->state
.ref_frame_ts
);
292 if (ref_vb2_buf
->state
== VB2_BUF_STATE_ERROR
)
294 ctx
->state
.ref_frame
.buf
=
295 vb2_plane_vaddr(ref_vb2_buf
, 0);
297 ctx
->state
.ref_frame
.buf
= NULL
;
300 p_dst
= vb2_plane_vaddr(&dst_vb
->vb2_buf
, 0);
301 if (!p_src
|| !p_dst
) {
302 v4l2_err(&dev
->v4l2_dev
,
303 "Acquiring kernel pointers to buffers failed\n");
308 struct vicodec_q_data
*q_src
;
309 int comp_sz_or_errcode
;
311 q_src
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_OUTPUT
);
312 state
->info
= q_src
->info
;
313 comp_sz_or_errcode
= v4l2_fwht_encode(state
, p_src
, p_dst
);
314 if (comp_sz_or_errcode
< 0)
315 return comp_sz_or_errcode
;
316 vb2_set_plane_payload(&dst_vb
->vb2_buf
, 0, comp_sz_or_errcode
);
318 struct vicodec_q_data
*q_dst
;
319 unsigned int comp_frame_size
= ntohl(ctx
->state
.header
.size
);
321 q_dst
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_CAPTURE
);
322 if (comp_frame_size
> ctx
->comp_max_size
)
324 state
->info
= q_dst
->info
;
325 ret
= v4l2_fwht_decode(state
, p_src
, p_dst
);
328 if (!ctx
->is_stateless
)
329 copy_cap_to_ref(p_dst
, ctx
->state
.info
, &ctx
->state
);
331 vb2_set_plane_payload(&dst_vb
->vb2_buf
, 0, q_dst
->sizeimage
);
332 if (ntohl(ctx
->state
.header
.flags
) & V4L2_FWHT_FL_I_FRAME
)
333 dst_vb
->flags
|= V4L2_BUF_FLAG_KEYFRAME
;
335 dst_vb
->flags
|= V4L2_BUF_FLAG_PFRAME
;
343 static enum vb2_buffer_state
get_next_header(struct vicodec_ctx
*ctx
,
346 static const u8 magic
[] = {
347 0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
351 u8
*header
= (u8
*)&ctx
->state
.header
;
353 state
= VB2_BUF_STATE_DONE
;
355 if (!ctx
->header_size
) {
356 state
= VB2_BUF_STATE_ERROR
;
357 for (; p
< *pp
+ sz
; p
++) {
360 p
= memchr(p
, magic
[ctx
->comp_magic_cnt
],
363 ctx
->comp_magic_cnt
= 0;
367 copy
= sizeof(magic
) - ctx
->comp_magic_cnt
;
368 if (*pp
+ sz
- p
< copy
)
371 memcpy(header
+ ctx
->comp_magic_cnt
, p
, copy
);
372 ctx
->comp_magic_cnt
+= copy
;
373 if (!memcmp(header
, magic
, ctx
->comp_magic_cnt
)) {
375 state
= VB2_BUF_STATE_DONE
;
378 ctx
->comp_magic_cnt
= 0;
380 if (ctx
->comp_magic_cnt
< sizeof(magic
)) {
384 ctx
->header_size
= sizeof(magic
);
387 if (ctx
->header_size
< sizeof(struct fwht_cframe_hdr
)) {
388 u32 copy
= sizeof(struct fwht_cframe_hdr
) - ctx
->header_size
;
390 if (*pp
+ sz
- p
< copy
)
393 memcpy(header
+ ctx
->header_size
, p
, copy
);
395 ctx
->header_size
+= copy
;
401 /* device_run() - prepares and starts the device */
402 static void device_run(void *priv
)
404 struct vicodec_ctx
*ctx
= priv
;
405 struct vicodec_dev
*dev
= ctx
->dev
;
406 struct vb2_v4l2_buffer
*src_buf
, *dst_buf
;
407 struct vicodec_q_data
*q_src
, *q_dst
;
409 struct media_request
*src_req
;
411 src_buf
= v4l2_m2m_next_src_buf(ctx
->fh
.m2m_ctx
);
412 dst_buf
= v4l2_m2m_dst_buf_remove(ctx
->fh
.m2m_ctx
);
413 src_req
= src_buf
->vb2_buf
.req_obj
.req
;
415 q_src
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_OUTPUT
);
416 q_dst
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_CAPTURE
);
418 state
= VB2_BUF_STATE_DONE
;
419 if (device_process(ctx
, src_buf
, dst_buf
))
420 state
= VB2_BUF_STATE_ERROR
;
422 dst_buf
->sequence
= q_dst
->sequence
++;
423 dst_buf
->flags
&= ~V4L2_BUF_FLAG_LAST
;
424 v4l2_m2m_buf_copy_metadata(src_buf
, dst_buf
, false);
426 spin_lock(ctx
->lock
);
427 if (!ctx
->comp_has_next_frame
&&
428 v4l2_m2m_is_last_draining_src_buf(ctx
->fh
.m2m_ctx
, src_buf
)) {
429 dst_buf
->flags
|= V4L2_BUF_FLAG_LAST
;
430 v4l2_event_queue_fh(&ctx
->fh
, &vicodec_eos_event
);
431 v4l2_m2m_mark_stopped(ctx
->fh
.m2m_ctx
);
433 if (ctx
->is_enc
|| ctx
->is_stateless
) {
434 src_buf
->sequence
= q_src
->sequence
++;
435 src_buf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
436 v4l2_m2m_buf_done(src_buf
, state
);
437 } else if (vb2_get_plane_payload(&src_buf
->vb2_buf
, 0) == ctx
->cur_buf_offset
) {
438 src_buf
->sequence
= q_src
->sequence
++;
439 src_buf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
440 v4l2_m2m_buf_done(src_buf
, state
);
441 ctx
->cur_buf_offset
= 0;
442 ctx
->comp_has_next_frame
= false;
444 v4l2_m2m_buf_done(dst_buf
, state
);
447 ctx
->header_size
= 0;
448 ctx
->comp_magic_cnt
= 0;
449 ctx
->comp_has_frame
= false;
450 spin_unlock(ctx
->lock
);
451 if (ctx
->is_stateless
&& src_req
)
452 v4l2_ctrl_request_complete(src_req
, &ctx
->hdl
);
455 v4l2_m2m_job_finish(dev
->stateful_enc
.m2m_dev
, ctx
->fh
.m2m_ctx
);
456 else if (ctx
->is_stateless
)
457 v4l2_m2m_job_finish(dev
->stateless_dec
.m2m_dev
,
460 v4l2_m2m_job_finish(dev
->stateful_dec
.m2m_dev
, ctx
->fh
.m2m_ctx
);
463 static void job_remove_src_buf(struct vicodec_ctx
*ctx
, u32 state
)
465 struct vb2_v4l2_buffer
*src_buf
;
466 struct vicodec_q_data
*q_src
;
468 q_src
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_OUTPUT
);
469 spin_lock(ctx
->lock
);
470 src_buf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
471 src_buf
->sequence
= q_src
->sequence
++;
472 v4l2_m2m_buf_done(src_buf
, state
);
473 ctx
->cur_buf_offset
= 0;
474 spin_unlock(ctx
->lock
);
477 static const struct v4l2_fwht_pixfmt_info
*
478 info_from_header(const struct fwht_cframe_hdr
*p_hdr
)
480 unsigned int flags
= ntohl(p_hdr
->flags
);
481 unsigned int width_div
= (flags
& V4L2_FWHT_FL_CHROMA_FULL_WIDTH
) ? 1 : 2;
482 unsigned int height_div
= (flags
& V4L2_FWHT_FL_CHROMA_FULL_HEIGHT
) ? 1 : 2;
483 unsigned int components_num
= 3;
484 unsigned int pixenc
= 0;
485 unsigned int version
= ntohl(p_hdr
->version
);
488 components_num
= 1 + ((flags
& V4L2_FWHT_FL_COMPONENTS_NUM_MSK
) >>
489 V4L2_FWHT_FL_COMPONENTS_NUM_OFFSET
);
490 pixenc
= (flags
& V4L2_FWHT_FL_PIXENC_MSK
);
492 return v4l2_fwht_find_nth_fmt(width_div
, height_div
,
493 components_num
, pixenc
, 0);
496 static bool is_header_valid(const struct fwht_cframe_hdr
*p_hdr
)
498 const struct v4l2_fwht_pixfmt_info
*info
;
499 unsigned int w
= ntohl(p_hdr
->width
);
500 unsigned int h
= ntohl(p_hdr
->height
);
501 unsigned int version
= ntohl(p_hdr
->version
);
502 unsigned int flags
= ntohl(p_hdr
->flags
);
504 if (w
< MIN_WIDTH
|| w
> MAX_WIDTH
|| h
< MIN_HEIGHT
|| h
> MAX_HEIGHT
)
507 if (!validate_by_version(flags
, version
))
510 info
= info_from_header(p_hdr
);
516 static void update_capture_data_from_header(struct vicodec_ctx
*ctx
)
518 struct vicodec_q_data
*q_dst
= get_q_data(ctx
,
519 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
520 const struct fwht_cframe_hdr
*p_hdr
= &ctx
->state
.header
;
521 const struct v4l2_fwht_pixfmt_info
*info
= info_from_header(p_hdr
);
522 unsigned int flags
= ntohl(p_hdr
->flags
);
523 unsigned int hdr_width_div
= (flags
& V4L2_FWHT_FL_CHROMA_FULL_WIDTH
) ? 1 : 2;
524 unsigned int hdr_height_div
= (flags
& V4L2_FWHT_FL_CHROMA_FULL_HEIGHT
) ? 1 : 2;
527 * This function should not be used by a stateless codec since
528 * it changes values in q_data that are not request specific
530 WARN_ON(ctx
->is_stateless
);
533 q_dst
->visible_width
= ntohl(p_hdr
->width
);
534 q_dst
->visible_height
= ntohl(p_hdr
->height
);
535 q_dst
->coded_width
= vic_round_dim(q_dst
->visible_width
, hdr_width_div
);
536 q_dst
->coded_height
= vic_round_dim(q_dst
->visible_height
,
539 q_dst
->sizeimage
= q_dst
->coded_width
* q_dst
->coded_height
*
540 q_dst
->info
->sizeimage_mult
/ q_dst
->info
->sizeimage_div
;
541 ctx
->state
.colorspace
= ntohl(p_hdr
->colorspace
);
543 ctx
->state
.xfer_func
= ntohl(p_hdr
->xfer_func
);
544 ctx
->state
.ycbcr_enc
= ntohl(p_hdr
->ycbcr_enc
);
545 ctx
->state
.quantization
= ntohl(p_hdr
->quantization
);
548 static void set_last_buffer(struct vb2_v4l2_buffer
*dst_buf
,
549 const struct vb2_v4l2_buffer
*src_buf
,
550 struct vicodec_ctx
*ctx
)
552 struct vicodec_q_data
*q_dst
= get_q_data(ctx
,
553 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
555 vb2_set_plane_payload(&dst_buf
->vb2_buf
, 0, 0);
556 dst_buf
->sequence
= q_dst
->sequence
++;
558 v4l2_m2m_buf_copy_metadata(src_buf
, dst_buf
, !ctx
->is_enc
);
559 dst_buf
->flags
|= V4L2_BUF_FLAG_LAST
;
560 v4l2_m2m_buf_done(dst_buf
, VB2_BUF_STATE_DONE
);
563 static int job_ready(void *priv
)
565 static const u8 magic
[] = {
566 0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
568 struct vicodec_ctx
*ctx
= priv
;
569 struct vb2_v4l2_buffer
*src_buf
;
574 struct vicodec_q_data
*q_dst
= get_q_data(ctx
,
575 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
577 unsigned int hdr_width_div
;
578 unsigned int hdr_height_div
;
579 unsigned int max_to_copy
;
580 unsigned int comp_frame_size
;
582 if (ctx
->source_changed
)
584 if (ctx
->is_stateless
|| ctx
->is_enc
|| ctx
->comp_has_frame
)
588 ctx
->comp_has_next_frame
= false;
589 src_buf
= v4l2_m2m_next_src_buf(ctx
->fh
.m2m_ctx
);
592 p_src
= vb2_plane_vaddr(&src_buf
->vb2_buf
, 0);
593 sz
= vb2_get_plane_payload(&src_buf
->vb2_buf
, 0);
594 p
= p_src
+ ctx
->cur_buf_offset
;
596 state
= VB2_BUF_STATE_DONE
;
598 if (ctx
->header_size
< sizeof(struct fwht_cframe_hdr
)) {
599 state
= get_next_header(ctx
, &p
, p_src
+ sz
- p
);
600 if (ctx
->header_size
< sizeof(struct fwht_cframe_hdr
)) {
601 if (v4l2_m2m_is_last_draining_src_buf(ctx
->fh
.m2m_ctx
,
604 job_remove_src_buf(ctx
, state
);
609 comp_frame_size
= ntohl(ctx
->state
.header
.size
);
612 * The current scanned frame might be the first frame of a new
613 * resolution so its size might be larger than ctx->comp_max_size.
614 * In that case it is copied up to the current buffer capacity and
615 * the copy will continue after allocating new large enough buffer
618 max_to_copy
= min(comp_frame_size
, ctx
->comp_max_size
);
620 if (ctx
->comp_size
< max_to_copy
) {
621 u32 copy
= max_to_copy
- ctx
->comp_size
;
623 if (copy
> p_src
+ sz
- p
)
624 copy
= p_src
+ sz
- p
;
626 memcpy(ctx
->state
.compressed_frame
+ ctx
->comp_size
,
629 ctx
->comp_size
+= copy
;
630 if (ctx
->comp_size
< max_to_copy
) {
631 if (v4l2_m2m_is_last_draining_src_buf(ctx
->fh
.m2m_ctx
,
634 job_remove_src_buf(ctx
, state
);
638 ctx
->cur_buf_offset
= p
- p_src
;
639 if (ctx
->comp_size
== comp_frame_size
)
640 ctx
->comp_has_frame
= true;
641 ctx
->comp_has_next_frame
= false;
642 if (ctx
->comp_has_frame
&& sz
- ctx
->cur_buf_offset
>=
643 sizeof(struct fwht_cframe_hdr
)) {
644 struct fwht_cframe_hdr
*p_hdr
= (struct fwht_cframe_hdr
*)p
;
645 u32 frame_size
= ntohl(p_hdr
->size
);
646 u32 remaining
= sz
- ctx
->cur_buf_offset
- sizeof(*p_hdr
);
648 if (!memcmp(p
, magic
, sizeof(magic
)))
649 ctx
->comp_has_next_frame
= remaining
>= frame_size
;
652 * if the header is invalid the device_run will just drop the frame
655 if (!is_header_valid(&ctx
->state
.header
) && ctx
->comp_has_frame
)
657 flags
= ntohl(ctx
->state
.header
.flags
);
658 hdr_width_div
= (flags
& V4L2_FWHT_FL_CHROMA_FULL_WIDTH
) ? 1 : 2;
659 hdr_height_div
= (flags
& V4L2_FWHT_FL_CHROMA_FULL_HEIGHT
) ? 1 : 2;
661 if (ntohl(ctx
->state
.header
.width
) != q_dst
->visible_width
||
662 ntohl(ctx
->state
.header
.height
) != q_dst
->visible_height
||
664 hdr_width_div
!= q_dst
->info
->width_div
||
665 hdr_height_div
!= q_dst
->info
->height_div
) {
666 static const struct v4l2_event rs_event
= {
667 .type
= V4L2_EVENT_SOURCE_CHANGE
,
668 .u
.src_change
.changes
= V4L2_EVENT_SRC_CH_RESOLUTION
,
671 struct vb2_v4l2_buffer
*dst_buf
=
672 v4l2_m2m_dst_buf_remove(ctx
->fh
.m2m_ctx
);
674 update_capture_data_from_header(ctx
);
675 v4l2_event_queue_fh(&ctx
->fh
, &rs_event
);
676 set_last_buffer(dst_buf
, src_buf
, ctx
);
677 ctx
->source_changed
= true;
687 static const struct v4l2_fwht_pixfmt_info
*find_fmt(u32 fmt
)
689 const struct v4l2_fwht_pixfmt_info
*info
=
690 v4l2_fwht_find_pixfmt(fmt
);
693 info
= v4l2_fwht_get_pixfmt(0);
697 static int vidioc_querycap(struct file
*file
, void *priv
,
698 struct v4l2_capability
*cap
)
700 strscpy(cap
->driver
, VICODEC_NAME
, sizeof(cap
->driver
));
701 strscpy(cap
->card
, VICODEC_NAME
, sizeof(cap
->card
));
702 snprintf(cap
->bus_info
, sizeof(cap
->bus_info
),
703 "platform:%s", VICODEC_NAME
);
707 static int enum_fmt(struct v4l2_fmtdesc
*f
, struct vicodec_ctx
*ctx
,
710 bool is_uncomp
= (ctx
->is_enc
&& is_out
) || (!ctx
->is_enc
&& !is_out
);
712 if (V4L2_TYPE_IS_MULTIPLANAR(f
->type
) && !multiplanar
)
714 if (!V4L2_TYPE_IS_MULTIPLANAR(f
->type
) && multiplanar
)
718 const struct v4l2_fwht_pixfmt_info
*info
=
719 get_q_data(ctx
, f
->type
)->info
;
722 !vb2_is_streaming(&ctx
->fh
.m2m_ctx
->cap_q_ctx
.q
))
723 info
= v4l2_fwht_get_pixfmt(f
->index
);
725 info
= v4l2_fwht_find_nth_fmt(info
->width_div
,
727 info
->components_num
,
732 f
->pixelformat
= info
->id
;
736 f
->pixelformat
= ctx
->is_stateless
?
737 V4L2_PIX_FMT_FWHT_STATELESS
: V4L2_PIX_FMT_FWHT
;
738 if (!ctx
->is_enc
&& !ctx
->is_stateless
)
739 f
->flags
= V4L2_FMT_FLAG_DYN_RESOLUTION
|
740 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM
;
745 static int vidioc_enum_fmt_vid_cap(struct file
*file
, void *priv
,
746 struct v4l2_fmtdesc
*f
)
748 struct vicodec_ctx
*ctx
= file2ctx(file
);
750 return enum_fmt(f
, ctx
, false);
753 static int vidioc_enum_fmt_vid_out(struct file
*file
, void *priv
,
754 struct v4l2_fmtdesc
*f
)
756 struct vicodec_ctx
*ctx
= file2ctx(file
);
758 return enum_fmt(f
, ctx
, true);
761 static int vidioc_g_fmt(struct vicodec_ctx
*ctx
, struct v4l2_format
*f
)
763 struct vb2_queue
*vq
;
764 struct vicodec_q_data
*q_data
;
765 struct v4l2_pix_format_mplane
*pix_mp
;
766 struct v4l2_pix_format
*pix
;
767 const struct v4l2_fwht_pixfmt_info
*info
;
769 vq
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
, f
->type
);
773 q_data
= get_q_data(ctx
, f
->type
);
777 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
778 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
782 pix
->width
= q_data
->coded_width
;
783 pix
->height
= q_data
->coded_height
;
784 pix
->field
= V4L2_FIELD_NONE
;
785 pix
->pixelformat
= info
->id
;
786 pix
->bytesperline
= q_data
->coded_width
*
787 info
->bytesperline_mult
;
788 pix
->sizeimage
= q_data
->sizeimage
;
789 pix
->colorspace
= ctx
->state
.colorspace
;
790 pix
->xfer_func
= ctx
->state
.xfer_func
;
791 pix
->ycbcr_enc
= ctx
->state
.ycbcr_enc
;
792 pix
->quantization
= ctx
->state
.quantization
;
795 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
796 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
799 pix_mp
= &f
->fmt
.pix_mp
;
800 pix_mp
->width
= q_data
->coded_width
;
801 pix_mp
->height
= q_data
->coded_height
;
802 pix_mp
->field
= V4L2_FIELD_NONE
;
803 pix_mp
->pixelformat
= info
->id
;
804 pix_mp
->num_planes
= 1;
805 pix_mp
->plane_fmt
[0].bytesperline
=
806 q_data
->coded_width
* info
->bytesperline_mult
;
807 pix_mp
->plane_fmt
[0].sizeimage
= q_data
->sizeimage
;
808 pix_mp
->colorspace
= ctx
->state
.colorspace
;
809 pix_mp
->xfer_func
= ctx
->state
.xfer_func
;
810 pix_mp
->ycbcr_enc
= ctx
->state
.ycbcr_enc
;
811 pix_mp
->quantization
= ctx
->state
.quantization
;
819 static int vidioc_g_fmt_vid_out(struct file
*file
, void *priv
,
820 struct v4l2_format
*f
)
822 return vidioc_g_fmt(file2ctx(file
), f
);
825 static int vidioc_g_fmt_vid_cap(struct file
*file
, void *priv
,
826 struct v4l2_format
*f
)
828 return vidioc_g_fmt(file2ctx(file
), f
);
831 static int vidioc_try_fmt(struct vicodec_ctx
*ctx
, struct v4l2_format
*f
)
833 struct v4l2_pix_format_mplane
*pix_mp
;
834 struct v4l2_pix_format
*pix
;
835 struct v4l2_plane_pix_format
*plane
;
836 const struct v4l2_fwht_pixfmt_info
*info
= ctx
->is_stateless
?
837 &pixfmt_stateless_fwht
: &pixfmt_fwht
;
840 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
841 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
843 if (pix
->pixelformat
!= V4L2_PIX_FMT_FWHT
&&
844 pix
->pixelformat
!= V4L2_PIX_FMT_FWHT_STATELESS
)
845 info
= find_fmt(pix
->pixelformat
);
847 pix
->width
= clamp(pix
->width
, MIN_WIDTH
, MAX_WIDTH
);
848 pix
->width
= vic_round_dim(pix
->width
, info
->width_div
);
850 pix
->height
= clamp(pix
->height
, MIN_HEIGHT
, MAX_HEIGHT
);
851 pix
->height
= vic_round_dim(pix
->height
, info
->height_div
);
853 pix
->field
= V4L2_FIELD_NONE
;
855 pix
->width
* info
->bytesperline_mult
;
856 pix
->sizeimage
= pix
->width
* pix
->height
*
857 info
->sizeimage_mult
/ info
->sizeimage_div
;
858 if (pix
->pixelformat
== V4L2_PIX_FMT_FWHT
)
859 pix
->sizeimage
+= sizeof(struct fwht_cframe_hdr
);
861 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
862 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
863 pix_mp
= &f
->fmt
.pix_mp
;
864 plane
= pix_mp
->plane_fmt
;
865 if (pix_mp
->pixelformat
!= V4L2_PIX_FMT_FWHT
&&
866 pix_mp
->pixelformat
!= V4L2_PIX_FMT_FWHT_STATELESS
)
867 info
= find_fmt(pix_mp
->pixelformat
);
868 pix_mp
->num_planes
= 1;
870 pix_mp
->width
= clamp(pix_mp
->width
, MIN_WIDTH
, MAX_WIDTH
);
871 pix_mp
->width
= vic_round_dim(pix_mp
->width
, info
->width_div
);
873 pix_mp
->height
= clamp(pix_mp
->height
, MIN_HEIGHT
, MAX_HEIGHT
);
874 pix_mp
->height
= vic_round_dim(pix_mp
->height
,
877 pix_mp
->field
= V4L2_FIELD_NONE
;
878 plane
->bytesperline
=
879 pix_mp
->width
* info
->bytesperline_mult
;
880 plane
->sizeimage
= pix_mp
->width
* pix_mp
->height
*
881 info
->sizeimage_mult
/ info
->sizeimage_div
;
882 if (pix_mp
->pixelformat
== V4L2_PIX_FMT_FWHT
)
883 plane
->sizeimage
+= sizeof(struct fwht_cframe_hdr
);
892 static int vidioc_try_fmt_vid_cap(struct file
*file
, void *priv
,
893 struct v4l2_format
*f
)
895 struct vicodec_ctx
*ctx
= file2ctx(file
);
896 struct v4l2_pix_format_mplane
*pix_mp
;
897 struct v4l2_pix_format
*pix
;
900 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
904 pix
->pixelformat
= ctx
->is_enc
? V4L2_PIX_FMT_FWHT
:
905 find_fmt(f
->fmt
.pix
.pixelformat
)->id
;
906 pix
->colorspace
= ctx
->state
.colorspace
;
907 pix
->xfer_func
= ctx
->state
.xfer_func
;
908 pix
->ycbcr_enc
= ctx
->state
.ycbcr_enc
;
909 pix
->quantization
= ctx
->state
.quantization
;
911 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
914 pix_mp
= &f
->fmt
.pix_mp
;
915 pix_mp
->pixelformat
= ctx
->is_enc
? V4L2_PIX_FMT_FWHT
:
916 find_fmt(pix_mp
->pixelformat
)->id
;
917 pix_mp
->colorspace
= ctx
->state
.colorspace
;
918 pix_mp
->xfer_func
= ctx
->state
.xfer_func
;
919 pix_mp
->ycbcr_enc
= ctx
->state
.ycbcr_enc
;
920 pix_mp
->quantization
= ctx
->state
.quantization
;
926 return vidioc_try_fmt(ctx
, f
);
929 static int vidioc_try_fmt_vid_out(struct file
*file
, void *priv
,
930 struct v4l2_format
*f
)
932 struct vicodec_ctx
*ctx
= file2ctx(file
);
933 struct v4l2_pix_format_mplane
*pix_mp
;
934 struct v4l2_pix_format
*pix
;
937 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
942 pix
->pixelformat
= find_fmt(pix
->pixelformat
)->id
;
943 else if (ctx
->is_stateless
)
944 pix
->pixelformat
= V4L2_PIX_FMT_FWHT_STATELESS
;
946 pix
->pixelformat
= V4L2_PIX_FMT_FWHT
;
947 if (!pix
->colorspace
)
948 pix
->colorspace
= V4L2_COLORSPACE_REC709
;
950 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
953 pix_mp
= &f
->fmt
.pix_mp
;
955 pix_mp
->pixelformat
= find_fmt(pix_mp
->pixelformat
)->id
;
956 else if (ctx
->is_stateless
)
957 pix_mp
->pixelformat
= V4L2_PIX_FMT_FWHT_STATELESS
;
959 pix_mp
->pixelformat
= V4L2_PIX_FMT_FWHT
;
960 if (!pix_mp
->colorspace
)
961 pix_mp
->colorspace
= V4L2_COLORSPACE_REC709
;
967 return vidioc_try_fmt(ctx
, f
);
970 static int vidioc_s_fmt(struct vicodec_ctx
*ctx
, struct v4l2_format
*f
)
972 struct vicodec_q_data
*q_data
;
973 struct vb2_queue
*vq
;
974 bool fmt_changed
= true;
975 struct v4l2_pix_format_mplane
*pix_mp
;
976 struct v4l2_pix_format
*pix
;
978 vq
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
, f
->type
);
982 q_data
= get_q_data(ctx
, f
->type
);
987 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
988 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
990 if (ctx
->is_enc
&& V4L2_TYPE_IS_OUTPUT(f
->type
))
993 q_data
->info
->id
!= pix
->pixelformat
||
994 q_data
->coded_width
!= pix
->width
||
995 q_data
->coded_height
!= pix
->height
;
997 if (vb2_is_busy(vq
) && fmt_changed
)
1000 if (pix
->pixelformat
== V4L2_PIX_FMT_FWHT
)
1001 q_data
->info
= &pixfmt_fwht
;
1002 else if (pix
->pixelformat
== V4L2_PIX_FMT_FWHT_STATELESS
)
1003 q_data
->info
= &pixfmt_stateless_fwht
;
1005 q_data
->info
= find_fmt(pix
->pixelformat
);
1006 q_data
->coded_width
= pix
->width
;
1007 q_data
->coded_height
= pix
->height
;
1008 q_data
->sizeimage
= pix
->sizeimage
;
1010 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
1011 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
1012 pix_mp
= &f
->fmt
.pix_mp
;
1013 if (ctx
->is_enc
&& V4L2_TYPE_IS_OUTPUT(f
->type
))
1016 q_data
->info
->id
!= pix_mp
->pixelformat
||
1017 q_data
->coded_width
!= pix_mp
->width
||
1018 q_data
->coded_height
!= pix_mp
->height
;
1020 if (vb2_is_busy(vq
) && fmt_changed
)
1023 if (pix_mp
->pixelformat
== V4L2_PIX_FMT_FWHT
)
1024 q_data
->info
= &pixfmt_fwht
;
1025 else if (pix_mp
->pixelformat
== V4L2_PIX_FMT_FWHT_STATELESS
)
1026 q_data
->info
= &pixfmt_stateless_fwht
;
1028 q_data
->info
= find_fmt(pix_mp
->pixelformat
);
1029 q_data
->coded_width
= pix_mp
->width
;
1030 q_data
->coded_height
= pix_mp
->height
;
1031 q_data
->sizeimage
= pix_mp
->plane_fmt
[0].sizeimage
;
1038 "Setting format for type %d, coded wxh: %dx%d, fourcc: 0x%08x\n",
1039 f
->type
, q_data
->coded_width
, q_data
->coded_height
,
1045 static int vidioc_s_fmt_vid_cap(struct file
*file
, void *priv
,
1046 struct v4l2_format
*f
)
1050 ret
= vidioc_try_fmt_vid_cap(file
, priv
, f
);
1054 return vidioc_s_fmt(file2ctx(file
), f
);
1057 static int vidioc_s_fmt_vid_out(struct file
*file
, void *priv
,
1058 struct v4l2_format
*f
)
1060 struct vicodec_ctx
*ctx
= file2ctx(file
);
1061 struct vicodec_q_data
*q_data
;
1062 struct vicodec_q_data
*q_data_cap
;
1063 struct v4l2_pix_format
*pix
;
1064 struct v4l2_pix_format_mplane
*pix_mp
;
1065 u32 coded_w
= 0, coded_h
= 0;
1066 unsigned int size
= 0;
1069 q_data
= get_q_data(ctx
, f
->type
);
1070 q_data_cap
= get_q_data(ctx
, V4L2_BUF_TYPE_VIDEO_CAPTURE
);
1072 ret
= vidioc_try_fmt_vid_out(file
, priv
, f
);
1077 struct vb2_queue
*vq
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
, f
->type
);
1078 struct vb2_queue
*vq_cap
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
,
1079 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
1080 const struct v4l2_fwht_pixfmt_info
*info
= ctx
->is_stateless
?
1081 &pixfmt_stateless_fwht
: &pixfmt_fwht
;
1083 if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT
) {
1084 coded_w
= f
->fmt
.pix
.width
;
1085 coded_h
= f
->fmt
.pix
.height
;
1087 coded_w
= f
->fmt
.pix_mp
.width
;
1088 coded_h
= f
->fmt
.pix_mp
.height
;
1090 if (vb2_is_busy(vq
) && (coded_w
!= q_data
->coded_width
||
1091 coded_h
!= q_data
->coded_height
))
1093 size
= coded_w
* coded_h
*
1094 info
->sizeimage_mult
/ info
->sizeimage_div
;
1095 if (!ctx
->is_stateless
)
1096 size
+= sizeof(struct fwht_cframe_hdr
);
1098 if (vb2_is_busy(vq_cap
) && size
> q_data_cap
->sizeimage
)
1102 ret
= vidioc_s_fmt(file2ctx(file
), f
);
1105 q_data
->visible_width
= coded_w
;
1106 q_data
->visible_height
= coded_h
;
1107 q_data_cap
->coded_width
= coded_w
;
1108 q_data_cap
->coded_height
= coded_h
;
1109 q_data_cap
->sizeimage
= size
;
1113 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
1115 ctx
->state
.colorspace
= pix
->colorspace
;
1116 ctx
->state
.xfer_func
= pix
->xfer_func
;
1117 ctx
->state
.ycbcr_enc
= pix
->ycbcr_enc
;
1118 ctx
->state
.quantization
= pix
->quantization
;
1120 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
1121 pix_mp
= &f
->fmt
.pix_mp
;
1122 ctx
->state
.colorspace
= pix_mp
->colorspace
;
1123 ctx
->state
.xfer_func
= pix_mp
->xfer_func
;
1124 ctx
->state
.ycbcr_enc
= pix_mp
->ycbcr_enc
;
1125 ctx
->state
.quantization
= pix_mp
->quantization
;
1134 static int vidioc_g_selection(struct file
*file
, void *priv
,
1135 struct v4l2_selection
*s
)
1137 struct vicodec_ctx
*ctx
= file2ctx(file
);
1138 struct vicodec_q_data
*q_data
;
1140 q_data
= get_q_data(ctx
, s
->type
);
1144 * encoder supports only cropping on the OUTPUT buffer
1145 * decoder supports only composing on the CAPTURE buffer
1147 if (ctx
->is_enc
&& s
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT
) {
1148 switch (s
->target
) {
1149 case V4L2_SEL_TGT_CROP
:
1152 s
->r
.width
= q_data
->visible_width
;
1153 s
->r
.height
= q_data
->visible_height
;
1155 case V4L2_SEL_TGT_CROP_DEFAULT
:
1156 case V4L2_SEL_TGT_CROP_BOUNDS
:
1159 s
->r
.width
= q_data
->coded_width
;
1160 s
->r
.height
= q_data
->coded_height
;
1163 } else if (!ctx
->is_enc
&& s
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
1164 switch (s
->target
) {
1165 case V4L2_SEL_TGT_COMPOSE
:
1168 s
->r
.width
= q_data
->visible_width
;
1169 s
->r
.height
= q_data
->visible_height
;
1171 case V4L2_SEL_TGT_COMPOSE_DEFAULT
:
1172 case V4L2_SEL_TGT_COMPOSE_BOUNDS
:
1175 s
->r
.width
= q_data
->coded_width
;
1176 s
->r
.height
= q_data
->coded_height
;
1183 static int vidioc_s_selection(struct file
*file
, void *priv
,
1184 struct v4l2_selection
*s
)
1186 struct vicodec_ctx
*ctx
= file2ctx(file
);
1187 struct vicodec_q_data
*q_data
;
1189 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT
)
1192 q_data
= get_q_data(ctx
, s
->type
);
1196 if (!ctx
->is_enc
|| s
->target
!= V4L2_SEL_TGT_CROP
)
1201 q_data
->visible_width
= clamp(s
->r
.width
, MIN_WIDTH
,
1202 q_data
->coded_width
);
1203 s
->r
.width
= q_data
->visible_width
;
1204 q_data
->visible_height
= clamp(s
->r
.height
, MIN_HEIGHT
,
1205 q_data
->coded_height
);
1206 s
->r
.height
= q_data
->visible_height
;
1210 static int vicodec_encoder_cmd(struct file
*file
, void *fh
,
1211 struct v4l2_encoder_cmd
*ec
)
1213 struct vicodec_ctx
*ctx
= file2ctx(file
);
1216 ret
= v4l2_m2m_ioctl_try_encoder_cmd(file
, fh
, ec
);
1220 if (!vb2_is_streaming(&ctx
->fh
.m2m_ctx
->out_q_ctx
.q
))
1223 ret
= v4l2_m2m_ioctl_encoder_cmd(file
, fh
, ec
);
1227 if (ec
->cmd
== V4L2_ENC_CMD_STOP
&&
1228 v4l2_m2m_has_stopped(ctx
->fh
.m2m_ctx
))
1229 v4l2_event_queue_fh(&ctx
->fh
, &vicodec_eos_event
);
1231 if (ec
->cmd
== V4L2_ENC_CMD_START
&&
1232 v4l2_m2m_has_stopped(ctx
->fh
.m2m_ctx
))
1233 vb2_clear_last_buffer_dequeued(&ctx
->fh
.m2m_ctx
->cap_q_ctx
.q
);
1238 static int vicodec_decoder_cmd(struct file
*file
, void *fh
,
1239 struct v4l2_decoder_cmd
*dc
)
1241 struct vicodec_ctx
*ctx
= file2ctx(file
);
1245 * This ioctl should not be used with a stateless codec that doesn't
1246 * support holding buffers and the associated flush command.
1248 WARN_ON(ctx
->is_stateless
);
1250 ret
= v4l2_m2m_ioctl_try_decoder_cmd(file
, fh
, dc
);
1254 if (!vb2_is_streaming(&ctx
->fh
.m2m_ctx
->out_q_ctx
.q
))
1257 ret
= v4l2_m2m_ioctl_decoder_cmd(file
, fh
, dc
);
1261 if (dc
->cmd
== V4L2_DEC_CMD_STOP
&&
1262 v4l2_m2m_has_stopped(ctx
->fh
.m2m_ctx
))
1263 v4l2_event_queue_fh(&ctx
->fh
, &vicodec_eos_event
);
1265 if (dc
->cmd
== V4L2_DEC_CMD_START
&&
1266 v4l2_m2m_has_stopped(ctx
->fh
.m2m_ctx
))
1267 vb2_clear_last_buffer_dequeued(&ctx
->fh
.m2m_ctx
->cap_q_ctx
.q
);
1272 static int vicodec_enum_framesizes(struct file
*file
, void *fh
,
1273 struct v4l2_frmsizeenum
*fsize
)
1275 switch (fsize
->pixel_format
) {
1276 case V4L2_PIX_FMT_FWHT_STATELESS
:
1278 case V4L2_PIX_FMT_FWHT
:
1281 if (find_fmt(fsize
->pixel_format
)->id
== fsize
->pixel_format
)
1289 fsize
->type
= V4L2_FRMSIZE_TYPE_STEPWISE
;
1291 fsize
->stepwise
.min_width
= MIN_WIDTH
;
1292 fsize
->stepwise
.max_width
= MAX_WIDTH
;
1293 fsize
->stepwise
.step_width
= 8;
1294 fsize
->stepwise
.min_height
= MIN_HEIGHT
;
1295 fsize
->stepwise
.max_height
= MAX_HEIGHT
;
1296 fsize
->stepwise
.step_height
= 8;
1301 static int vicodec_subscribe_event(struct v4l2_fh
*fh
,
1302 const struct v4l2_event_subscription
*sub
)
1304 struct vicodec_ctx
*ctx
= container_of(fh
, struct vicodec_ctx
, fh
);
1306 switch (sub
->type
) {
1307 case V4L2_EVENT_SOURCE_CHANGE
:
1311 case V4L2_EVENT_EOS
:
1312 if (ctx
->is_stateless
)
1314 return v4l2_event_subscribe(fh
, sub
, 0, NULL
);
1316 return v4l2_ctrl_subscribe_event(fh
, sub
);
1320 static const struct v4l2_ioctl_ops vicodec_ioctl_ops
= {
1321 .vidioc_querycap
= vidioc_querycap
,
1323 .vidioc_enum_fmt_vid_cap
= vidioc_enum_fmt_vid_cap
,
1324 .vidioc_g_fmt_vid_cap
= vidioc_g_fmt_vid_cap
,
1325 .vidioc_try_fmt_vid_cap
= vidioc_try_fmt_vid_cap
,
1326 .vidioc_s_fmt_vid_cap
= vidioc_s_fmt_vid_cap
,
1328 .vidioc_g_fmt_vid_cap_mplane
= vidioc_g_fmt_vid_cap
,
1329 .vidioc_try_fmt_vid_cap_mplane
= vidioc_try_fmt_vid_cap
,
1330 .vidioc_s_fmt_vid_cap_mplane
= vidioc_s_fmt_vid_cap
,
1332 .vidioc_enum_fmt_vid_out
= vidioc_enum_fmt_vid_out
,
1333 .vidioc_g_fmt_vid_out
= vidioc_g_fmt_vid_out
,
1334 .vidioc_try_fmt_vid_out
= vidioc_try_fmt_vid_out
,
1335 .vidioc_s_fmt_vid_out
= vidioc_s_fmt_vid_out
,
1337 .vidioc_g_fmt_vid_out_mplane
= vidioc_g_fmt_vid_out
,
1338 .vidioc_try_fmt_vid_out_mplane
= vidioc_try_fmt_vid_out
,
1339 .vidioc_s_fmt_vid_out_mplane
= vidioc_s_fmt_vid_out
,
1341 .vidioc_reqbufs
= v4l2_m2m_ioctl_reqbufs
,
1342 .vidioc_querybuf
= v4l2_m2m_ioctl_querybuf
,
1343 .vidioc_qbuf
= v4l2_m2m_ioctl_qbuf
,
1344 .vidioc_dqbuf
= v4l2_m2m_ioctl_dqbuf
,
1345 .vidioc_prepare_buf
= v4l2_m2m_ioctl_prepare_buf
,
1346 .vidioc_create_bufs
= v4l2_m2m_ioctl_create_bufs
,
1347 .vidioc_expbuf
= v4l2_m2m_ioctl_expbuf
,
1348 .vidioc_remove_bufs
= v4l2_m2m_ioctl_remove_bufs
,
1350 .vidioc_streamon
= v4l2_m2m_ioctl_streamon
,
1351 .vidioc_streamoff
= v4l2_m2m_ioctl_streamoff
,
1353 .vidioc_g_selection
= vidioc_g_selection
,
1354 .vidioc_s_selection
= vidioc_s_selection
,
1356 .vidioc_try_encoder_cmd
= v4l2_m2m_ioctl_try_encoder_cmd
,
1357 .vidioc_encoder_cmd
= vicodec_encoder_cmd
,
1358 .vidioc_try_decoder_cmd
= v4l2_m2m_ioctl_try_decoder_cmd
,
1359 .vidioc_decoder_cmd
= vicodec_decoder_cmd
,
1360 .vidioc_enum_framesizes
= vicodec_enum_framesizes
,
1362 .vidioc_subscribe_event
= vicodec_subscribe_event
,
1363 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
1371 static int vicodec_queue_setup(struct vb2_queue
*vq
, unsigned int *nbuffers
,
1372 unsigned int *nplanes
, unsigned int sizes
[],
1373 struct device
*alloc_devs
[])
1375 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(vq
);
1376 struct vicodec_q_data
*q_data
= get_q_data(ctx
, vq
->type
);
1377 unsigned int size
= q_data
->sizeimage
;
1380 return sizes
[0] < size
? -EINVAL
: 0;
1384 q_data
->vb2_sizeimage
= size
;
1388 static int vicodec_buf_out_validate(struct vb2_buffer
*vb
)
1390 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1392 vbuf
->field
= V4L2_FIELD_NONE
;
1396 static int vicodec_buf_prepare(struct vb2_buffer
*vb
)
1398 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1399 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1400 struct vicodec_q_data
*q_data
;
1402 dprintk(ctx
->dev
, "type: %d\n", vb
->vb2_queue
->type
);
1404 q_data
= get_q_data(ctx
, vb
->vb2_queue
->type
);
1405 if (V4L2_TYPE_IS_OUTPUT(vb
->vb2_queue
->type
)) {
1406 if (vbuf
->field
== V4L2_FIELD_ANY
)
1407 vbuf
->field
= V4L2_FIELD_NONE
;
1408 if (vbuf
->field
!= V4L2_FIELD_NONE
) {
1409 dprintk(ctx
->dev
, "%s field isn't supported\n",
1415 if (vb2_plane_size(vb
, 0) < q_data
->vb2_sizeimage
) {
1417 "%s data will not fit into plane (%lu < %lu)\n",
1418 __func__
, vb2_plane_size(vb
, 0),
1419 (long)q_data
->vb2_sizeimage
);
1426 static void vicodec_buf_queue(struct vb2_buffer
*vb
)
1428 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1429 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1430 unsigned int sz
= vb2_get_plane_payload(&vbuf
->vb2_buf
, 0);
1431 u8
*p_src
= vb2_plane_vaddr(&vbuf
->vb2_buf
, 0);
1433 struct vb2_queue
*vq_out
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
,
1434 V4L2_BUF_TYPE_VIDEO_OUTPUT
);
1435 struct vb2_queue
*vq_cap
= v4l2_m2m_get_vq(ctx
->fh
.m2m_ctx
,
1436 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
1437 bool header_valid
= false;
1438 static const struct v4l2_event rs_event
= {
1439 .type
= V4L2_EVENT_SOURCE_CHANGE
,
1440 .u
.src_change
.changes
= V4L2_EVENT_SRC_CH_RESOLUTION
,
1443 if (V4L2_TYPE_IS_CAPTURE(vb
->vb2_queue
->type
) &&
1444 vb2_is_streaming(vb
->vb2_queue
) &&
1445 v4l2_m2m_dst_buf_is_last(ctx
->fh
.m2m_ctx
)) {
1448 for (i
= 0; i
< vb
->num_planes
; i
++)
1449 vb2_set_plane_payload(vb
, i
, 0);
1451 vbuf
->field
= V4L2_FIELD_NONE
;
1453 get_q_data(ctx
, vb
->vb2_queue
->type
)->sequence
++;
1455 v4l2_m2m_last_buffer_done(ctx
->fh
.m2m_ctx
, vbuf
);
1456 v4l2_event_queue_fh(&ctx
->fh
, &vicodec_eos_event
);
1460 /* buf_queue handles only the first source change event */
1461 if (ctx
->first_source_change_sent
) {
1462 v4l2_m2m_buf_queue(ctx
->fh
.m2m_ctx
, vbuf
);
1467 * if both queues are streaming, the source change event is
1468 * handled in job_ready
1470 if (vb2_is_streaming(vq_cap
) && vb2_is_streaming(vq_out
)) {
1471 v4l2_m2m_buf_queue(ctx
->fh
.m2m_ctx
, vbuf
);
1476 * source change event is relevant only for the stateful decoder
1477 * in the compressed stream
1479 if (ctx
->is_stateless
|| ctx
->is_enc
||
1480 V4L2_TYPE_IS_CAPTURE(vb
->vb2_queue
->type
)) {
1481 v4l2_m2m_buf_queue(ctx
->fh
.m2m_ctx
, vbuf
);
1486 enum vb2_buffer_state state
=
1487 get_next_header(ctx
, &p
, p_src
+ sz
- p
);
1489 if (ctx
->header_size
< sizeof(struct fwht_cframe_hdr
)) {
1490 v4l2_m2m_buf_done(vbuf
, state
);
1493 header_valid
= is_header_valid(&ctx
->state
.header
);
1495 * p points right after the end of the header in the
1496 * buffer. If the header is invalid we set p to point
1497 * to the next byte after the start of the header
1499 if (!header_valid
) {
1500 p
= p
- sizeof(struct fwht_cframe_hdr
) + 1;
1503 ctx
->header_size
= 0;
1504 ctx
->comp_magic_cnt
= 0;
1507 } while (!header_valid
);
1509 ctx
->cur_buf_offset
= p
- p_src
;
1510 update_capture_data_from_header(ctx
);
1511 ctx
->first_source_change_sent
= true;
1512 v4l2_event_queue_fh(&ctx
->fh
, &rs_event
);
1513 v4l2_m2m_buf_queue(ctx
->fh
.m2m_ctx
, vbuf
);
1516 static void vicodec_return_bufs(struct vb2_queue
*q
, u32 state
)
1518 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(q
);
1519 struct vb2_v4l2_buffer
*vbuf
;
1522 if (V4L2_TYPE_IS_OUTPUT(q
->type
))
1523 vbuf
= v4l2_m2m_src_buf_remove(ctx
->fh
.m2m_ctx
);
1525 vbuf
= v4l2_m2m_dst_buf_remove(ctx
->fh
.m2m_ctx
);
1528 v4l2_ctrl_request_complete(vbuf
->vb2_buf
.req_obj
.req
,
1530 spin_lock(ctx
->lock
);
1531 v4l2_m2m_buf_done(vbuf
, state
);
1532 spin_unlock(ctx
->lock
);
1536 static unsigned int total_frame_size(struct vicodec_q_data
*q_data
)
1539 unsigned int chroma_div
;
1541 if (!q_data
->info
) {
1545 size
= q_data
->coded_width
* q_data
->coded_height
;
1546 chroma_div
= q_data
->info
->width_div
* q_data
->info
->height_div
;
1548 if (q_data
->info
->components_num
== 4)
1549 return 2 * size
+ 2 * (size
/ chroma_div
);
1550 else if (q_data
->info
->components_num
== 3)
1551 return size
+ 2 * (size
/ chroma_div
);
1555 static int vicodec_start_streaming(struct vb2_queue
*q
,
1558 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(q
);
1559 struct vicodec_q_data
*q_data
= get_q_data(ctx
, q
->type
);
1560 struct v4l2_fwht_state
*state
= &ctx
->state
;
1561 const struct v4l2_fwht_pixfmt_info
*info
= q_data
->info
;
1562 unsigned int size
= q_data
->coded_width
* q_data
->coded_height
;
1563 unsigned int chroma_div
;
1564 unsigned int total_planes_size
;
1565 u8
*new_comp_frame
= NULL
;
1567 chroma_div
= info
->width_div
* info
->height_div
;
1568 q_data
->sequence
= 0;
1570 v4l2_m2m_update_start_streaming_state(ctx
->fh
.m2m_ctx
, q
);
1574 if ((V4L2_TYPE_IS_OUTPUT(q
->type
) && !ctx
->is_enc
) ||
1575 (V4L2_TYPE_IS_CAPTURE(q
->type
) && ctx
->is_enc
))
1578 if (info
->id
== V4L2_PIX_FMT_FWHT
||
1579 info
->id
== V4L2_PIX_FMT_FWHT_STATELESS
) {
1580 vicodec_return_bufs(q
, VB2_BUF_STATE_QUEUED
);
1583 total_planes_size
= total_frame_size(q_data
);
1584 ctx
->comp_max_size
= total_planes_size
;
1586 state
->visible_width
= q_data
->visible_width
;
1587 state
->visible_height
= q_data
->visible_height
;
1588 state
->coded_width
= q_data
->coded_width
;
1589 state
->coded_height
= q_data
->coded_height
;
1590 state
->stride
= q_data
->coded_width
*
1591 info
->bytesperline_mult
;
1593 if (ctx
->is_stateless
) {
1594 state
->ref_stride
= state
->stride
;
1597 state
->ref_stride
= q_data
->coded_width
* info
->luma_alpha_step
;
1599 state
->ref_frame
.buf
= kvmalloc(total_planes_size
, GFP_KERNEL
);
1600 state
->ref_frame
.luma
= state
->ref_frame
.buf
;
1601 new_comp_frame
= kvmalloc(ctx
->comp_max_size
, GFP_KERNEL
);
1603 if (!state
->ref_frame
.luma
|| !new_comp_frame
) {
1604 kvfree(state
->ref_frame
.luma
);
1605 kvfree(new_comp_frame
);
1606 vicodec_return_bufs(q
, VB2_BUF_STATE_QUEUED
);
1610 * if state->compressed_frame was already allocated then
1611 * it contain data of the first frame of the new resolution
1613 if (state
->compressed_frame
) {
1614 if (ctx
->comp_size
> ctx
->comp_max_size
)
1615 ctx
->comp_size
= ctx
->comp_max_size
;
1617 memcpy(new_comp_frame
,
1618 state
->compressed_frame
, ctx
->comp_size
);
1621 kvfree(state
->compressed_frame
);
1622 state
->compressed_frame
= new_comp_frame
;
1624 if (info
->components_num
< 3) {
1625 state
->ref_frame
.cb
= NULL
;
1626 state
->ref_frame
.cr
= NULL
;
1627 state
->ref_frame
.alpha
= NULL
;
1631 state
->ref_frame
.cb
= state
->ref_frame
.luma
+ size
;
1632 state
->ref_frame
.cr
= state
->ref_frame
.cb
+ size
/ chroma_div
;
1634 if (info
->components_num
== 4)
1635 state
->ref_frame
.alpha
=
1636 state
->ref_frame
.cr
+ size
/ chroma_div
;
1638 state
->ref_frame
.alpha
= NULL
;
1643 static void vicodec_stop_streaming(struct vb2_queue
*q
)
1645 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(q
);
1647 vicodec_return_bufs(q
, VB2_BUF_STATE_ERROR
);
1649 v4l2_m2m_update_stop_streaming_state(ctx
->fh
.m2m_ctx
, q
);
1651 if (V4L2_TYPE_IS_OUTPUT(q
->type
) &&
1652 v4l2_m2m_has_stopped(ctx
->fh
.m2m_ctx
))
1653 v4l2_event_queue_fh(&ctx
->fh
, &vicodec_eos_event
);
1655 if (!ctx
->is_enc
&& V4L2_TYPE_IS_OUTPUT(q
->type
))
1656 ctx
->first_source_change_sent
= false;
1658 if ((!V4L2_TYPE_IS_OUTPUT(q
->type
) && !ctx
->is_enc
) ||
1659 (V4L2_TYPE_IS_OUTPUT(q
->type
) && ctx
->is_enc
)) {
1660 if (!ctx
->is_stateless
)
1661 kvfree(ctx
->state
.ref_frame
.buf
);
1662 ctx
->state
.ref_frame
.buf
= NULL
;
1663 ctx
->state
.ref_frame
.luma
= NULL
;
1664 ctx
->comp_max_size
= 0;
1665 ctx
->source_changed
= false;
1667 if (V4L2_TYPE_IS_OUTPUT(q
->type
) && !ctx
->is_enc
) {
1668 ctx
->cur_buf_offset
= 0;
1670 ctx
->header_size
= 0;
1671 ctx
->comp_magic_cnt
= 0;
1672 ctx
->comp_has_frame
= false;
1673 ctx
->comp_has_next_frame
= false;
1677 static void vicodec_buf_request_complete(struct vb2_buffer
*vb
)
1679 struct vicodec_ctx
*ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1681 v4l2_ctrl_request_complete(vb
->req_obj
.req
, &ctx
->hdl
);
1685 static const struct vb2_ops vicodec_qops
= {
1686 .queue_setup
= vicodec_queue_setup
,
1687 .buf_out_validate
= vicodec_buf_out_validate
,
1688 .buf_prepare
= vicodec_buf_prepare
,
1689 .buf_queue
= vicodec_buf_queue
,
1690 .buf_request_complete
= vicodec_buf_request_complete
,
1691 .start_streaming
= vicodec_start_streaming
,
1692 .stop_streaming
= vicodec_stop_streaming
,
1695 static int queue_init(void *priv
, struct vb2_queue
*src_vq
,
1696 struct vb2_queue
*dst_vq
)
1698 struct vicodec_ctx
*ctx
= priv
;
1701 src_vq
->type
= (multiplanar
?
1702 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
1703 V4L2_BUF_TYPE_VIDEO_OUTPUT
);
1704 src_vq
->io_modes
= VB2_MMAP
| VB2_USERPTR
| VB2_DMABUF
;
1705 src_vq
->drv_priv
= ctx
;
1706 src_vq
->buf_struct_size
= sizeof(struct v4l2_m2m_buffer
);
1707 src_vq
->ops
= &vicodec_qops
;
1708 src_vq
->mem_ops
= &vb2_vmalloc_memops
;
1709 src_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1711 src_vq
->lock
= &ctx
->dev
->stateful_enc
.mutex
;
1712 src_vq
->min_reqbufs_allocation
= VICODEC_REC_BUFS
;
1713 } else if (ctx
->is_stateless
) {
1714 src_vq
->lock
= &ctx
->dev
->stateless_dec
.mutex
;
1716 src_vq
->lock
= &ctx
->dev
->stateful_dec
.mutex
;
1718 src_vq
->supports_requests
= ctx
->is_stateless
;
1719 src_vq
->requires_requests
= ctx
->is_stateless
;
1720 ret
= vb2_queue_init(src_vq
);
1724 dst_vq
->type
= (multiplanar
?
1725 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
1726 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
1727 dst_vq
->io_modes
= VB2_MMAP
| VB2_USERPTR
| VB2_DMABUF
;
1728 dst_vq
->max_num_buffers
= 64;
1729 dst_vq
->drv_priv
= ctx
;
1730 dst_vq
->buf_struct_size
= sizeof(struct v4l2_m2m_buffer
);
1731 dst_vq
->ops
= &vicodec_qops
;
1732 dst_vq
->mem_ops
= &vb2_vmalloc_memops
;
1733 dst_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1734 dst_vq
->lock
= src_vq
->lock
;
1735 if (!ctx
->is_stateless
&& !ctx
->is_enc
)
1736 dst_vq
->min_reqbufs_allocation
= VICODEC_REC_BUFS
;
1738 return vb2_queue_init(dst_vq
);
1741 static int vicodec_try_ctrl(struct v4l2_ctrl
*ctrl
)
1743 struct vicodec_ctx
*ctx
= container_of(ctrl
->handler
,
1744 struct vicodec_ctx
, hdl
);
1745 const struct v4l2_ctrl_fwht_params
*params
;
1746 struct vicodec_q_data
*q_dst
= get_q_data(ctx
,
1747 V4L2_BUF_TYPE_VIDEO_CAPTURE
);
1750 case V4L2_CID_STATELESS_FWHT_PARAMS
:
1753 params
= ctrl
->p_new
.p_fwht_params
;
1754 if (params
->width
> q_dst
->coded_width
||
1755 params
->width
< MIN_WIDTH
||
1756 params
->height
> q_dst
->coded_height
||
1757 params
->height
< MIN_HEIGHT
)
1759 if (!validate_by_version(params
->flags
, params
->version
))
1761 if (!validate_stateless_params_flags(params
, q_dst
->info
))
1770 static void update_header_from_stateless_params(struct vicodec_ctx
*ctx
,
1771 const struct v4l2_ctrl_fwht_params
*params
)
1773 struct fwht_cframe_hdr
*p_hdr
= &ctx
->state
.header
;
1775 p_hdr
->magic1
= FWHT_MAGIC1
;
1776 p_hdr
->magic2
= FWHT_MAGIC2
;
1777 p_hdr
->version
= htonl(params
->version
);
1778 p_hdr
->width
= htonl(params
->width
);
1779 p_hdr
->height
= htonl(params
->height
);
1780 p_hdr
->flags
= htonl(params
->flags
);
1781 p_hdr
->colorspace
= htonl(params
->colorspace
);
1782 p_hdr
->xfer_func
= htonl(params
->xfer_func
);
1783 p_hdr
->ycbcr_enc
= htonl(params
->ycbcr_enc
);
1784 p_hdr
->quantization
= htonl(params
->quantization
);
1787 static int vicodec_s_ctrl(struct v4l2_ctrl
*ctrl
)
1789 struct vicodec_ctx
*ctx
= container_of(ctrl
->handler
,
1790 struct vicodec_ctx
, hdl
);
1791 const struct v4l2_ctrl_fwht_params
*params
;
1794 case V4L2_CID_MPEG_VIDEO_GOP_SIZE
:
1795 ctx
->state
.gop_size
= ctrl
->val
;
1797 case V4L2_CID_FWHT_I_FRAME_QP
:
1798 ctx
->state
.i_frame_qp
= ctrl
->val
;
1800 case V4L2_CID_FWHT_P_FRAME_QP
:
1801 ctx
->state
.p_frame_qp
= ctrl
->val
;
1803 case V4L2_CID_STATELESS_FWHT_PARAMS
:
1804 params
= ctrl
->p_new
.p_fwht_params
;
1805 update_header_from_stateless_params(ctx
, params
);
1806 ctx
->state
.ref_frame_ts
= params
->backward_ref_ts
;
1812 static const struct v4l2_ctrl_ops vicodec_ctrl_ops
= {
1813 .s_ctrl
= vicodec_s_ctrl
,
1814 .try_ctrl
= vicodec_try_ctrl
,
1817 static const struct v4l2_ctrl_config vicodec_ctrl_stateless_state
= {
1818 .ops
= &vicodec_ctrl_ops
,
1819 .id
= V4L2_CID_STATELESS_FWHT_PARAMS
,
1820 .elem_size
= sizeof(struct v4l2_ctrl_fwht_params
),
1826 static int vicodec_open(struct file
*file
)
1828 const struct v4l2_fwht_pixfmt_info
*info
= v4l2_fwht_get_pixfmt(0);
1829 struct video_device
*vfd
= video_devdata(file
);
1830 struct vicodec_dev
*dev
= video_drvdata(file
);
1831 struct vicodec_ctx
*ctx
= NULL
;
1832 struct v4l2_ctrl_handler
*hdl
;
1833 unsigned int raw_size
;
1834 unsigned int comp_size
;
1837 if (mutex_lock_interruptible(vfd
->lock
))
1838 return -ERESTARTSYS
;
1839 ctx
= kzalloc(sizeof(*ctx
), GFP_KERNEL
);
1845 if (vfd
== &dev
->stateful_enc
.vfd
)
1847 else if (vfd
== &dev
->stateless_dec
.vfd
)
1848 ctx
->is_stateless
= true;
1850 v4l2_fh_init(&ctx
->fh
, video_devdata(file
));
1851 file
->private_data
= &ctx
->fh
;
1854 v4l2_ctrl_handler_init(hdl
, 5);
1855 v4l2_ctrl_new_std(hdl
, &vicodec_ctrl_ops
, V4L2_CID_MPEG_VIDEO_GOP_SIZE
,
1857 v4l2_ctrl_new_std(hdl
, &vicodec_ctrl_ops
, V4L2_CID_FWHT_I_FRAME_QP
,
1859 v4l2_ctrl_new_std(hdl
, &vicodec_ctrl_ops
, V4L2_CID_FWHT_P_FRAME_QP
,
1862 if (ctx
->is_stateless
)
1863 v4l2_ctrl_new_custom(hdl
, &vicodec_ctrl_stateless_state
, NULL
);
1865 v4l2_ctrl_new_std(hdl
, &vicodec_ctrl_ops
, ctx
->is_enc
?
1866 V4L2_CID_MIN_BUFFERS_FOR_OUTPUT
:
1867 V4L2_CID_MIN_BUFFERS_FOR_CAPTURE
,
1868 VICODEC_REC_BUFS
, VICODEC_REC_BUFS
, 1,
1873 v4l2_ctrl_handler_free(hdl
);
1877 ctx
->fh
.ctrl_handler
= hdl
;
1878 v4l2_ctrl_handler_setup(hdl
);
1881 ctx
->q_data
[V4L2_M2M_SRC
].info
= info
;
1882 else if (ctx
->is_stateless
)
1883 ctx
->q_data
[V4L2_M2M_SRC
].info
= &pixfmt_stateless_fwht
;
1885 ctx
->q_data
[V4L2_M2M_SRC
].info
= &pixfmt_fwht
;
1886 ctx
->q_data
[V4L2_M2M_SRC
].coded_width
= 1280;
1887 ctx
->q_data
[V4L2_M2M_SRC
].coded_height
= 720;
1888 ctx
->q_data
[V4L2_M2M_SRC
].visible_width
= 1280;
1889 ctx
->q_data
[V4L2_M2M_SRC
].visible_height
= 720;
1890 raw_size
= 1280 * 720 * info
->sizeimage_mult
/ info
->sizeimage_div
;
1891 comp_size
= 1280 * 720 * pixfmt_fwht
.sizeimage_mult
/
1892 pixfmt_fwht
.sizeimage_div
;
1894 ctx
->q_data
[V4L2_M2M_SRC
].sizeimage
= raw_size
;
1895 else if (ctx
->is_stateless
)
1896 ctx
->q_data
[V4L2_M2M_SRC
].sizeimage
= comp_size
;
1898 ctx
->q_data
[V4L2_M2M_SRC
].sizeimage
=
1899 comp_size
+ sizeof(struct fwht_cframe_hdr
);
1900 ctx
->q_data
[V4L2_M2M_DST
] = ctx
->q_data
[V4L2_M2M_SRC
];
1902 ctx
->q_data
[V4L2_M2M_DST
].info
= &pixfmt_fwht
;
1903 ctx
->q_data
[V4L2_M2M_DST
].sizeimage
=
1904 comp_size
+ sizeof(struct fwht_cframe_hdr
);
1906 ctx
->q_data
[V4L2_M2M_DST
].info
= info
;
1907 ctx
->q_data
[V4L2_M2M_DST
].sizeimage
= raw_size
;
1910 ctx
->state
.colorspace
= V4L2_COLORSPACE_REC709
;
1913 ctx
->fh
.m2m_ctx
= v4l2_m2m_ctx_init(dev
->stateful_enc
.m2m_dev
,
1915 ctx
->lock
= &dev
->stateful_enc
.lock
;
1916 } else if (ctx
->is_stateless
) {
1917 ctx
->fh
.m2m_ctx
= v4l2_m2m_ctx_init(dev
->stateless_dec
.m2m_dev
,
1919 ctx
->lock
= &dev
->stateless_dec
.lock
;
1921 ctx
->fh
.m2m_ctx
= v4l2_m2m_ctx_init(dev
->stateful_dec
.m2m_dev
,
1923 ctx
->lock
= &dev
->stateful_dec
.lock
;
1926 if (IS_ERR(ctx
->fh
.m2m_ctx
)) {
1927 rc
= PTR_ERR(ctx
->fh
.m2m_ctx
);
1929 v4l2_ctrl_handler_free(hdl
);
1930 v4l2_fh_exit(&ctx
->fh
);
1935 v4l2_fh_add(&ctx
->fh
);
1938 mutex_unlock(vfd
->lock
);
1942 static int vicodec_release(struct file
*file
)
1944 struct video_device
*vfd
= video_devdata(file
);
1945 struct vicodec_ctx
*ctx
= file2ctx(file
);
1947 mutex_lock(vfd
->lock
);
1948 v4l2_m2m_ctx_release(ctx
->fh
.m2m_ctx
);
1949 mutex_unlock(vfd
->lock
);
1950 v4l2_fh_del(&ctx
->fh
);
1951 v4l2_fh_exit(&ctx
->fh
);
1952 v4l2_ctrl_handler_free(&ctx
->hdl
);
1953 kvfree(ctx
->state
.compressed_frame
);
1959 static int vicodec_request_validate(struct media_request
*req
)
1961 struct media_request_object
*obj
;
1962 struct v4l2_ctrl_handler
*parent_hdl
, *hdl
;
1963 struct vicodec_ctx
*ctx
= NULL
;
1964 struct v4l2_ctrl
*ctrl
;
1967 list_for_each_entry(obj
, &req
->objects
, list
) {
1968 struct vb2_buffer
*vb
;
1970 if (vb2_request_object_is_buffer(obj
)) {
1971 vb
= container_of(obj
, struct vb2_buffer
, req_obj
);
1972 ctx
= vb2_get_drv_priv(vb
->vb2_queue
);
1979 pr_err("No buffer was provided with the request\n");
1983 count
= vb2_request_buffer_cnt(req
);
1985 v4l2_info(&ctx
->dev
->v4l2_dev
,
1986 "No buffer was provided with the request\n");
1988 } else if (count
> 1) {
1989 v4l2_info(&ctx
->dev
->v4l2_dev
,
1990 "More than one buffer was provided with the request\n");
1994 parent_hdl
= &ctx
->hdl
;
1996 hdl
= v4l2_ctrl_request_hdl_find(req
, parent_hdl
);
1998 v4l2_info(&ctx
->dev
->v4l2_dev
, "Missing codec control\n");
2001 ctrl
= v4l2_ctrl_request_hdl_ctrl_find(hdl
,
2002 vicodec_ctrl_stateless_state
.id
);
2003 v4l2_ctrl_request_hdl_put(hdl
);
2005 v4l2_info(&ctx
->dev
->v4l2_dev
,
2006 "Missing required codec control\n");
2010 return vb2_request_validate(req
);
2013 static const struct v4l2_file_operations vicodec_fops
= {
2014 .owner
= THIS_MODULE
,
2015 .open
= vicodec_open
,
2016 .release
= vicodec_release
,
2017 .poll
= v4l2_m2m_fop_poll
,
2018 .unlocked_ioctl
= video_ioctl2
,
2019 .mmap
= v4l2_m2m_fop_mmap
,
2022 static const struct video_device vicodec_videodev
= {
2023 .name
= VICODEC_NAME
,
2024 .vfl_dir
= VFL_DIR_M2M
,
2025 .fops
= &vicodec_fops
,
2026 .ioctl_ops
= &vicodec_ioctl_ops
,
2028 .release
= video_device_release_empty
,
2031 static const struct media_device_ops vicodec_m2m_media_ops
= {
2032 .req_validate
= vicodec_request_validate
,
2033 .req_queue
= v4l2_m2m_request_queue
,
2036 static const struct v4l2_m2m_ops m2m_ops
= {
2037 .device_run
= device_run
,
2038 .job_ready
= job_ready
,
2041 static int register_instance(struct vicodec_dev
*dev
,
2042 struct vicodec_dev_instance
*dev_instance
,
2043 const char *name
, bool is_enc
, bool is_stateless
)
2045 struct video_device
*vfd
;
2048 spin_lock_init(&dev_instance
->lock
);
2049 mutex_init(&dev_instance
->mutex
);
2050 dev_instance
->m2m_dev
= v4l2_m2m_init(&m2m_ops
);
2051 if (IS_ERR(dev_instance
->m2m_dev
)) {
2052 v4l2_err(&dev
->v4l2_dev
, "Failed to init vicodec enc device\n");
2053 return PTR_ERR(dev_instance
->m2m_dev
);
2056 dev_instance
->vfd
= vicodec_videodev
;
2057 vfd
= &dev_instance
->vfd
;
2058 vfd
->lock
= &dev_instance
->mutex
;
2059 vfd
->v4l2_dev
= &dev
->v4l2_dev
;
2060 strscpy(vfd
->name
, name
, sizeof(vfd
->name
));
2061 vfd
->device_caps
= V4L2_CAP_STREAMING
|
2062 (multiplanar
? V4L2_CAP_VIDEO_M2M_MPLANE
: V4L2_CAP_VIDEO_M2M
);
2063 if (is_enc
|| is_stateless
) {
2064 v4l2_disable_ioctl(vfd
, VIDIOC_DECODER_CMD
);
2065 v4l2_disable_ioctl(vfd
, VIDIOC_TRY_DECODER_CMD
);
2068 v4l2_disable_ioctl(vfd
, VIDIOC_ENCODER_CMD
);
2069 v4l2_disable_ioctl(vfd
, VIDIOC_TRY_ENCODER_CMD
);
2071 video_set_drvdata(vfd
, dev
);
2073 ret
= video_register_device(vfd
, VFL_TYPE_VIDEO
, 0);
2075 v4l2_err(&dev
->v4l2_dev
, "Failed to register video device '%s'\n", name
);
2076 v4l2_m2m_release(dev_instance
->m2m_dev
);
2079 v4l2_info(&dev
->v4l2_dev
, "Device '%s' registered as /dev/video%d\n",
2084 static void vicodec_v4l2_dev_release(struct v4l2_device
*v4l2_dev
)
2086 struct vicodec_dev
*dev
= container_of(v4l2_dev
, struct vicodec_dev
, v4l2_dev
);
2088 v4l2_device_unregister(&dev
->v4l2_dev
);
2089 v4l2_m2m_release(dev
->stateful_enc
.m2m_dev
);
2090 v4l2_m2m_release(dev
->stateful_dec
.m2m_dev
);
2091 v4l2_m2m_release(dev
->stateless_dec
.m2m_dev
);
2092 #ifdef CONFIG_MEDIA_CONTROLLER
2093 media_device_cleanup(&dev
->mdev
);
2098 static int vicodec_probe(struct platform_device
*pdev
)
2100 struct vicodec_dev
*dev
;
2103 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
2107 ret
= v4l2_device_register(&pdev
->dev
, &dev
->v4l2_dev
);
2111 dev
->v4l2_dev
.release
= vicodec_v4l2_dev_release
;
2113 #ifdef CONFIG_MEDIA_CONTROLLER
2114 dev
->mdev
.dev
= &pdev
->dev
;
2115 strscpy(dev
->mdev
.model
, "vicodec", sizeof(dev
->mdev
.model
));
2116 strscpy(dev
->mdev
.bus_info
, "platform:vicodec",
2117 sizeof(dev
->mdev
.bus_info
));
2118 media_device_init(&dev
->mdev
);
2119 dev
->mdev
.ops
= &vicodec_m2m_media_ops
;
2120 dev
->v4l2_dev
.mdev
= &dev
->mdev
;
2123 platform_set_drvdata(pdev
, dev
);
2125 ret
= register_instance(dev
, &dev
->stateful_enc
, "stateful-encoder",
2130 ret
= register_instance(dev
, &dev
->stateful_dec
, "stateful-decoder",
2135 ret
= register_instance(dev
, &dev
->stateless_dec
, "stateless-decoder",
2140 #ifdef CONFIG_MEDIA_CONTROLLER
2141 ret
= v4l2_m2m_register_media_controller(dev
->stateful_enc
.m2m_dev
,
2142 &dev
->stateful_enc
.vfd
,
2143 MEDIA_ENT_F_PROC_VIDEO_ENCODER
);
2145 v4l2_err(&dev
->v4l2_dev
, "Failed to init mem2mem media controller for enc\n");
2149 ret
= v4l2_m2m_register_media_controller(dev
->stateful_dec
.m2m_dev
,
2150 &dev
->stateful_dec
.vfd
,
2151 MEDIA_ENT_F_PROC_VIDEO_DECODER
);
2153 v4l2_err(&dev
->v4l2_dev
, "Failed to init mem2mem media controller for dec\n");
2154 goto unreg_m2m_sf_enc_mc
;
2157 ret
= v4l2_m2m_register_media_controller(dev
->stateless_dec
.m2m_dev
,
2158 &dev
->stateless_dec
.vfd
,
2159 MEDIA_ENT_F_PROC_VIDEO_DECODER
);
2161 v4l2_err(&dev
->v4l2_dev
, "Failed to init mem2mem media controller for stateless dec\n");
2162 goto unreg_m2m_sf_dec_mc
;
2165 ret
= media_device_register(&dev
->mdev
);
2167 v4l2_err(&dev
->v4l2_dev
, "Failed to register mem2mem media device\n");
2168 goto unreg_m2m_sl_dec_mc
;
2173 #ifdef CONFIG_MEDIA_CONTROLLER
2174 unreg_m2m_sl_dec_mc
:
2175 v4l2_m2m_unregister_media_controller(dev
->stateless_dec
.m2m_dev
);
2176 unreg_m2m_sf_dec_mc
:
2177 v4l2_m2m_unregister_media_controller(dev
->stateful_dec
.m2m_dev
);
2178 unreg_m2m_sf_enc_mc
:
2179 v4l2_m2m_unregister_media_controller(dev
->stateful_enc
.m2m_dev
);
2181 video_unregister_device(&dev
->stateless_dec
.vfd
);
2182 v4l2_m2m_release(dev
->stateless_dec
.m2m_dev
);
2185 video_unregister_device(&dev
->stateful_dec
.vfd
);
2186 v4l2_m2m_release(dev
->stateful_dec
.m2m_dev
);
2188 video_unregister_device(&dev
->stateful_enc
.vfd
);
2189 v4l2_m2m_release(dev
->stateful_enc
.m2m_dev
);
2191 v4l2_device_unregister(&dev
->v4l2_dev
);
2198 static void vicodec_remove(struct platform_device
*pdev
)
2200 struct vicodec_dev
*dev
= platform_get_drvdata(pdev
);
2202 v4l2_info(&dev
->v4l2_dev
, "Removing " VICODEC_NAME
);
2204 #ifdef CONFIG_MEDIA_CONTROLLER
2205 media_device_unregister(&dev
->mdev
);
2206 v4l2_m2m_unregister_media_controller(dev
->stateful_enc
.m2m_dev
);
2207 v4l2_m2m_unregister_media_controller(dev
->stateful_dec
.m2m_dev
);
2208 v4l2_m2m_unregister_media_controller(dev
->stateless_dec
.m2m_dev
);
2211 video_unregister_device(&dev
->stateful_enc
.vfd
);
2212 video_unregister_device(&dev
->stateful_dec
.vfd
);
2213 video_unregister_device(&dev
->stateless_dec
.vfd
);
2214 v4l2_device_put(&dev
->v4l2_dev
);
2217 static struct platform_driver vicodec_pdrv
= {
2218 .probe
= vicodec_probe
,
2219 .remove
= vicodec_remove
,
2221 .name
= VICODEC_NAME
,
2225 static void __exit
vicodec_exit(void)
2227 platform_driver_unregister(&vicodec_pdrv
);
2228 platform_device_unregister(&vicodec_pdev
);
2231 static int __init
vicodec_init(void)
2235 ret
= platform_device_register(&vicodec_pdev
);
2239 ret
= platform_driver_register(&vicodec_pdrv
);
2241 platform_device_unregister(&vicodec_pdev
);
2246 module_init(vicodec_init
);
2247 module_exit(vicodec_exit
);