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 void vicodec_dev_release(struct device *dev)
71 static struct platform_device vicodec_pdev = {
73 .dev.release = vicodec_dev_release,
76 /* Per-queue, driver-specific private data */
77 struct vicodec_q_data {
78 unsigned int coded_width;
79 unsigned int coded_height;
80 unsigned int visible_width;
81 unsigned int visible_height;
82 unsigned int sizeimage;
83 unsigned int sequence;
84 const struct v4l2_fwht_pixfmt_info *info;
93 struct v4l2_device v4l2_dev;
94 struct video_device enc_vfd;
95 struct video_device dec_vfd;
96 #ifdef CONFIG_MEDIA_CONTROLLER
97 struct media_device mdev;
100 struct mutex enc_mutex;
101 struct mutex dec_mutex;
105 struct v4l2_m2m_dev *enc_dev;
106 struct v4l2_m2m_dev *dec_dev;
111 struct vicodec_dev *dev;
115 struct v4l2_ctrl_handler hdl;
117 struct vb2_v4l2_buffer *last_src_buf;
118 struct vb2_v4l2_buffer *last_dst_buf;
120 /* Source and destination queue data */
121 struct vicodec_q_data q_data[2];
122 struct v4l2_fwht_state state;
130 bool comp_has_next_frame;
131 bool first_source_change_sent;
135 static inline struct vicodec_ctx *file2ctx(struct file *file)
137 return container_of(file->private_data, struct vicodec_ctx, fh);
140 static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx,
141 enum v4l2_buf_type type)
144 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
145 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
146 return &ctx->q_data[V4L2_M2M_SRC];
147 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
148 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
149 return &ctx->q_data[V4L2_M2M_DST];
157 static int device_process(struct vicodec_ctx *ctx,
158 struct vb2_v4l2_buffer *src_vb,
159 struct vb2_v4l2_buffer *dst_vb)
161 struct vicodec_dev *dev = ctx->dev;
162 struct vicodec_q_data *q_dst;
163 struct v4l2_fwht_state *state = &ctx->state;
167 q_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
169 p_src = vb2_plane_vaddr(&src_vb->vb2_buf, 0);
171 p_src = state->compressed_frame;
172 p_dst = vb2_plane_vaddr(&dst_vb->vb2_buf, 0);
173 if (!p_src || !p_dst) {
174 v4l2_err(&dev->v4l2_dev,
175 "Acquiring kernel pointers to buffers failed\n");
180 struct vicodec_q_data *q_src;
182 q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
183 state->info = q_src->info;
184 ret = v4l2_fwht_encode(state, p_src, p_dst);
187 vb2_set_plane_payload(&dst_vb->vb2_buf, 0, ret);
189 unsigned int comp_frame_size = ntohl(ctx->state.header.size);
191 if (comp_frame_size > ctx->comp_max_size)
193 state->info = q_dst->info;
194 ret = v4l2_fwht_decode(state, p_src, p_dst);
197 vb2_set_plane_payload(&dst_vb->vb2_buf, 0, q_dst->sizeimage);
200 dst_vb->sequence = q_dst->sequence++;
201 dst_vb->flags &= ~V4L2_BUF_FLAG_LAST;
202 v4l2_m2m_buf_copy_metadata(src_vb, dst_vb, !ctx->is_enc);
210 static enum vb2_buffer_state get_next_header(struct vicodec_ctx *ctx,
213 static const u8 magic[] = {
214 0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
218 u8 *header = (u8 *)&ctx->state.header;
220 state = VB2_BUF_STATE_DONE;
222 if (!ctx->header_size) {
223 state = VB2_BUF_STATE_ERROR;
224 for (; p < *pp + sz; p++) {
227 p = memchr(p, magic[ctx->comp_magic_cnt],
230 ctx->comp_magic_cnt = 0;
234 copy = sizeof(magic) - ctx->comp_magic_cnt;
235 if (*pp + sz - p < copy)
238 memcpy(header + ctx->comp_magic_cnt, p, copy);
239 ctx->comp_magic_cnt += copy;
240 if (!memcmp(header, magic, ctx->comp_magic_cnt)) {
242 state = VB2_BUF_STATE_DONE;
245 ctx->comp_magic_cnt = 0;
247 if (ctx->comp_magic_cnt < sizeof(magic)) {
251 ctx->header_size = sizeof(magic);
254 if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
255 u32 copy = sizeof(struct fwht_cframe_hdr) - ctx->header_size;
257 if (*pp + sz - p < copy)
260 memcpy(header + ctx->header_size, p, copy);
262 ctx->header_size += copy;
268 /* device_run() - prepares and starts the device */
269 static void device_run(void *priv)
271 static const struct v4l2_event eos_event = {
272 .type = V4L2_EVENT_EOS
274 struct vicodec_ctx *ctx = priv;
275 struct vicodec_dev *dev = ctx->dev;
276 struct vb2_v4l2_buffer *src_buf, *dst_buf;
277 struct vicodec_q_data *q_src;
280 src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
281 dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
282 q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
284 state = VB2_BUF_STATE_DONE;
285 if (device_process(ctx, src_buf, dst_buf))
286 state = VB2_BUF_STATE_ERROR;
287 ctx->last_dst_buf = dst_buf;
289 spin_lock(ctx->lock);
290 if (!ctx->comp_has_next_frame && src_buf == ctx->last_src_buf) {
291 dst_buf->flags |= V4L2_BUF_FLAG_LAST;
292 v4l2_event_queue_fh(&ctx->fh, &eos_event);
295 src_buf->sequence = q_src->sequence++;
296 src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
297 v4l2_m2m_buf_done(src_buf, state);
298 } else if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == ctx->cur_buf_offset) {
299 src_buf->sequence = q_src->sequence++;
300 src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
301 v4l2_m2m_buf_done(src_buf, state);
302 ctx->cur_buf_offset = 0;
303 ctx->comp_has_next_frame = false;
305 v4l2_m2m_buf_done(dst_buf, state);
307 ctx->header_size = 0;
308 ctx->comp_magic_cnt = 0;
309 ctx->comp_has_frame = false;
310 spin_unlock(ctx->lock);
313 v4l2_m2m_job_finish(dev->enc_dev, ctx->fh.m2m_ctx);
315 v4l2_m2m_job_finish(dev->dec_dev, ctx->fh.m2m_ctx);
318 static void job_remove_src_buf(struct vicodec_ctx *ctx, u32 state)
320 struct vb2_v4l2_buffer *src_buf;
321 struct vicodec_q_data *q_src;
323 q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
324 spin_lock(ctx->lock);
325 src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
326 src_buf->sequence = q_src->sequence++;
327 v4l2_m2m_buf_done(src_buf, state);
328 ctx->cur_buf_offset = 0;
329 spin_unlock(ctx->lock);
332 static const struct v4l2_fwht_pixfmt_info *
333 info_from_header(const struct fwht_cframe_hdr *p_hdr)
335 unsigned int flags = ntohl(p_hdr->flags);
336 unsigned int width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
337 unsigned int height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
338 unsigned int components_num = 3;
339 unsigned int pixenc = 0;
340 unsigned int version = ntohl(p_hdr->version);
343 components_num = 1 + ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
344 FWHT_FL_COMPONENTS_NUM_OFFSET);
345 pixenc = (flags & FWHT_FL_PIXENC_MSK);
347 return v4l2_fwht_default_fmt(width_div, height_div,
348 components_num, pixenc, 0);
351 static bool is_header_valid(const struct fwht_cframe_hdr *p_hdr)
353 const struct v4l2_fwht_pixfmt_info *info;
354 unsigned int w = ntohl(p_hdr->width);
355 unsigned int h = ntohl(p_hdr->height);
356 unsigned int version = ntohl(p_hdr->version);
357 unsigned int flags = ntohl(p_hdr->flags);
359 if (!version || version > FWHT_VERSION)
362 if (w < MIN_WIDTH || w > MAX_WIDTH || h < MIN_HEIGHT || h > MAX_HEIGHT)
366 unsigned int components_num = 1 +
367 ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
368 FWHT_FL_COMPONENTS_NUM_OFFSET);
369 unsigned int pixenc = flags & FWHT_FL_PIXENC_MSK;
371 if (components_num == 0 || components_num > 4 || !pixenc)
375 info = info_from_header(p_hdr);
381 static void update_capture_data_from_header(struct vicodec_ctx *ctx)
383 struct vicodec_q_data *q_dst = get_q_data(ctx,
384 V4L2_BUF_TYPE_VIDEO_CAPTURE);
385 const struct fwht_cframe_hdr *p_hdr = &ctx->state.header;
386 const struct v4l2_fwht_pixfmt_info *info = info_from_header(p_hdr);
387 unsigned int flags = ntohl(p_hdr->flags);
388 unsigned int hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
389 unsigned int hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
392 q_dst->visible_width = ntohl(p_hdr->width);
393 q_dst->visible_height = ntohl(p_hdr->height);
394 q_dst->coded_width = vic_round_dim(q_dst->visible_width, hdr_width_div);
395 q_dst->coded_height = vic_round_dim(q_dst->visible_height,
398 q_dst->sizeimage = q_dst->coded_width * q_dst->coded_height *
399 q_dst->info->sizeimage_mult / q_dst->info->sizeimage_div;
400 ctx->state.colorspace = ntohl(p_hdr->colorspace);
402 ctx->state.xfer_func = ntohl(p_hdr->xfer_func);
403 ctx->state.ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
404 ctx->state.quantization = ntohl(p_hdr->quantization);
407 static void set_last_buffer(struct vb2_v4l2_buffer *dst_buf,
408 const struct vb2_v4l2_buffer *src_buf,
409 struct vicodec_ctx *ctx)
411 struct vicodec_q_data *q_dst = get_q_data(ctx,
412 V4L2_BUF_TYPE_VIDEO_CAPTURE);
414 vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0);
415 dst_buf->sequence = q_dst->sequence++;
417 v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, !ctx->is_enc);
418 dst_buf->flags |= V4L2_BUF_FLAG_LAST;
419 v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
422 static int job_ready(void *priv)
424 static const u8 magic[] = {
425 0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
427 struct vicodec_ctx *ctx = priv;
428 struct vb2_v4l2_buffer *src_buf;
433 struct vicodec_q_data *q_dst = get_q_data(ctx,
434 V4L2_BUF_TYPE_VIDEO_CAPTURE);
436 unsigned int hdr_width_div;
437 unsigned int hdr_height_div;
438 unsigned int max_to_copy;
439 unsigned int comp_frame_size;
441 if (ctx->source_changed)
443 if (ctx->is_enc || ctx->comp_has_frame)
447 ctx->comp_has_next_frame = false;
448 src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
451 p_src = vb2_plane_vaddr(&src_buf->vb2_buf, 0);
452 sz = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
453 p = p_src + ctx->cur_buf_offset;
455 state = VB2_BUF_STATE_DONE;
457 if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
458 state = get_next_header(ctx, &p, p_src + sz - p);
459 if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
460 job_remove_src_buf(ctx, state);
465 comp_frame_size = ntohl(ctx->state.header.size);
468 * The current scanned frame might be the first frame of a new
469 * resolution so its size might be larger than ctx->comp_max_size.
470 * In that case it is copied up to the current buffer capacity and
471 * the copy will continue after allocating new large enough buffer
474 max_to_copy = min(comp_frame_size, ctx->comp_max_size);
476 if (ctx->comp_size < max_to_copy) {
477 u32 copy = max_to_copy - ctx->comp_size;
479 if (copy > p_src + sz - p)
480 copy = p_src + sz - p;
482 memcpy(ctx->state.compressed_frame + ctx->comp_size,
485 ctx->comp_size += copy;
486 if (ctx->comp_size < max_to_copy) {
487 job_remove_src_buf(ctx, state);
491 ctx->cur_buf_offset = p - p_src;
492 if (ctx->comp_size == comp_frame_size)
493 ctx->comp_has_frame = true;
494 ctx->comp_has_next_frame = false;
495 if (ctx->comp_has_frame && sz - ctx->cur_buf_offset >=
496 sizeof(struct fwht_cframe_hdr)) {
497 struct fwht_cframe_hdr *p_hdr = (struct fwht_cframe_hdr *)p;
498 u32 frame_size = ntohl(p_hdr->size);
499 u32 remaining = sz - ctx->cur_buf_offset - sizeof(*p_hdr);
501 if (!memcmp(p, magic, sizeof(magic)))
502 ctx->comp_has_next_frame = remaining >= frame_size;
505 * if the header is invalid the device_run will just drop the frame
508 if (!is_header_valid(&ctx->state.header) && ctx->comp_has_frame)
510 flags = ntohl(ctx->state.header.flags);
511 hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
512 hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
514 if (ntohl(ctx->state.header.width) != q_dst->visible_width ||
515 ntohl(ctx->state.header.height) != q_dst->visible_height ||
517 hdr_width_div != q_dst->info->width_div ||
518 hdr_height_div != q_dst->info->height_div) {
519 static const struct v4l2_event rs_event = {
520 .type = V4L2_EVENT_SOURCE_CHANGE,
521 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
524 struct vb2_v4l2_buffer *dst_buf =
525 v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
527 update_capture_data_from_header(ctx);
528 ctx->first_source_change_sent = true;
529 v4l2_event_queue_fh(&ctx->fh, &rs_event);
530 set_last_buffer(dst_buf, src_buf, ctx);
531 ctx->source_changed = true;
541 static const struct v4l2_fwht_pixfmt_info *find_fmt(u32 fmt)
543 const struct v4l2_fwht_pixfmt_info *info =
544 v4l2_fwht_find_pixfmt(fmt);
547 info = v4l2_fwht_get_pixfmt(0);
551 static int vidioc_querycap(struct file *file, void *priv,
552 struct v4l2_capability *cap)
554 strncpy(cap->driver, VICODEC_NAME, sizeof(cap->driver) - 1);
555 strncpy(cap->card, VICODEC_NAME, sizeof(cap->card) - 1);
556 snprintf(cap->bus_info, sizeof(cap->bus_info),
557 "platform:%s", VICODEC_NAME);
561 static int enum_fmt(struct v4l2_fmtdesc *f, struct vicodec_ctx *ctx,
564 bool is_uncomp = (ctx->is_enc && is_out) || (!ctx->is_enc && !is_out);
566 if (V4L2_TYPE_IS_MULTIPLANAR(f->type) && !multiplanar)
568 if (!V4L2_TYPE_IS_MULTIPLANAR(f->type) && multiplanar)
572 const struct v4l2_fwht_pixfmt_info *info =
573 get_q_data(ctx, f->type)->info;
575 if (!info || ctx->is_enc)
576 info = v4l2_fwht_get_pixfmt(f->index);
578 info = v4l2_fwht_default_fmt(info->width_div,
580 info->components_num,
585 f->pixelformat = info->id;
589 f->pixelformat = V4L2_PIX_FMT_FWHT;
594 static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
595 struct v4l2_fmtdesc *f)
597 struct vicodec_ctx *ctx = file2ctx(file);
599 return enum_fmt(f, ctx, false);
602 static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
603 struct v4l2_fmtdesc *f)
605 struct vicodec_ctx *ctx = file2ctx(file);
607 return enum_fmt(f, ctx, true);
610 static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
612 struct vb2_queue *vq;
613 struct vicodec_q_data *q_data;
614 struct v4l2_pix_format_mplane *pix_mp;
615 struct v4l2_pix_format *pix;
616 const struct v4l2_fwht_pixfmt_info *info;
618 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
622 q_data = get_q_data(ctx, f->type);
626 info = v4l2_fwht_get_pixfmt(0);
629 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
630 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
634 pix->width = q_data->coded_width;
635 pix->height = q_data->coded_height;
636 pix->field = V4L2_FIELD_NONE;
637 pix->pixelformat = info->id;
638 pix->bytesperline = q_data->coded_width *
639 info->bytesperline_mult;
640 pix->sizeimage = q_data->sizeimage;
641 pix->colorspace = ctx->state.colorspace;
642 pix->xfer_func = ctx->state.xfer_func;
643 pix->ycbcr_enc = ctx->state.ycbcr_enc;
644 pix->quantization = ctx->state.quantization;
647 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
648 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
651 pix_mp = &f->fmt.pix_mp;
652 pix_mp->width = q_data->coded_width;
653 pix_mp->height = q_data->coded_height;
654 pix_mp->field = V4L2_FIELD_NONE;
655 pix_mp->pixelformat = info->id;
656 pix_mp->num_planes = 1;
657 pix_mp->plane_fmt[0].bytesperline =
658 q_data->coded_width * info->bytesperline_mult;
659 pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage;
660 pix_mp->colorspace = ctx->state.colorspace;
661 pix_mp->xfer_func = ctx->state.xfer_func;
662 pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
663 pix_mp->quantization = ctx->state.quantization;
664 memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
665 memset(pix_mp->plane_fmt[0].reserved, 0,
666 sizeof(pix_mp->plane_fmt[0].reserved));
674 static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
675 struct v4l2_format *f)
677 return vidioc_g_fmt(file2ctx(file), f);
680 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
681 struct v4l2_format *f)
683 return vidioc_g_fmt(file2ctx(file), f);
686 static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
688 struct v4l2_pix_format_mplane *pix_mp;
689 struct v4l2_pix_format *pix;
690 struct v4l2_plane_pix_format *plane;
691 const struct v4l2_fwht_pixfmt_info *info = &pixfmt_fwht;
694 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
695 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
697 if (pix->pixelformat != V4L2_PIX_FMT_FWHT)
698 info = find_fmt(pix->pixelformat);
700 pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH);
701 pix->width = vic_round_dim(pix->width, info->width_div);
703 pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT);
704 pix->height = vic_round_dim(pix->height, info->height_div);
706 pix->field = V4L2_FIELD_NONE;
708 pix->width * info->bytesperline_mult;
709 pix->sizeimage = pix->width * pix->height *
710 info->sizeimage_mult / info->sizeimage_div;
711 if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
712 pix->sizeimage += sizeof(struct fwht_cframe_hdr);
714 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
715 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
716 pix_mp = &f->fmt.pix_mp;
717 plane = pix_mp->plane_fmt;
718 if (pix_mp->pixelformat != V4L2_PIX_FMT_FWHT)
719 info = find_fmt(pix_mp->pixelformat);
720 pix_mp->num_planes = 1;
722 pix_mp->width = clamp(pix_mp->width, MIN_WIDTH, MAX_WIDTH);
723 pix_mp->width = vic_round_dim(pix_mp->width, info->width_div);
725 pix_mp->height = clamp(pix_mp->height, MIN_HEIGHT, MAX_HEIGHT);
726 pix_mp->height = vic_round_dim(pix_mp->height,
729 pix_mp->field = V4L2_FIELD_NONE;
730 plane->bytesperline =
731 pix_mp->width * info->bytesperline_mult;
732 plane->sizeimage = pix_mp->width * pix_mp->height *
733 info->sizeimage_mult / info->sizeimage_div;
734 if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
735 plane->sizeimage += sizeof(struct fwht_cframe_hdr);
736 memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
737 memset(plane->reserved, 0, sizeof(plane->reserved));
746 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
747 struct v4l2_format *f)
749 struct vicodec_ctx *ctx = file2ctx(file);
750 struct v4l2_pix_format_mplane *pix_mp;
751 struct v4l2_pix_format *pix;
754 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
758 pix->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
759 find_fmt(f->fmt.pix.pixelformat)->id;
760 pix->colorspace = ctx->state.colorspace;
761 pix->xfer_func = ctx->state.xfer_func;
762 pix->ycbcr_enc = ctx->state.ycbcr_enc;
763 pix->quantization = ctx->state.quantization;
765 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
768 pix_mp = &f->fmt.pix_mp;
769 pix_mp->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
770 find_fmt(pix_mp->pixelformat)->id;
771 pix_mp->colorspace = ctx->state.colorspace;
772 pix_mp->xfer_func = ctx->state.xfer_func;
773 pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
774 pix_mp->quantization = ctx->state.quantization;
780 return vidioc_try_fmt(ctx, f);
783 static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
784 struct v4l2_format *f)
786 struct vicodec_ctx *ctx = file2ctx(file);
787 struct v4l2_pix_format_mplane *pix_mp;
788 struct v4l2_pix_format *pix;
791 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
795 pix->pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT :
796 find_fmt(pix->pixelformat)->id;
797 if (!pix->colorspace)
798 pix->colorspace = V4L2_COLORSPACE_REC709;
800 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
803 pix_mp = &f->fmt.pix_mp;
804 pix_mp->pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT :
805 find_fmt(pix_mp->pixelformat)->id;
806 if (!pix_mp->colorspace)
807 pix_mp->colorspace = V4L2_COLORSPACE_REC709;
813 return vidioc_try_fmt(ctx, f);
816 static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
818 struct vicodec_q_data *q_data;
819 struct vb2_queue *vq;
820 bool fmt_changed = true;
821 struct v4l2_pix_format_mplane *pix_mp;
822 struct v4l2_pix_format *pix;
824 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
828 q_data = get_q_data(ctx, f->type);
833 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
834 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
836 if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
839 q_data->info->id != pix->pixelformat ||
840 q_data->coded_width != pix->width ||
841 q_data->coded_height != pix->height;
843 if (vb2_is_busy(vq) && fmt_changed)
846 if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
847 q_data->info = &pixfmt_fwht;
849 q_data->info = find_fmt(pix->pixelformat);
850 q_data->coded_width = pix->width;
851 q_data->coded_height = pix->height;
852 q_data->sizeimage = pix->sizeimage;
854 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
855 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
856 pix_mp = &f->fmt.pix_mp;
857 if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
860 q_data->info->id != pix_mp->pixelformat ||
861 q_data->coded_width != pix_mp->width ||
862 q_data->coded_height != pix_mp->height;
864 if (vb2_is_busy(vq) && fmt_changed)
867 if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
868 q_data->info = &pixfmt_fwht;
870 q_data->info = find_fmt(pix_mp->pixelformat);
871 q_data->coded_width = pix_mp->width;
872 q_data->coded_height = pix_mp->height;
873 q_data->sizeimage = pix_mp->plane_fmt[0].sizeimage;
878 if (q_data->visible_width > q_data->coded_width)
879 q_data->visible_width = q_data->coded_width;
880 if (q_data->visible_height > q_data->coded_height)
881 q_data->visible_height = q_data->coded_height;
885 "Setting format for type %d, coded wxh: %dx%d, visible wxh: %dx%d, fourcc: %08x\n",
886 f->type, q_data->coded_width, q_data->coded_height,
887 q_data->visible_width, q_data->visible_height,
893 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
894 struct v4l2_format *f)
898 ret = vidioc_try_fmt_vid_cap(file, priv, f);
902 return vidioc_s_fmt(file2ctx(file), f);
905 static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
906 struct v4l2_format *f)
908 struct vicodec_ctx *ctx = file2ctx(file);
909 struct v4l2_pix_format_mplane *pix_mp;
910 struct v4l2_pix_format *pix;
913 ret = vidioc_try_fmt_vid_out(file, priv, f);
917 ret = vidioc_s_fmt(file2ctx(file), f);
920 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
921 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
923 ctx->state.colorspace = pix->colorspace;
924 ctx->state.xfer_func = pix->xfer_func;
925 ctx->state.ycbcr_enc = pix->ycbcr_enc;
926 ctx->state.quantization = pix->quantization;
928 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
929 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
930 pix_mp = &f->fmt.pix_mp;
931 ctx->state.colorspace = pix_mp->colorspace;
932 ctx->state.xfer_func = pix_mp->xfer_func;
933 ctx->state.ycbcr_enc = pix_mp->ycbcr_enc;
934 ctx->state.quantization = pix_mp->quantization;
943 static int vidioc_g_selection(struct file *file, void *priv,
944 struct v4l2_selection *s)
946 struct vicodec_ctx *ctx = file2ctx(file);
947 struct vicodec_q_data *q_data;
948 enum v4l2_buf_type valid_cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
949 enum v4l2_buf_type valid_out_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
952 valid_cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
953 valid_out_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
956 if (s->type != valid_cap_type && s->type != valid_out_type)
959 q_data = get_q_data(ctx, s->type);
963 * encoder supports only cropping on the OUTPUT buffer
964 * decoder supports only composing on the CAPTURE buffer
966 if ((ctx->is_enc && s->type == valid_out_type) ||
967 (!ctx->is_enc && s->type == valid_cap_type)) {
969 case V4L2_SEL_TGT_COMPOSE:
970 case V4L2_SEL_TGT_CROP:
973 s->r.width = q_data->visible_width;
974 s->r.height = q_data->visible_height;
976 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
977 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
978 case V4L2_SEL_TGT_CROP_DEFAULT:
979 case V4L2_SEL_TGT_CROP_BOUNDS:
982 s->r.width = q_data->coded_width;
983 s->r.height = q_data->coded_height;
990 static int vidioc_s_selection(struct file *file, void *priv,
991 struct v4l2_selection *s)
993 struct vicodec_ctx *ctx = file2ctx(file);
994 struct vicodec_q_data *q_data;
995 enum v4l2_buf_type out_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
998 out_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1000 if (s->type != out_type)
1003 q_data = get_q_data(ctx, s->type);
1007 if (!ctx->is_enc || s->target != V4L2_SEL_TGT_CROP)
1012 q_data->visible_width = clamp(s->r.width, MIN_WIDTH,
1013 q_data->coded_width);
1014 s->r.width = q_data->visible_width;
1015 q_data->visible_height = clamp(s->r.height, MIN_HEIGHT,
1016 q_data->coded_height);
1017 s->r.height = q_data->visible_height;
1021 static void vicodec_mark_last_buf(struct vicodec_ctx *ctx)
1023 static const struct v4l2_event eos_event = {
1024 .type = V4L2_EVENT_EOS
1027 spin_lock(ctx->lock);
1028 ctx->last_src_buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx);
1029 if (!ctx->last_src_buf && ctx->last_dst_buf) {
1030 ctx->last_dst_buf->flags |= V4L2_BUF_FLAG_LAST;
1031 v4l2_event_queue_fh(&ctx->fh, &eos_event);
1033 spin_unlock(ctx->lock);
1036 static int vicodec_try_encoder_cmd(struct file *file, void *fh,
1037 struct v4l2_encoder_cmd *ec)
1039 if (ec->cmd != V4L2_ENC_CMD_STOP)
1042 if (ec->flags & V4L2_ENC_CMD_STOP_AT_GOP_END)
1048 static int vicodec_encoder_cmd(struct file *file, void *fh,
1049 struct v4l2_encoder_cmd *ec)
1051 struct vicodec_ctx *ctx = file2ctx(file);
1054 ret = vicodec_try_encoder_cmd(file, fh, ec);
1058 vicodec_mark_last_buf(ctx);
1062 static int vicodec_try_decoder_cmd(struct file *file, void *fh,
1063 struct v4l2_decoder_cmd *dc)
1065 if (dc->cmd != V4L2_DEC_CMD_STOP)
1068 if (dc->flags & V4L2_DEC_CMD_STOP_TO_BLACK)
1071 if (!(dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) && (dc->stop.pts != 0))
1077 static int vicodec_decoder_cmd(struct file *file, void *fh,
1078 struct v4l2_decoder_cmd *dc)
1080 struct vicodec_ctx *ctx = file2ctx(file);
1083 ret = vicodec_try_decoder_cmd(file, fh, dc);
1087 vicodec_mark_last_buf(ctx);
1091 static int vicodec_enum_framesizes(struct file *file, void *fh,
1092 struct v4l2_frmsizeenum *fsize)
1094 switch (fsize->pixel_format) {
1095 case V4L2_PIX_FMT_FWHT:
1098 if (find_fmt(fsize->pixel_format)->id == fsize->pixel_format)
1106 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
1108 fsize->stepwise.min_width = MIN_WIDTH;
1109 fsize->stepwise.max_width = MAX_WIDTH;
1110 fsize->stepwise.step_width = 8;
1111 fsize->stepwise.min_height = MIN_HEIGHT;
1112 fsize->stepwise.max_height = MAX_HEIGHT;
1113 fsize->stepwise.step_height = 8;
1118 static int vicodec_subscribe_event(struct v4l2_fh *fh,
1119 const struct v4l2_event_subscription *sub)
1121 struct vicodec_ctx *ctx = container_of(fh, struct vicodec_ctx, fh);
1123 switch (sub->type) {
1124 case V4L2_EVENT_SOURCE_CHANGE:
1128 case V4L2_EVENT_EOS:
1129 return v4l2_event_subscribe(fh, sub, 0, NULL);
1131 return v4l2_ctrl_subscribe_event(fh, sub);
1135 static const struct v4l2_ioctl_ops vicodec_ioctl_ops = {
1136 .vidioc_querycap = vidioc_querycap,
1138 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1139 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1140 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1141 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1143 .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap,
1144 .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap,
1145 .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap,
1146 .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap,
1148 .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
1149 .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
1150 .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
1151 .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
1153 .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out,
1154 .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out,
1155 .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out,
1156 .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out,
1158 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
1159 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
1160 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
1161 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
1162 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
1163 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
1164 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
1166 .vidioc_streamon = v4l2_m2m_ioctl_streamon,
1167 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
1169 .vidioc_g_selection = vidioc_g_selection,
1170 .vidioc_s_selection = vidioc_s_selection,
1172 .vidioc_try_encoder_cmd = vicodec_try_encoder_cmd,
1173 .vidioc_encoder_cmd = vicodec_encoder_cmd,
1174 .vidioc_try_decoder_cmd = vicodec_try_decoder_cmd,
1175 .vidioc_decoder_cmd = vicodec_decoder_cmd,
1176 .vidioc_enum_framesizes = vicodec_enum_framesizes,
1178 .vidioc_subscribe_event = vicodec_subscribe_event,
1179 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1187 static int vicodec_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
1188 unsigned int *nplanes, unsigned int sizes[],
1189 struct device *alloc_devs[])
1191 struct vicodec_ctx *ctx = vb2_get_drv_priv(vq);
1192 struct vicodec_q_data *q_data = get_q_data(ctx, vq->type);
1193 unsigned int size = q_data->sizeimage;
1196 return sizes[0] < size ? -EINVAL : 0;
1203 static int vicodec_buf_prepare(struct vb2_buffer *vb)
1205 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1206 struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1207 struct vicodec_q_data *q_data;
1209 dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
1211 q_data = get_q_data(ctx, vb->vb2_queue->type);
1212 if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
1213 if (vbuf->field == V4L2_FIELD_ANY)
1214 vbuf->field = V4L2_FIELD_NONE;
1215 if (vbuf->field != V4L2_FIELD_NONE) {
1216 dprintk(ctx->dev, "%s field isn't supported\n",
1222 if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
1224 "%s data will not fit into plane (%lu < %lu)\n",
1225 __func__, vb2_plane_size(vb, 0),
1226 (long)q_data->sizeimage);
1233 static void vicodec_buf_queue(struct vb2_buffer *vb)
1235 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1236 struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1237 unsigned int sz = vb2_get_plane_payload(&vbuf->vb2_buf, 0);
1238 u8 *p_src = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
1240 struct vb2_queue *vq_out = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
1241 V4L2_BUF_TYPE_VIDEO_OUTPUT);
1242 struct vb2_queue *vq_cap = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
1243 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1244 bool header_valid = false;
1245 static const struct v4l2_event rs_event = {
1246 .type = V4L2_EVENT_SOURCE_CHANGE,
1247 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
1250 /* buf_queue handles only the first source change event */
1251 if (ctx->first_source_change_sent) {
1252 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1257 * if both queues are streaming, the source change event is
1258 * handled in job_ready
1260 if (vb2_is_streaming(vq_cap) && vb2_is_streaming(vq_out)) {
1261 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1266 * source change event is relevant only for the decoder
1267 * in the compressed stream
1269 if (ctx->is_enc || !V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
1270 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1275 enum vb2_buffer_state state =
1276 get_next_header(ctx, &p, p_src + sz - p);
1278 if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
1279 v4l2_m2m_buf_done(vbuf, state);
1282 header_valid = is_header_valid(&ctx->state.header);
1284 * p points right after the end of the header in the
1285 * buffer. If the header is invalid we set p to point
1286 * to the next byte after the start of the header
1288 if (!header_valid) {
1289 p = p - sizeof(struct fwht_cframe_hdr) + 1;
1292 ctx->header_size = 0;
1293 ctx->comp_magic_cnt = 0;
1296 } while (!header_valid);
1298 ctx->cur_buf_offset = p - p_src;
1299 update_capture_data_from_header(ctx);
1300 ctx->first_source_change_sent = true;
1301 v4l2_event_queue_fh(&ctx->fh, &rs_event);
1302 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1305 static void vicodec_return_bufs(struct vb2_queue *q, u32 state)
1307 struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
1308 struct vb2_v4l2_buffer *vbuf;
1311 if (V4L2_TYPE_IS_OUTPUT(q->type))
1312 vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
1314 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
1317 spin_lock(ctx->lock);
1318 v4l2_m2m_buf_done(vbuf, state);
1319 spin_unlock(ctx->lock);
1323 static int vicodec_start_streaming(struct vb2_queue *q,
1326 struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
1327 struct vicodec_q_data *q_data = get_q_data(ctx, q->type);
1328 struct v4l2_fwht_state *state = &ctx->state;
1329 const struct v4l2_fwht_pixfmt_info *info = q_data->info;
1330 unsigned int size = q_data->coded_width * q_data->coded_height;
1331 unsigned int chroma_div;
1332 unsigned int total_planes_size;
1338 chroma_div = info->width_div * info->height_div;
1339 q_data->sequence = 0;
1341 ctx->last_src_buf = NULL;
1342 ctx->last_dst_buf = NULL;
1345 if ((V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) ||
1346 (!V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc))
1349 if (info->id == V4L2_PIX_FMT_FWHT) {
1350 vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
1353 if (info->components_num == 4)
1354 total_planes_size = 2 * size + 2 * (size / chroma_div);
1355 else if (info->components_num == 3)
1356 total_planes_size = size + 2 * (size / chroma_div);
1358 total_planes_size = size;
1360 state->visible_width = q_data->visible_width;
1361 state->visible_height = q_data->visible_height;
1362 state->coded_width = q_data->coded_width;
1363 state->coded_height = q_data->coded_height;
1364 state->stride = q_data->coded_width *
1365 info->bytesperline_mult;
1367 state->ref_frame.luma = kvmalloc(total_planes_size, GFP_KERNEL);
1368 ctx->comp_max_size = total_planes_size;
1369 new_comp_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL);
1371 if (!state->ref_frame.luma || !new_comp_frame) {
1372 kvfree(state->ref_frame.luma);
1373 kvfree(new_comp_frame);
1374 vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
1378 * if state->compressed_frame was already allocated then
1379 * it contain data of the first frame of the new resolution
1381 if (state->compressed_frame) {
1382 if (ctx->comp_size > ctx->comp_max_size)
1383 ctx->comp_size = ctx->comp_max_size;
1385 memcpy(new_comp_frame,
1386 state->compressed_frame, ctx->comp_size);
1389 kvfree(state->compressed_frame);
1390 state->compressed_frame = new_comp_frame;
1392 if (info->components_num >= 3) {
1393 state->ref_frame.cb = state->ref_frame.luma + size;
1394 state->ref_frame.cr = state->ref_frame.cb + size / chroma_div;
1396 state->ref_frame.cb = NULL;
1397 state->ref_frame.cr = NULL;
1400 if (info->components_num == 4)
1401 state->ref_frame.alpha =
1402 state->ref_frame.cr + size / chroma_div;
1404 state->ref_frame.alpha = NULL;
1408 static void vicodec_stop_streaming(struct vb2_queue *q)
1410 struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
1412 vicodec_return_bufs(q, VB2_BUF_STATE_ERROR);
1414 if ((!V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) ||
1415 (V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc)) {
1416 kvfree(ctx->state.ref_frame.luma);
1417 ctx->comp_max_size = 0;
1418 ctx->source_changed = false;
1420 if (V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) {
1421 ctx->cur_buf_offset = 0;
1423 ctx->header_size = 0;
1424 ctx->comp_magic_cnt = 0;
1425 ctx->comp_has_frame = 0;
1426 ctx->comp_has_next_frame = 0;
1430 static const struct vb2_ops vicodec_qops = {
1431 .queue_setup = vicodec_queue_setup,
1432 .buf_prepare = vicodec_buf_prepare,
1433 .buf_queue = vicodec_buf_queue,
1434 .start_streaming = vicodec_start_streaming,
1435 .stop_streaming = vicodec_stop_streaming,
1436 .wait_prepare = vb2_ops_wait_prepare,
1437 .wait_finish = vb2_ops_wait_finish,
1440 static int queue_init(void *priv, struct vb2_queue *src_vq,
1441 struct vb2_queue *dst_vq)
1443 struct vicodec_ctx *ctx = priv;
1446 src_vq->type = (multiplanar ?
1447 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
1448 V4L2_BUF_TYPE_VIDEO_OUTPUT);
1449 src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1450 src_vq->drv_priv = ctx;
1451 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1452 src_vq->ops = &vicodec_qops;
1453 src_vq->mem_ops = &vb2_vmalloc_memops;
1454 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1455 src_vq->lock = ctx->is_enc ? &ctx->dev->enc_mutex :
1456 &ctx->dev->dec_mutex;
1458 ret = vb2_queue_init(src_vq);
1462 dst_vq->type = (multiplanar ?
1463 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
1464 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1465 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1466 dst_vq->drv_priv = ctx;
1467 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1468 dst_vq->ops = &vicodec_qops;
1469 dst_vq->mem_ops = &vb2_vmalloc_memops;
1470 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1471 dst_vq->lock = src_vq->lock;
1473 return vb2_queue_init(dst_vq);
1476 #define VICODEC_CID_CUSTOM_BASE (V4L2_CID_MPEG_BASE | 0xf000)
1477 #define VICODEC_CID_I_FRAME_QP (VICODEC_CID_CUSTOM_BASE + 0)
1478 #define VICODEC_CID_P_FRAME_QP (VICODEC_CID_CUSTOM_BASE + 1)
1480 static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl)
1482 struct vicodec_ctx *ctx = container_of(ctrl->handler,
1483 struct vicodec_ctx, hdl);
1486 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1487 ctx->state.gop_size = ctrl->val;
1489 case VICODEC_CID_I_FRAME_QP:
1490 ctx->state.i_frame_qp = ctrl->val;
1492 case VICODEC_CID_P_FRAME_QP:
1493 ctx->state.p_frame_qp = ctrl->val;
1499 static const struct v4l2_ctrl_ops vicodec_ctrl_ops = {
1500 .s_ctrl = vicodec_s_ctrl,
1503 static const struct v4l2_ctrl_config vicodec_ctrl_i_frame = {
1504 .ops = &vicodec_ctrl_ops,
1505 .id = VICODEC_CID_I_FRAME_QP,
1506 .name = "FWHT I-Frame QP Value",
1507 .type = V4L2_CTRL_TYPE_INTEGER,
1514 static const struct v4l2_ctrl_config vicodec_ctrl_p_frame = {
1515 .ops = &vicodec_ctrl_ops,
1516 .id = VICODEC_CID_P_FRAME_QP,
1517 .name = "FWHT P-Frame QP Value",
1518 .type = V4L2_CTRL_TYPE_INTEGER,
1528 static int vicodec_open(struct file *file)
1530 struct video_device *vfd = video_devdata(file);
1531 struct vicodec_dev *dev = video_drvdata(file);
1532 struct vicodec_ctx *ctx = NULL;
1533 struct v4l2_ctrl_handler *hdl;
1537 if (mutex_lock_interruptible(vfd->lock))
1538 return -ERESTARTSYS;
1539 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1545 if (vfd == &dev->enc_vfd)
1548 v4l2_fh_init(&ctx->fh, video_devdata(file));
1549 file->private_data = &ctx->fh;
1552 v4l2_ctrl_handler_init(hdl, 4);
1553 v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE,
1555 v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_i_frame, NULL);
1556 v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_p_frame, NULL);
1559 v4l2_ctrl_handler_free(hdl);
1563 ctx->fh.ctrl_handler = hdl;
1564 v4l2_ctrl_handler_setup(hdl);
1566 ctx->q_data[V4L2_M2M_SRC].info =
1567 ctx->is_enc ? v4l2_fwht_get_pixfmt(0) : &pixfmt_fwht;
1568 ctx->q_data[V4L2_M2M_SRC].coded_width = 1280;
1569 ctx->q_data[V4L2_M2M_SRC].coded_height = 720;
1570 ctx->q_data[V4L2_M2M_SRC].visible_width = 1280;
1571 ctx->q_data[V4L2_M2M_SRC].visible_height = 720;
1572 size = 1280 * 720 * ctx->q_data[V4L2_M2M_SRC].info->sizeimage_mult /
1573 ctx->q_data[V4L2_M2M_SRC].info->sizeimage_div;
1575 ctx->q_data[V4L2_M2M_SRC].sizeimage = size;
1577 ctx->q_data[V4L2_M2M_SRC].sizeimage =
1578 size + sizeof(struct fwht_cframe_hdr);
1580 ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
1581 ctx->q_data[V4L2_M2M_DST].info = &pixfmt_fwht;
1582 ctx->q_data[V4L2_M2M_DST].sizeimage = 1280 * 720 *
1583 ctx->q_data[V4L2_M2M_DST].info->sizeimage_mult /
1584 ctx->q_data[V4L2_M2M_DST].info->sizeimage_div +
1585 sizeof(struct fwht_cframe_hdr);
1587 ctx->q_data[V4L2_M2M_DST].info = NULL;
1590 ctx->state.colorspace = V4L2_COLORSPACE_REC709;
1593 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->enc_dev, ctx,
1595 ctx->lock = &dev->enc_lock;
1597 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->dec_dev, ctx,
1599 ctx->lock = &dev->dec_lock;
1602 if (IS_ERR(ctx->fh.m2m_ctx)) {
1603 rc = PTR_ERR(ctx->fh.m2m_ctx);
1605 v4l2_ctrl_handler_free(hdl);
1606 v4l2_fh_exit(&ctx->fh);
1611 v4l2_fh_add(&ctx->fh);
1614 mutex_unlock(vfd->lock);
1618 static int vicodec_release(struct file *file)
1620 struct video_device *vfd = video_devdata(file);
1621 struct vicodec_ctx *ctx = file2ctx(file);
1623 v4l2_fh_del(&ctx->fh);
1624 v4l2_fh_exit(&ctx->fh);
1625 v4l2_ctrl_handler_free(&ctx->hdl);
1626 mutex_lock(vfd->lock);
1627 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
1628 mutex_unlock(vfd->lock);
1634 static const struct v4l2_file_operations vicodec_fops = {
1635 .owner = THIS_MODULE,
1636 .open = vicodec_open,
1637 .release = vicodec_release,
1638 .poll = v4l2_m2m_fop_poll,
1639 .unlocked_ioctl = video_ioctl2,
1640 .mmap = v4l2_m2m_fop_mmap,
1643 static const struct video_device vicodec_videodev = {
1644 .name = VICODEC_NAME,
1645 .vfl_dir = VFL_DIR_M2M,
1646 .fops = &vicodec_fops,
1647 .ioctl_ops = &vicodec_ioctl_ops,
1649 .release = video_device_release_empty,
1652 static const struct v4l2_m2m_ops m2m_ops = {
1653 .device_run = device_run,
1654 .job_ready = job_ready,
1657 static int vicodec_probe(struct platform_device *pdev)
1659 struct vicodec_dev *dev;
1660 struct video_device *vfd;
1663 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
1667 spin_lock_init(&dev->enc_lock);
1668 spin_lock_init(&dev->dec_lock);
1670 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
1674 #ifdef CONFIG_MEDIA_CONTROLLER
1675 dev->mdev.dev = &pdev->dev;
1676 strscpy(dev->mdev.model, "vicodec", sizeof(dev->mdev.model));
1677 strscpy(dev->mdev.bus_info, "platform:vicodec",
1678 sizeof(dev->mdev.bus_info));
1679 media_device_init(&dev->mdev);
1680 dev->v4l2_dev.mdev = &dev->mdev;
1683 mutex_init(&dev->enc_mutex);
1684 mutex_init(&dev->dec_mutex);
1686 platform_set_drvdata(pdev, dev);
1688 dev->enc_dev = v4l2_m2m_init(&m2m_ops);
1689 if (IS_ERR(dev->enc_dev)) {
1690 v4l2_err(&dev->v4l2_dev, "Failed to init vicodec device\n");
1691 ret = PTR_ERR(dev->enc_dev);
1695 dev->dec_dev = v4l2_m2m_init(&m2m_ops);
1696 if (IS_ERR(dev->dec_dev)) {
1697 v4l2_err(&dev->v4l2_dev, "Failed to init vicodec device\n");
1698 ret = PTR_ERR(dev->dec_dev);
1702 dev->enc_vfd = vicodec_videodev;
1703 vfd = &dev->enc_vfd;
1704 vfd->lock = &dev->enc_mutex;
1705 vfd->v4l2_dev = &dev->v4l2_dev;
1706 strscpy(vfd->name, "vicodec-enc", sizeof(vfd->name));
1707 vfd->device_caps = V4L2_CAP_STREAMING |
1708 (multiplanar ? V4L2_CAP_VIDEO_M2M_MPLANE : V4L2_CAP_VIDEO_M2M);
1709 v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
1710 v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
1711 video_set_drvdata(vfd, dev);
1713 ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
1715 v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
1718 v4l2_info(&dev->v4l2_dev,
1719 "Device registered as /dev/video%d\n", vfd->num);
1721 dev->dec_vfd = vicodec_videodev;
1722 vfd = &dev->dec_vfd;
1723 vfd->lock = &dev->dec_mutex;
1724 vfd->v4l2_dev = &dev->v4l2_dev;
1725 vfd->device_caps = V4L2_CAP_STREAMING |
1726 (multiplanar ? V4L2_CAP_VIDEO_M2M_MPLANE : V4L2_CAP_VIDEO_M2M);
1727 strscpy(vfd->name, "vicodec-dec", sizeof(vfd->name));
1728 v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
1729 v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
1730 video_set_drvdata(vfd, dev);
1732 ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
1734 v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
1737 v4l2_info(&dev->v4l2_dev,
1738 "Device registered as /dev/video%d\n", vfd->num);
1740 #ifdef CONFIG_MEDIA_CONTROLLER
1741 ret = v4l2_m2m_register_media_controller(dev->enc_dev,
1742 &dev->enc_vfd, MEDIA_ENT_F_PROC_VIDEO_ENCODER);
1744 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n");
1748 ret = v4l2_m2m_register_media_controller(dev->dec_dev,
1749 &dev->dec_vfd, MEDIA_ENT_F_PROC_VIDEO_DECODER);
1751 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n");
1752 goto unreg_m2m_enc_mc;
1755 ret = media_device_register(&dev->mdev);
1757 v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n");
1758 goto unreg_m2m_dec_mc;
1763 #ifdef CONFIG_MEDIA_CONTROLLER
1765 v4l2_m2m_unregister_media_controller(dev->dec_dev);
1767 v4l2_m2m_unregister_media_controller(dev->enc_dev);
1769 video_unregister_device(&dev->dec_vfd);
1772 video_unregister_device(&dev->enc_vfd);
1774 v4l2_m2m_release(dev->dec_dev);
1776 v4l2_m2m_release(dev->enc_dev);
1778 v4l2_device_unregister(&dev->v4l2_dev);
1783 static int vicodec_remove(struct platform_device *pdev)
1785 struct vicodec_dev *dev = platform_get_drvdata(pdev);
1787 v4l2_info(&dev->v4l2_dev, "Removing " VICODEC_NAME);
1789 #ifdef CONFIG_MEDIA_CONTROLLER
1790 media_device_unregister(&dev->mdev);
1791 v4l2_m2m_unregister_media_controller(dev->enc_dev);
1792 v4l2_m2m_unregister_media_controller(dev->dec_dev);
1793 media_device_cleanup(&dev->mdev);
1796 v4l2_m2m_release(dev->enc_dev);
1797 v4l2_m2m_release(dev->dec_dev);
1798 video_unregister_device(&dev->enc_vfd);
1799 video_unregister_device(&dev->dec_vfd);
1800 v4l2_device_unregister(&dev->v4l2_dev);
1805 static struct platform_driver vicodec_pdrv = {
1806 .probe = vicodec_probe,
1807 .remove = vicodec_remove,
1809 .name = VICODEC_NAME,
1813 static void __exit vicodec_exit(void)
1815 platform_driver_unregister(&vicodec_pdrv);
1816 platform_device_unregister(&vicodec_pdev);
1819 static int __init vicodec_init(void)
1823 ret = platform_device_register(&vicodec_pdev);
1827 ret = platform_driver_register(&vicodec_pdrv);
1829 platform_device_unregister(&vicodec_pdev);
1834 module_init(vicodec_init);
1835 module_exit(vicodec_exit);