1 // SPDX-License-Identifier: GPL-2.0-only
3 * A virtual codec example device.
5 * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
7 * This is a virtual codec device driver for testing the codec framework.
8 * It simulates a device that uses memory buffers for both source and
9 * destination and encodes or decodes the data.
12 #include <linux/module.h>
13 #include <linux/delay.h>
15 #include <linux/sched.h>
16 #include <linux/slab.h>
18 #include <linux/platform_device.h>
19 #include <media/v4l2-mem2mem.h>
20 #include <media/v4l2-device.h>
21 #include <media/v4l2-ioctl.h>
22 #include <media/v4l2-ctrls.h>
23 #include <media/v4l2-event.h>
24 #include <media/videobuf2-vmalloc.h>
26 #include "codec-v4l2-fwht.h"
28 MODULE_DESCRIPTION("Virtual codec device");
29 MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
30 MODULE_LICENSE("GPL v2");
32 static bool multiplanar;
33 module_param(multiplanar, bool, 0444);
34 MODULE_PARM_DESC(multiplanar,
35 " use multi-planar API instead of single-planar API");
37 static unsigned int debug;
38 module_param(debug, uint, 0644);
39 MODULE_PARM_DESC(debug, " activates debug info");
41 #define VICODEC_NAME "vicodec"
42 #define MAX_WIDTH 4096U
43 #define MIN_WIDTH 640U
44 #define MAX_HEIGHT 2160U
45 #define MIN_HEIGHT 360U
47 #define dprintk(dev, fmt, arg...) \
48 v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
53 unsigned int bytesperline_mult;
54 unsigned int sizeimage_mult;
55 unsigned int sizeimage_div;
56 unsigned int luma_step;
57 unsigned int chroma_step;
58 /* Chroma plane subsampling */
59 unsigned int width_div;
60 unsigned int height_div;
63 static const struct v4l2_fwht_pixfmt_info pixfmt_fwht = {
64 V4L2_PIX_FMT_FWHT, 0, 3, 1, 1, 1, 1, 1, 0, 1
67 static const struct v4l2_fwht_pixfmt_info pixfmt_stateless_fwht = {
68 V4L2_PIX_FMT_FWHT_STATELESS, 0, 3, 1, 1, 1, 1, 1, 0, 1
71 static void vicodec_dev_release(struct device *dev)
75 static struct platform_device vicodec_pdev = {
77 .dev.release = vicodec_dev_release,
80 /* Per-queue, driver-specific private data */
81 struct vicodec_q_data {
82 unsigned int coded_width;
83 unsigned int coded_height;
84 unsigned int visible_width;
85 unsigned int visible_height;
86 unsigned int sizeimage;
87 unsigned int sequence;
88 const struct v4l2_fwht_pixfmt_info *info;
96 struct vicodec_dev_instance {
97 struct video_device vfd;
100 struct v4l2_m2m_dev *m2m_dev;
104 struct v4l2_device v4l2_dev;
105 struct vicodec_dev_instance stateful_enc;
106 struct vicodec_dev_instance stateful_dec;
107 struct vicodec_dev_instance stateless_dec;
108 #ifdef CONFIG_MEDIA_CONTROLLER
109 struct media_device mdev;
116 struct vicodec_dev *dev;
121 struct v4l2_ctrl_handler hdl;
123 struct vb2_v4l2_buffer *last_src_buf;
124 struct vb2_v4l2_buffer *last_dst_buf;
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 inline struct vicodec_ctx *file2ctx(struct file *file)
143 return container_of(file->private_data, struct vicodec_ctx, fh);
146 static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx,
147 enum v4l2_buf_type type)
150 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
151 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
152 return &ctx->q_data[V4L2_M2M_SRC];
153 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
154 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
155 return &ctx->q_data[V4L2_M2M_DST];
162 static void copy_cap_to_ref(const u8 *cap, const struct v4l2_fwht_pixfmt_info *info,
163 struct v4l2_fwht_state *state)
166 u8 *p_ref = state->ref_frame.buf;
167 unsigned int cap_stride = state->stride;
168 unsigned int ref_stride = state->ref_stride;
170 for (plane_idx = 0; plane_idx < info->planes_num; plane_idx++) {
172 unsigned int h_div = (plane_idx == 1 || plane_idx == 2) ?
173 info->height_div : 1;
174 const u8 *row_cap = cap;
177 if (info->planes_num == 3 && plane_idx == 1) {
182 if (plane_idx == 1 &&
183 (info->id == V4L2_PIX_FMT_NV24 ||
184 info->id == V4L2_PIX_FMT_NV42)) {
189 for (i = 0; i < state->visible_height / h_div; i++) {
190 memcpy(row_ref, row_cap, ref_stride);
191 row_ref += ref_stride;
192 row_cap += cap_stride;
194 cap += cap_stride * (state->coded_height / h_div);
195 p_ref += ref_stride * (state->coded_height / h_div);
199 static bool validate_by_version(unsigned int flags, unsigned int version)
201 if (!version || version > FWHT_VERSION)
205 unsigned int components_num = 1 +
206 ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
207 FWHT_FL_COMPONENTS_NUM_OFFSET);
208 unsigned int pixenc = flags & FWHT_FL_PIXENC_MSK;
210 if (components_num == 0 || components_num > 4 || !pixenc)
216 static bool validate_stateless_params_flags(const struct v4l2_ctrl_fwht_params *params,
217 const struct v4l2_fwht_pixfmt_info *cur_info)
219 unsigned int width_div =
220 (params->flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
221 unsigned int height_div =
222 (params->flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
223 unsigned int components_num = 3;
224 unsigned int pixenc = 0;
226 if (params->version < 3)
229 components_num = 1 + ((params->flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
230 FWHT_FL_COMPONENTS_NUM_OFFSET);
231 pixenc = (params->flags & FWHT_FL_PIXENC_MSK);
232 if (v4l2_fwht_validate_fmt(cur_info, width_div, height_div,
233 components_num, pixenc))
239 static void update_state_from_header(struct vicodec_ctx *ctx)
241 const struct fwht_cframe_hdr *p_hdr = &ctx->state.header;
243 ctx->state.visible_width = ntohl(p_hdr->width);
244 ctx->state.visible_height = ntohl(p_hdr->height);
245 ctx->state.colorspace = ntohl(p_hdr->colorspace);
246 ctx->state.xfer_func = ntohl(p_hdr->xfer_func);
247 ctx->state.ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
248 ctx->state.quantization = ntohl(p_hdr->quantization);
251 static int device_process(struct vicodec_ctx *ctx,
252 struct vb2_v4l2_buffer *src_vb,
253 struct vb2_v4l2_buffer *dst_vb)
255 struct vicodec_dev *dev = ctx->dev;
256 struct v4l2_fwht_state *state = &ctx->state;
260 if (ctx->is_enc || ctx->is_stateless)
261 p_src = vb2_plane_vaddr(&src_vb->vb2_buf, 0);
263 p_src = state->compressed_frame;
265 if (ctx->is_stateless) {
266 struct media_request *src_req = src_vb->vb2_buf.req_obj.req;
268 ret = v4l2_ctrl_request_setup(src_req, &ctx->hdl);
271 update_state_from_header(ctx);
273 ctx->state.header.size =
274 htonl(vb2_get_plane_payload(&src_vb->vb2_buf, 0));
276 * set the reference buffer from the reference timestamp
277 * only if this is a P-frame
279 if (!(ntohl(ctx->state.header.flags) & FWHT_FL_I_FRAME)) {
280 struct vb2_buffer *ref_vb2_buf;
282 struct vb2_queue *vq_cap =
283 v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
284 V4L2_BUF_TYPE_VIDEO_CAPTURE);
286 ref_buf_idx = vb2_find_timestamp(vq_cap,
287 ctx->state.ref_frame_ts, 0);
291 ref_vb2_buf = vq_cap->bufs[ref_buf_idx];
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);
339 static enum vb2_buffer_state get_next_header(struct vicodec_ctx *ctx,
342 static const u8 magic[] = {
343 0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
347 u8 *header = (u8 *)&ctx->state.header;
349 state = VB2_BUF_STATE_DONE;
351 if (!ctx->header_size) {
352 state = VB2_BUF_STATE_ERROR;
353 for (; p < *pp + sz; p++) {
356 p = memchr(p, magic[ctx->comp_magic_cnt],
359 ctx->comp_magic_cnt = 0;
363 copy = sizeof(magic) - ctx->comp_magic_cnt;
364 if (*pp + sz - p < copy)
367 memcpy(header + ctx->comp_magic_cnt, p, copy);
368 ctx->comp_magic_cnt += copy;
369 if (!memcmp(header, magic, ctx->comp_magic_cnt)) {
371 state = VB2_BUF_STATE_DONE;
374 ctx->comp_magic_cnt = 0;
376 if (ctx->comp_magic_cnt < sizeof(magic)) {
380 ctx->header_size = sizeof(magic);
383 if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
384 u32 copy = sizeof(struct fwht_cframe_hdr) - ctx->header_size;
386 if (*pp + sz - p < copy)
389 memcpy(header + ctx->header_size, p, copy);
391 ctx->header_size += copy;
397 /* device_run() - prepares and starts the device */
398 static void device_run(void *priv)
400 static const struct v4l2_event eos_event = {
401 .type = V4L2_EVENT_EOS
403 struct vicodec_ctx *ctx = priv;
404 struct vicodec_dev *dev = ctx->dev;
405 struct vb2_v4l2_buffer *src_buf, *dst_buf;
406 struct vicodec_q_data *q_src, *q_dst;
408 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, !ctx->is_enc);
426 ctx->last_dst_buf = dst_buf;
428 spin_lock(ctx->lock);
429 if (!ctx->comp_has_next_frame && src_buf == ctx->last_src_buf) {
430 dst_buf->flags |= V4L2_BUF_FLAG_LAST;
431 v4l2_event_queue_fh(&ctx->fh, &eos_event);
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 & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
482 unsigned int height_div = (flags & 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 & FWHT_FL_COMPONENTS_NUM_MSK) >>
489 FWHT_FL_COMPONENTS_NUM_OFFSET);
490 pixenc = (flags & 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 & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
524 unsigned int hdr_height_div = (flags & 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 job_remove_src_buf(ctx, state);
606 comp_frame_size = ntohl(ctx->state.header.size);
609 * The current scanned frame might be the first frame of a new
610 * resolution so its size might be larger than ctx->comp_max_size.
611 * In that case it is copied up to the current buffer capacity and
612 * the copy will continue after allocating new large enough buffer
615 max_to_copy = min(comp_frame_size, ctx->comp_max_size);
617 if (ctx->comp_size < max_to_copy) {
618 u32 copy = max_to_copy - ctx->comp_size;
620 if (copy > p_src + sz - p)
621 copy = p_src + sz - p;
623 memcpy(ctx->state.compressed_frame + ctx->comp_size,
626 ctx->comp_size += copy;
627 if (ctx->comp_size < max_to_copy) {
628 job_remove_src_buf(ctx, state);
632 ctx->cur_buf_offset = p - p_src;
633 if (ctx->comp_size == comp_frame_size)
634 ctx->comp_has_frame = true;
635 ctx->comp_has_next_frame = false;
636 if (ctx->comp_has_frame && sz - ctx->cur_buf_offset >=
637 sizeof(struct fwht_cframe_hdr)) {
638 struct fwht_cframe_hdr *p_hdr = (struct fwht_cframe_hdr *)p;
639 u32 frame_size = ntohl(p_hdr->size);
640 u32 remaining = sz - ctx->cur_buf_offset - sizeof(*p_hdr);
642 if (!memcmp(p, magic, sizeof(magic)))
643 ctx->comp_has_next_frame = remaining >= frame_size;
646 * if the header is invalid the device_run will just drop the frame
649 if (!is_header_valid(&ctx->state.header) && ctx->comp_has_frame)
651 flags = ntohl(ctx->state.header.flags);
652 hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
653 hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
655 if (ntohl(ctx->state.header.width) != q_dst->visible_width ||
656 ntohl(ctx->state.header.height) != q_dst->visible_height ||
658 hdr_width_div != q_dst->info->width_div ||
659 hdr_height_div != q_dst->info->height_div) {
660 static const struct v4l2_event rs_event = {
661 .type = V4L2_EVENT_SOURCE_CHANGE,
662 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
665 struct vb2_v4l2_buffer *dst_buf =
666 v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
668 update_capture_data_from_header(ctx);
669 ctx->first_source_change_sent = true;
670 v4l2_event_queue_fh(&ctx->fh, &rs_event);
671 set_last_buffer(dst_buf, src_buf, ctx);
672 ctx->source_changed = true;
682 static const struct v4l2_fwht_pixfmt_info *find_fmt(u32 fmt)
684 const struct v4l2_fwht_pixfmt_info *info =
685 v4l2_fwht_find_pixfmt(fmt);
688 info = v4l2_fwht_get_pixfmt(0);
692 static int vidioc_querycap(struct file *file, void *priv,
693 struct v4l2_capability *cap)
695 strscpy(cap->driver, VICODEC_NAME, sizeof(cap->driver));
696 strscpy(cap->card, VICODEC_NAME, sizeof(cap->card));
697 snprintf(cap->bus_info, sizeof(cap->bus_info),
698 "platform:%s", VICODEC_NAME);
702 static int enum_fmt(struct v4l2_fmtdesc *f, struct vicodec_ctx *ctx,
705 bool is_uncomp = (ctx->is_enc && is_out) || (!ctx->is_enc && !is_out);
707 if (V4L2_TYPE_IS_MULTIPLANAR(f->type) && !multiplanar)
709 if (!V4L2_TYPE_IS_MULTIPLANAR(f->type) && multiplanar)
713 const struct v4l2_fwht_pixfmt_info *info =
714 get_q_data(ctx, f->type)->info;
716 if (!info || ctx->is_enc)
717 info = v4l2_fwht_get_pixfmt(f->index);
719 info = v4l2_fwht_find_nth_fmt(info->width_div,
721 info->components_num,
726 f->pixelformat = info->id;
730 f->pixelformat = ctx->is_stateless ?
731 V4L2_PIX_FMT_FWHT_STATELESS : V4L2_PIX_FMT_FWHT;
736 static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
737 struct v4l2_fmtdesc *f)
739 struct vicodec_ctx *ctx = file2ctx(file);
741 return enum_fmt(f, ctx, false);
744 static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
745 struct v4l2_fmtdesc *f)
747 struct vicodec_ctx *ctx = file2ctx(file);
749 return enum_fmt(f, ctx, true);
752 static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
754 struct vb2_queue *vq;
755 struct vicodec_q_data *q_data;
756 struct v4l2_pix_format_mplane *pix_mp;
757 struct v4l2_pix_format *pix;
758 const struct v4l2_fwht_pixfmt_info *info;
760 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
764 q_data = get_q_data(ctx, f->type);
768 info = v4l2_fwht_get_pixfmt(0);
771 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
772 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
776 pix->width = q_data->coded_width;
777 pix->height = q_data->coded_height;
778 pix->field = V4L2_FIELD_NONE;
779 pix->pixelformat = info->id;
780 pix->bytesperline = q_data->coded_width *
781 info->bytesperline_mult;
782 pix->sizeimage = q_data->sizeimage;
783 pix->colorspace = ctx->state.colorspace;
784 pix->xfer_func = ctx->state.xfer_func;
785 pix->ycbcr_enc = ctx->state.ycbcr_enc;
786 pix->quantization = ctx->state.quantization;
789 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
790 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
793 pix_mp = &f->fmt.pix_mp;
794 pix_mp->width = q_data->coded_width;
795 pix_mp->height = q_data->coded_height;
796 pix_mp->field = V4L2_FIELD_NONE;
797 pix_mp->pixelformat = info->id;
798 pix_mp->num_planes = 1;
799 pix_mp->plane_fmt[0].bytesperline =
800 q_data->coded_width * info->bytesperline_mult;
801 pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage;
802 pix_mp->colorspace = ctx->state.colorspace;
803 pix_mp->xfer_func = ctx->state.xfer_func;
804 pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
805 pix_mp->quantization = ctx->state.quantization;
806 memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
807 memset(pix_mp->plane_fmt[0].reserved, 0,
808 sizeof(pix_mp->plane_fmt[0].reserved));
816 static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
817 struct v4l2_format *f)
819 return vidioc_g_fmt(file2ctx(file), f);
822 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
823 struct v4l2_format *f)
825 return vidioc_g_fmt(file2ctx(file), f);
828 static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
830 struct v4l2_pix_format_mplane *pix_mp;
831 struct v4l2_pix_format *pix;
832 struct v4l2_plane_pix_format *plane;
833 const struct v4l2_fwht_pixfmt_info *info = ctx->is_stateless ?
834 &pixfmt_stateless_fwht : &pixfmt_fwht;
837 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
838 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
840 if (pix->pixelformat != V4L2_PIX_FMT_FWHT &&
841 pix->pixelformat != V4L2_PIX_FMT_FWHT_STATELESS)
842 info = find_fmt(pix->pixelformat);
844 pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH);
845 pix->width = vic_round_dim(pix->width, info->width_div);
847 pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT);
848 pix->height = vic_round_dim(pix->height, info->height_div);
850 pix->field = V4L2_FIELD_NONE;
852 pix->width * info->bytesperline_mult;
853 pix->sizeimage = pix->width * pix->height *
854 info->sizeimage_mult / info->sizeimage_div;
855 if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
856 pix->sizeimage += sizeof(struct fwht_cframe_hdr);
858 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
859 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
860 pix_mp = &f->fmt.pix_mp;
861 plane = pix_mp->plane_fmt;
862 if (pix_mp->pixelformat != V4L2_PIX_FMT_FWHT &&
863 pix_mp->pixelformat != V4L2_PIX_FMT_FWHT_STATELESS)
864 info = find_fmt(pix_mp->pixelformat);
865 pix_mp->num_planes = 1;
867 pix_mp->width = clamp(pix_mp->width, MIN_WIDTH, MAX_WIDTH);
868 pix_mp->width = vic_round_dim(pix_mp->width, info->width_div);
870 pix_mp->height = clamp(pix_mp->height, MIN_HEIGHT, MAX_HEIGHT);
871 pix_mp->height = vic_round_dim(pix_mp->height,
874 pix_mp->field = V4L2_FIELD_NONE;
875 plane->bytesperline =
876 pix_mp->width * info->bytesperline_mult;
877 plane->sizeimage = pix_mp->width * pix_mp->height *
878 info->sizeimage_mult / info->sizeimage_div;
879 if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
880 plane->sizeimage += sizeof(struct fwht_cframe_hdr);
881 memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
882 memset(plane->reserved, 0, sizeof(plane->reserved));
891 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
892 struct v4l2_format *f)
894 struct vicodec_ctx *ctx = file2ctx(file);
895 struct v4l2_pix_format_mplane *pix_mp;
896 struct v4l2_pix_format *pix;
899 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
903 pix->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
904 find_fmt(f->fmt.pix.pixelformat)->id;
905 pix->colorspace = ctx->state.colorspace;
906 pix->xfer_func = ctx->state.xfer_func;
907 pix->ycbcr_enc = ctx->state.ycbcr_enc;
908 pix->quantization = ctx->state.quantization;
910 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
913 pix_mp = &f->fmt.pix_mp;
914 pix_mp->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
915 find_fmt(pix_mp->pixelformat)->id;
916 pix_mp->colorspace = ctx->state.colorspace;
917 pix_mp->xfer_func = ctx->state.xfer_func;
918 pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
919 pix_mp->quantization = ctx->state.quantization;
925 return vidioc_try_fmt(ctx, f);
928 static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
929 struct v4l2_format *f)
931 struct vicodec_ctx *ctx = file2ctx(file);
932 struct v4l2_pix_format_mplane *pix_mp;
933 struct v4l2_pix_format *pix;
936 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
941 pix->pixelformat = find_fmt(pix->pixelformat)->id;
942 else if (ctx->is_stateless)
943 pix->pixelformat = V4L2_PIX_FMT_FWHT_STATELESS;
945 pix->pixelformat = V4L2_PIX_FMT_FWHT;
946 if (!pix->colorspace)
947 pix->colorspace = V4L2_COLORSPACE_REC709;
949 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
952 pix_mp = &f->fmt.pix_mp;
954 pix_mp->pixelformat = find_fmt(pix_mp->pixelformat)->id;
955 else if (ctx->is_stateless)
956 pix_mp->pixelformat = V4L2_PIX_FMT_FWHT_STATELESS;
958 pix_mp->pixelformat = V4L2_PIX_FMT_FWHT;
959 if (!pix_mp->colorspace)
960 pix_mp->colorspace = V4L2_COLORSPACE_REC709;
966 return vidioc_try_fmt(ctx, f);
969 static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
971 struct vicodec_q_data *q_data;
972 struct vb2_queue *vq;
973 bool fmt_changed = true;
974 struct v4l2_pix_format_mplane *pix_mp;
975 struct v4l2_pix_format *pix;
977 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
981 q_data = get_q_data(ctx, f->type);
986 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
987 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
989 if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
992 q_data->info->id != pix->pixelformat ||
993 q_data->coded_width != pix->width ||
994 q_data->coded_height != pix->height;
996 if (vb2_is_busy(vq) && fmt_changed)
999 if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
1000 q_data->info = &pixfmt_fwht;
1001 else if (pix->pixelformat == V4L2_PIX_FMT_FWHT_STATELESS)
1002 q_data->info = &pixfmt_stateless_fwht;
1004 q_data->info = find_fmt(pix->pixelformat);
1005 q_data->coded_width = pix->width;
1006 q_data->coded_height = pix->height;
1007 q_data->sizeimage = pix->sizeimage;
1009 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1010 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1011 pix_mp = &f->fmt.pix_mp;
1012 if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
1015 q_data->info->id != pix_mp->pixelformat ||
1016 q_data->coded_width != pix_mp->width ||
1017 q_data->coded_height != pix_mp->height;
1019 if (vb2_is_busy(vq) && fmt_changed)
1022 if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
1023 q_data->info = &pixfmt_fwht;
1024 else if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT_STATELESS)
1025 q_data->info = &pixfmt_stateless_fwht;
1027 q_data->info = find_fmt(pix_mp->pixelformat);
1028 q_data->coded_width = pix_mp->width;
1029 q_data->coded_height = pix_mp->height;
1030 q_data->sizeimage = pix_mp->plane_fmt[0].sizeimage;
1037 "Setting format for type %d, coded wxh: %dx%d, fourcc: 0x%08x\n",
1038 f->type, q_data->coded_width, q_data->coded_height,
1044 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1045 struct v4l2_format *f)
1049 ret = vidioc_try_fmt_vid_cap(file, priv, f);
1053 return vidioc_s_fmt(file2ctx(file), f);
1056 static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
1057 struct v4l2_format *f)
1059 struct vicodec_ctx *ctx = file2ctx(file);
1060 struct vicodec_q_data *q_data;
1061 struct vicodec_q_data *q_data_cap;
1062 struct v4l2_pix_format *pix;
1063 struct v4l2_pix_format_mplane *pix_mp;
1064 u32 coded_w = 0, coded_h = 0;
1065 unsigned int size = 0;
1068 q_data = get_q_data(ctx, f->type);
1069 q_data_cap = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
1071 ret = vidioc_try_fmt_vid_out(file, priv, f);
1076 struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
1077 struct vb2_queue *vq_cap = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
1078 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1079 const struct v4l2_fwht_pixfmt_info *info = ctx->is_stateless ?
1080 &pixfmt_stateless_fwht : &pixfmt_fwht;
1082 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1083 coded_w = f->fmt.pix.width;
1084 coded_h = f->fmt.pix.height;
1086 coded_w = f->fmt.pix_mp.width;
1087 coded_h = f->fmt.pix_mp.height;
1089 if (vb2_is_busy(vq) && (coded_w != q_data->coded_width ||
1090 coded_h != q_data->coded_height))
1092 size = coded_w * coded_h *
1093 info->sizeimage_mult / info->sizeimage_div;
1094 if (!ctx->is_stateless)
1095 size += sizeof(struct fwht_cframe_hdr);
1097 if (vb2_is_busy(vq_cap) && size > q_data_cap->sizeimage)
1101 ret = vidioc_s_fmt(file2ctx(file), f);
1104 q_data->visible_width = coded_w;
1105 q_data->visible_height = coded_h;
1106 q_data_cap->coded_width = coded_w;
1107 q_data_cap->coded_height = coded_h;
1108 q_data_cap->sizeimage = size;
1112 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1114 ctx->state.colorspace = pix->colorspace;
1115 ctx->state.xfer_func = pix->xfer_func;
1116 ctx->state.ycbcr_enc = pix->ycbcr_enc;
1117 ctx->state.quantization = pix->quantization;
1119 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1120 pix_mp = &f->fmt.pix_mp;
1121 ctx->state.colorspace = pix_mp->colorspace;
1122 ctx->state.xfer_func = pix_mp->xfer_func;
1123 ctx->state.ycbcr_enc = pix_mp->ycbcr_enc;
1124 ctx->state.quantization = pix_mp->quantization;
1133 static int vidioc_g_selection(struct file *file, void *priv,
1134 struct v4l2_selection *s)
1136 struct vicodec_ctx *ctx = file2ctx(file);
1137 struct vicodec_q_data *q_data;
1139 q_data = get_q_data(ctx, s->type);
1143 * encoder supports only cropping on the OUTPUT buffer
1144 * decoder supports only composing on the CAPTURE buffer
1146 if (ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1147 switch (s->target) {
1148 case V4L2_SEL_TGT_CROP:
1151 s->r.width = q_data->visible_width;
1152 s->r.height = q_data->visible_height;
1154 case V4L2_SEL_TGT_CROP_DEFAULT:
1155 case V4L2_SEL_TGT_CROP_BOUNDS:
1158 s->r.width = q_data->coded_width;
1159 s->r.height = q_data->coded_height;
1162 } else if (!ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1163 switch (s->target) {
1164 case V4L2_SEL_TGT_COMPOSE:
1167 s->r.width = q_data->visible_width;
1168 s->r.height = q_data->visible_height;
1170 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1171 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1174 s->r.width = q_data->coded_width;
1175 s->r.height = q_data->coded_height;
1182 static int vidioc_s_selection(struct file *file, void *priv,
1183 struct v4l2_selection *s)
1185 struct vicodec_ctx *ctx = file2ctx(file);
1186 struct vicodec_q_data *q_data;
1188 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1191 q_data = get_q_data(ctx, s->type);
1195 if (!ctx->is_enc || s->target != V4L2_SEL_TGT_CROP)
1200 q_data->visible_width = clamp(s->r.width, MIN_WIDTH,
1201 q_data->coded_width);
1202 s->r.width = q_data->visible_width;
1203 q_data->visible_height = clamp(s->r.height, MIN_HEIGHT,
1204 q_data->coded_height);
1205 s->r.height = q_data->visible_height;
1209 static void vicodec_mark_last_buf(struct vicodec_ctx *ctx)
1211 static const struct v4l2_event eos_event = {
1212 .type = V4L2_EVENT_EOS
1215 spin_lock(ctx->lock);
1216 ctx->last_src_buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx);
1217 if (!ctx->last_src_buf && ctx->last_dst_buf) {
1218 ctx->last_dst_buf->flags |= V4L2_BUF_FLAG_LAST;
1219 v4l2_event_queue_fh(&ctx->fh, &eos_event);
1221 spin_unlock(ctx->lock);
1224 static int vicodec_encoder_cmd(struct file *file, void *fh,
1225 struct v4l2_encoder_cmd *ec)
1227 struct vicodec_ctx *ctx = file2ctx(file);
1230 ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec);
1234 vicodec_mark_last_buf(ctx);
1238 static int vicodec_decoder_cmd(struct file *file, void *fh,
1239 struct v4l2_decoder_cmd *dc)
1241 struct vicodec_ctx *ctx = file2ctx(file);
1244 ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc);
1248 vicodec_mark_last_buf(ctx);
1252 static int vicodec_enum_framesizes(struct file *file, void *fh,
1253 struct v4l2_frmsizeenum *fsize)
1255 switch (fsize->pixel_format) {
1256 case V4L2_PIX_FMT_FWHT_STATELESS:
1258 case V4L2_PIX_FMT_FWHT:
1261 if (find_fmt(fsize->pixel_format)->id == fsize->pixel_format)
1269 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
1271 fsize->stepwise.min_width = MIN_WIDTH;
1272 fsize->stepwise.max_width = MAX_WIDTH;
1273 fsize->stepwise.step_width = 8;
1274 fsize->stepwise.min_height = MIN_HEIGHT;
1275 fsize->stepwise.max_height = MAX_HEIGHT;
1276 fsize->stepwise.step_height = 8;
1281 static int vicodec_subscribe_event(struct v4l2_fh *fh,
1282 const struct v4l2_event_subscription *sub)
1284 struct vicodec_ctx *ctx = container_of(fh, struct vicodec_ctx, fh);
1286 switch (sub->type) {
1287 case V4L2_EVENT_SOURCE_CHANGE:
1291 case V4L2_EVENT_EOS:
1292 return v4l2_event_subscribe(fh, sub, 0, NULL);
1294 return v4l2_ctrl_subscribe_event(fh, sub);
1298 static const struct v4l2_ioctl_ops vicodec_ioctl_ops = {
1299 .vidioc_querycap = vidioc_querycap,
1301 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1302 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1303 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1304 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1306 .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap,
1307 .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap,
1308 .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap,
1310 .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
1311 .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
1312 .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
1313 .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
1315 .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out,
1316 .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out,
1317 .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out,
1319 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
1320 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
1321 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
1322 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
1323 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
1324 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
1325 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
1327 .vidioc_streamon = v4l2_m2m_ioctl_streamon,
1328 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
1330 .vidioc_g_selection = vidioc_g_selection,
1331 .vidioc_s_selection = vidioc_s_selection,
1333 .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
1334 .vidioc_encoder_cmd = vicodec_encoder_cmd,
1335 .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
1336 .vidioc_decoder_cmd = vicodec_decoder_cmd,
1337 .vidioc_enum_framesizes = vicodec_enum_framesizes,
1339 .vidioc_subscribe_event = vicodec_subscribe_event,
1340 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1348 static int vicodec_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
1349 unsigned int *nplanes, unsigned int sizes[],
1350 struct device *alloc_devs[])
1352 struct vicodec_ctx *ctx = vb2_get_drv_priv(vq);
1353 struct vicodec_q_data *q_data = get_q_data(ctx, vq->type);
1354 unsigned int size = q_data->sizeimage;
1357 return sizes[0] < size ? -EINVAL : 0;
1364 static int vicodec_buf_out_validate(struct vb2_buffer *vb)
1366 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1368 vbuf->field = V4L2_FIELD_NONE;
1372 static int vicodec_buf_prepare(struct vb2_buffer *vb)
1374 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1375 struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1376 struct vicodec_q_data *q_data;
1378 dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
1380 q_data = get_q_data(ctx, vb->vb2_queue->type);
1381 if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
1382 if (vbuf->field == V4L2_FIELD_ANY)
1383 vbuf->field = V4L2_FIELD_NONE;
1384 if (vbuf->field != V4L2_FIELD_NONE) {
1385 dprintk(ctx->dev, "%s field isn't supported\n",
1391 if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
1393 "%s data will not fit into plane (%lu < %lu)\n",
1394 __func__, vb2_plane_size(vb, 0),
1395 (long)q_data->sizeimage);
1402 static void vicodec_buf_queue(struct vb2_buffer *vb)
1404 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1405 struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1406 unsigned int sz = vb2_get_plane_payload(&vbuf->vb2_buf, 0);
1407 u8 *p_src = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
1409 struct vb2_queue *vq_out = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
1410 V4L2_BUF_TYPE_VIDEO_OUTPUT);
1411 struct vb2_queue *vq_cap = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
1412 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1413 bool header_valid = false;
1414 static const struct v4l2_event rs_event = {
1415 .type = V4L2_EVENT_SOURCE_CHANGE,
1416 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
1419 /* buf_queue handles only the first source change event */
1420 if (ctx->first_source_change_sent) {
1421 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1426 * if both queues are streaming, the source change event is
1427 * handled in job_ready
1429 if (vb2_is_streaming(vq_cap) && vb2_is_streaming(vq_out)) {
1430 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1435 * source change event is relevant only for the stateful decoder
1436 * in the compressed stream
1438 if (ctx->is_stateless || ctx->is_enc ||
1439 !V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
1440 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1445 enum vb2_buffer_state state =
1446 get_next_header(ctx, &p, p_src + sz - p);
1448 if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
1449 v4l2_m2m_buf_done(vbuf, state);
1452 header_valid = is_header_valid(&ctx->state.header);
1454 * p points right after the end of the header in the
1455 * buffer. If the header is invalid we set p to point
1456 * to the next byte after the start of the header
1458 if (!header_valid) {
1459 p = p - sizeof(struct fwht_cframe_hdr) + 1;
1462 ctx->header_size = 0;
1463 ctx->comp_magic_cnt = 0;
1466 } while (!header_valid);
1468 ctx->cur_buf_offset = p - p_src;
1469 update_capture_data_from_header(ctx);
1470 ctx->first_source_change_sent = true;
1471 v4l2_event_queue_fh(&ctx->fh, &rs_event);
1472 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1475 static void vicodec_return_bufs(struct vb2_queue *q, u32 state)
1477 struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
1478 struct vb2_v4l2_buffer *vbuf;
1481 if (V4L2_TYPE_IS_OUTPUT(q->type))
1482 vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
1484 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
1487 v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
1489 spin_lock(ctx->lock);
1490 v4l2_m2m_buf_done(vbuf, state);
1491 spin_unlock(ctx->lock);
1495 static unsigned int total_frame_size(struct vicodec_q_data *q_data)
1498 unsigned int chroma_div;
1500 if (!q_data->info) {
1504 size = q_data->coded_width * q_data->coded_height;
1505 chroma_div = q_data->info->width_div * q_data->info->height_div;
1507 if (q_data->info->components_num == 4)
1508 return 2 * size + 2 * (size / chroma_div);
1509 else if (q_data->info->components_num == 3)
1510 return size + 2 * (size / chroma_div);
1514 static int vicodec_start_streaming(struct vb2_queue *q,
1517 struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
1518 struct vicodec_q_data *q_data = get_q_data(ctx, q->type);
1519 struct v4l2_fwht_state *state = &ctx->state;
1520 const struct v4l2_fwht_pixfmt_info *info = q_data->info;
1521 unsigned int size = q_data->coded_width * q_data->coded_height;
1522 unsigned int chroma_div;
1523 unsigned int total_planes_size;
1524 u8 *new_comp_frame = NULL;
1529 chroma_div = info->width_div * info->height_div;
1530 q_data->sequence = 0;
1532 if (V4L2_TYPE_IS_OUTPUT(q->type))
1533 ctx->last_src_buf = NULL;
1535 ctx->last_dst_buf = NULL;
1539 if ((V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) ||
1540 (!V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc))
1543 if (info->id == V4L2_PIX_FMT_FWHT ||
1544 info->id == V4L2_PIX_FMT_FWHT_STATELESS) {
1545 vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
1548 total_planes_size = total_frame_size(q_data);
1549 ctx->comp_max_size = total_planes_size;
1551 state->visible_width = q_data->visible_width;
1552 state->visible_height = q_data->visible_height;
1553 state->coded_width = q_data->coded_width;
1554 state->coded_height = q_data->coded_height;
1555 state->stride = q_data->coded_width *
1556 info->bytesperline_mult;
1558 if (ctx->is_stateless) {
1559 state->ref_stride = state->stride;
1562 state->ref_stride = q_data->coded_width * info->luma_alpha_step;
1564 state->ref_frame.buf = kvmalloc(total_planes_size, GFP_KERNEL);
1565 state->ref_frame.luma = state->ref_frame.buf;
1566 new_comp_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL);
1568 if (!state->ref_frame.luma || !new_comp_frame) {
1569 kvfree(state->ref_frame.luma);
1570 kvfree(new_comp_frame);
1571 vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
1575 * if state->compressed_frame was already allocated then
1576 * it contain data of the first frame of the new resolution
1578 if (state->compressed_frame) {
1579 if (ctx->comp_size > ctx->comp_max_size)
1580 ctx->comp_size = ctx->comp_max_size;
1582 memcpy(new_comp_frame,
1583 state->compressed_frame, ctx->comp_size);
1586 kvfree(state->compressed_frame);
1587 state->compressed_frame = new_comp_frame;
1589 if (info->components_num >= 3) {
1590 state->ref_frame.cb = state->ref_frame.luma + size;
1591 state->ref_frame.cr = state->ref_frame.cb + size / chroma_div;
1593 state->ref_frame.cb = NULL;
1594 state->ref_frame.cr = NULL;
1597 if (info->components_num == 4)
1598 state->ref_frame.alpha =
1599 state->ref_frame.cr + size / chroma_div;
1601 state->ref_frame.alpha = NULL;
1605 static void vicodec_stop_streaming(struct vb2_queue *q)
1607 struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
1609 vicodec_return_bufs(q, VB2_BUF_STATE_ERROR);
1611 if ((!V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) ||
1612 (V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc)) {
1613 if (!ctx->is_stateless)
1614 kvfree(ctx->state.ref_frame.buf);
1615 ctx->state.ref_frame.buf = NULL;
1616 ctx->state.ref_frame.luma = NULL;
1617 ctx->comp_max_size = 0;
1618 ctx->source_changed = false;
1620 if (V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) {
1621 ctx->cur_buf_offset = 0;
1623 ctx->header_size = 0;
1624 ctx->comp_magic_cnt = 0;
1625 ctx->comp_has_frame = 0;
1626 ctx->comp_has_next_frame = 0;
1630 static void vicodec_buf_request_complete(struct vb2_buffer *vb)
1632 struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1634 v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
1638 static const struct vb2_ops vicodec_qops = {
1639 .queue_setup = vicodec_queue_setup,
1640 .buf_out_validate = vicodec_buf_out_validate,
1641 .buf_prepare = vicodec_buf_prepare,
1642 .buf_queue = vicodec_buf_queue,
1643 .buf_request_complete = vicodec_buf_request_complete,
1644 .start_streaming = vicodec_start_streaming,
1645 .stop_streaming = vicodec_stop_streaming,
1646 .wait_prepare = vb2_ops_wait_prepare,
1647 .wait_finish = vb2_ops_wait_finish,
1650 static int queue_init(void *priv, struct vb2_queue *src_vq,
1651 struct vb2_queue *dst_vq)
1653 struct vicodec_ctx *ctx = priv;
1656 src_vq->type = (multiplanar ?
1657 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
1658 V4L2_BUF_TYPE_VIDEO_OUTPUT);
1659 src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1660 src_vq->drv_priv = ctx;
1661 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1662 src_vq->ops = &vicodec_qops;
1663 src_vq->mem_ops = &vb2_vmalloc_memops;
1664 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1666 src_vq->lock = &ctx->dev->stateful_enc.mutex;
1667 else if (ctx->is_stateless)
1668 src_vq->lock = &ctx->dev->stateless_dec.mutex;
1670 src_vq->lock = &ctx->dev->stateful_dec.mutex;
1671 src_vq->supports_requests = ctx->is_stateless;
1672 src_vq->requires_requests = ctx->is_stateless;
1673 ret = vb2_queue_init(src_vq);
1677 dst_vq->type = (multiplanar ?
1678 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
1679 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1680 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1681 dst_vq->drv_priv = ctx;
1682 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1683 dst_vq->ops = &vicodec_qops;
1684 dst_vq->mem_ops = &vb2_vmalloc_memops;
1685 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1686 dst_vq->lock = src_vq->lock;
1688 return vb2_queue_init(dst_vq);
1691 static int vicodec_try_ctrl(struct v4l2_ctrl *ctrl)
1693 struct vicodec_ctx *ctx = container_of(ctrl->handler,
1694 struct vicodec_ctx, hdl);
1695 const struct v4l2_ctrl_fwht_params *params;
1696 struct vicodec_q_data *q_dst = get_q_data(ctx,
1697 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1700 case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS:
1703 params = ctrl->p_new.p_fwht_params;
1704 if (params->width > q_dst->coded_width ||
1705 params->width < MIN_WIDTH ||
1706 params->height > q_dst->coded_height ||
1707 params->height < MIN_HEIGHT)
1709 if (!validate_by_version(params->flags, params->version))
1711 if (!validate_stateless_params_flags(params, q_dst->info))
1720 static void update_header_from_stateless_params(struct vicodec_ctx *ctx,
1721 const struct v4l2_ctrl_fwht_params *params)
1723 struct fwht_cframe_hdr *p_hdr = &ctx->state.header;
1725 p_hdr->magic1 = FWHT_MAGIC1;
1726 p_hdr->magic2 = FWHT_MAGIC2;
1727 p_hdr->version = htonl(params->version);
1728 p_hdr->width = htonl(params->width);
1729 p_hdr->height = htonl(params->height);
1730 p_hdr->flags = htonl(params->flags);
1731 p_hdr->colorspace = htonl(params->colorspace);
1732 p_hdr->xfer_func = htonl(params->xfer_func);
1733 p_hdr->ycbcr_enc = htonl(params->ycbcr_enc);
1734 p_hdr->quantization = htonl(params->quantization);
1737 static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl)
1739 struct vicodec_ctx *ctx = container_of(ctrl->handler,
1740 struct vicodec_ctx, hdl);
1741 const struct v4l2_ctrl_fwht_params *params;
1744 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1745 ctx->state.gop_size = ctrl->val;
1747 case V4L2_CID_FWHT_I_FRAME_QP:
1748 ctx->state.i_frame_qp = ctrl->val;
1750 case V4L2_CID_FWHT_P_FRAME_QP:
1751 ctx->state.p_frame_qp = ctrl->val;
1753 case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS:
1754 params = ctrl->p_new.p_fwht_params;
1755 update_header_from_stateless_params(ctx, params);
1756 ctx->state.ref_frame_ts = params->backward_ref_ts;
1762 static const struct v4l2_ctrl_ops vicodec_ctrl_ops = {
1763 .s_ctrl = vicodec_s_ctrl,
1764 .try_ctrl = vicodec_try_ctrl,
1767 static const struct v4l2_ctrl_config vicodec_ctrl_stateless_state = {
1768 .ops = &vicodec_ctrl_ops,
1769 .id = V4L2_CID_MPEG_VIDEO_FWHT_PARAMS,
1770 .elem_size = sizeof(struct v4l2_ctrl_fwht_params),
1776 static int vicodec_open(struct file *file)
1778 const struct v4l2_fwht_pixfmt_info *info = v4l2_fwht_get_pixfmt(0);
1779 struct video_device *vfd = video_devdata(file);
1780 struct vicodec_dev *dev = video_drvdata(file);
1781 struct vicodec_ctx *ctx = NULL;
1782 struct v4l2_ctrl_handler *hdl;
1783 unsigned int raw_size;
1784 unsigned int comp_size;
1787 if (mutex_lock_interruptible(vfd->lock))
1788 return -ERESTARTSYS;
1789 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1795 if (vfd == &dev->stateful_enc.vfd)
1797 else if (vfd == &dev->stateless_dec.vfd)
1798 ctx->is_stateless = true;
1800 v4l2_fh_init(&ctx->fh, video_devdata(file));
1801 file->private_data = &ctx->fh;
1804 v4l2_ctrl_handler_init(hdl, 5);
1805 v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE,
1807 v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_I_FRAME_QP,
1809 v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_P_FRAME_QP,
1812 v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops,
1813 V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 1, 1, 1);
1814 if (ctx->is_stateless)
1815 v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_stateless_state, NULL);
1818 v4l2_ctrl_handler_free(hdl);
1822 ctx->fh.ctrl_handler = hdl;
1823 v4l2_ctrl_handler_setup(hdl);
1826 ctx->q_data[V4L2_M2M_SRC].info = info;
1827 else if (ctx->is_stateless)
1828 ctx->q_data[V4L2_M2M_SRC].info = &pixfmt_stateless_fwht;
1830 ctx->q_data[V4L2_M2M_SRC].info = &pixfmt_fwht;
1831 ctx->q_data[V4L2_M2M_SRC].coded_width = 1280;
1832 ctx->q_data[V4L2_M2M_SRC].coded_height = 720;
1833 ctx->q_data[V4L2_M2M_SRC].visible_width = 1280;
1834 ctx->q_data[V4L2_M2M_SRC].visible_height = 720;
1835 raw_size = 1280 * 720 * info->sizeimage_mult / info->sizeimage_div;
1836 comp_size = 1280 * 720 * pixfmt_fwht.sizeimage_mult /
1837 pixfmt_fwht.sizeimage_div;
1839 ctx->q_data[V4L2_M2M_SRC].sizeimage = raw_size;
1840 else if (ctx->is_stateless)
1841 ctx->q_data[V4L2_M2M_SRC].sizeimage = comp_size;
1843 ctx->q_data[V4L2_M2M_SRC].sizeimage =
1844 comp_size + sizeof(struct fwht_cframe_hdr);
1845 ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
1847 ctx->q_data[V4L2_M2M_DST].info = &pixfmt_fwht;
1848 ctx->q_data[V4L2_M2M_DST].sizeimage =
1849 comp_size + sizeof(struct fwht_cframe_hdr);
1851 ctx->q_data[V4L2_M2M_DST].info = info;
1852 ctx->q_data[V4L2_M2M_DST].sizeimage = raw_size;
1855 ctx->state.colorspace = V4L2_COLORSPACE_REC709;
1858 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateful_enc.m2m_dev,
1860 ctx->lock = &dev->stateful_enc.lock;
1861 } else if (ctx->is_stateless) {
1862 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateless_dec.m2m_dev,
1864 ctx->lock = &dev->stateless_dec.lock;
1866 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateful_dec.m2m_dev,
1868 ctx->lock = &dev->stateful_dec.lock;
1871 if (IS_ERR(ctx->fh.m2m_ctx)) {
1872 rc = PTR_ERR(ctx->fh.m2m_ctx);
1874 v4l2_ctrl_handler_free(hdl);
1875 v4l2_fh_exit(&ctx->fh);
1880 v4l2_fh_add(&ctx->fh);
1883 mutex_unlock(vfd->lock);
1887 static int vicodec_release(struct file *file)
1889 struct video_device *vfd = video_devdata(file);
1890 struct vicodec_ctx *ctx = file2ctx(file);
1892 mutex_lock(vfd->lock);
1893 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
1894 mutex_unlock(vfd->lock);
1895 v4l2_fh_del(&ctx->fh);
1896 v4l2_fh_exit(&ctx->fh);
1897 v4l2_ctrl_handler_free(&ctx->hdl);
1898 kvfree(ctx->state.compressed_frame);
1904 static int vicodec_request_validate(struct media_request *req)
1906 struct media_request_object *obj;
1907 struct v4l2_ctrl_handler *parent_hdl, *hdl;
1908 struct vicodec_ctx *ctx = NULL;
1909 struct v4l2_ctrl *ctrl;
1912 list_for_each_entry(obj, &req->objects, list) {
1913 struct vb2_buffer *vb;
1915 if (vb2_request_object_is_buffer(obj)) {
1916 vb = container_of(obj, struct vb2_buffer, req_obj);
1917 ctx = vb2_get_drv_priv(vb->vb2_queue);
1924 pr_err("No buffer was provided with the request\n");
1928 count = vb2_request_buffer_cnt(req);
1930 v4l2_info(&ctx->dev->v4l2_dev,
1931 "No buffer was provided with the request\n");
1933 } else if (count > 1) {
1934 v4l2_info(&ctx->dev->v4l2_dev,
1935 "More than one buffer was provided with the request\n");
1939 parent_hdl = &ctx->hdl;
1941 hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl);
1943 v4l2_info(&ctx->dev->v4l2_dev, "Missing codec control\n");
1946 ctrl = v4l2_ctrl_request_hdl_ctrl_find(hdl,
1947 vicodec_ctrl_stateless_state.id);
1949 v4l2_info(&ctx->dev->v4l2_dev,
1950 "Missing required codec control\n");
1954 return vb2_request_validate(req);
1957 static const struct v4l2_file_operations vicodec_fops = {
1958 .owner = THIS_MODULE,
1959 .open = vicodec_open,
1960 .release = vicodec_release,
1961 .poll = v4l2_m2m_fop_poll,
1962 .unlocked_ioctl = video_ioctl2,
1963 .mmap = v4l2_m2m_fop_mmap,
1966 static const struct video_device vicodec_videodev = {
1967 .name = VICODEC_NAME,
1968 .vfl_dir = VFL_DIR_M2M,
1969 .fops = &vicodec_fops,
1970 .ioctl_ops = &vicodec_ioctl_ops,
1972 .release = video_device_release_empty,
1975 static const struct media_device_ops vicodec_m2m_media_ops = {
1976 .req_validate = vicodec_request_validate,
1977 .req_queue = v4l2_m2m_request_queue,
1980 static const struct v4l2_m2m_ops m2m_ops = {
1981 .device_run = device_run,
1982 .job_ready = job_ready,
1985 static int register_instance(struct vicodec_dev *dev,
1986 struct vicodec_dev_instance *dev_instance,
1987 const char *name, bool is_enc)
1989 struct video_device *vfd;
1992 spin_lock_init(&dev_instance->lock);
1993 mutex_init(&dev_instance->mutex);
1994 dev_instance->m2m_dev = v4l2_m2m_init(&m2m_ops);
1995 if (IS_ERR(dev_instance->m2m_dev)) {
1996 v4l2_err(&dev->v4l2_dev, "Failed to init vicodec enc device\n");
1997 return PTR_ERR(dev_instance->m2m_dev);
2000 dev_instance->vfd = vicodec_videodev;
2001 vfd = &dev_instance->vfd;
2002 vfd->lock = &dev_instance->mutex;
2003 vfd->v4l2_dev = &dev->v4l2_dev;
2004 strscpy(vfd->name, name, sizeof(vfd->name));
2005 vfd->device_caps = V4L2_CAP_STREAMING |
2006 (multiplanar ? V4L2_CAP_VIDEO_M2M_MPLANE : V4L2_CAP_VIDEO_M2M);
2008 v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
2009 v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
2011 v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
2012 v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
2014 video_set_drvdata(vfd, dev);
2016 ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
2018 v4l2_err(&dev->v4l2_dev, "Failed to register video device '%s'\n", name);
2019 v4l2_m2m_release(dev_instance->m2m_dev);
2022 v4l2_info(&dev->v4l2_dev, "Device '%s' registered as /dev/video%d\n",
2027 static void vicodec_v4l2_dev_release(struct v4l2_device *v4l2_dev)
2029 struct vicodec_dev *dev = container_of(v4l2_dev, struct vicodec_dev, v4l2_dev);
2031 v4l2_device_unregister(&dev->v4l2_dev);
2032 v4l2_m2m_release(dev->stateful_enc.m2m_dev);
2033 v4l2_m2m_release(dev->stateful_dec.m2m_dev);
2034 v4l2_m2m_release(dev->stateless_dec.m2m_dev);
2038 static int vicodec_probe(struct platform_device *pdev)
2040 struct vicodec_dev *dev;
2043 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
2047 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
2051 dev->v4l2_dev.release = vicodec_v4l2_dev_release;
2053 #ifdef CONFIG_MEDIA_CONTROLLER
2054 dev->mdev.dev = &pdev->dev;
2055 strscpy(dev->mdev.model, "vicodec", sizeof(dev->mdev.model));
2056 strscpy(dev->mdev.bus_info, "platform:vicodec",
2057 sizeof(dev->mdev.bus_info));
2058 media_device_init(&dev->mdev);
2059 dev->mdev.ops = &vicodec_m2m_media_ops;
2060 dev->v4l2_dev.mdev = &dev->mdev;
2063 platform_set_drvdata(pdev, dev);
2065 if (register_instance(dev, &dev->stateful_enc,
2066 "stateful-encoder", true))
2069 if (register_instance(dev, &dev->stateful_dec,
2070 "stateful-decoder", false))
2073 if (register_instance(dev, &dev->stateless_dec,
2074 "stateless-decoder", false))
2077 #ifdef CONFIG_MEDIA_CONTROLLER
2078 ret = v4l2_m2m_register_media_controller(dev->stateful_enc.m2m_dev,
2079 &dev->stateful_enc.vfd,
2080 MEDIA_ENT_F_PROC_VIDEO_ENCODER);
2082 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for enc\n");
2086 ret = v4l2_m2m_register_media_controller(dev->stateful_dec.m2m_dev,
2087 &dev->stateful_dec.vfd,
2088 MEDIA_ENT_F_PROC_VIDEO_DECODER);
2090 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for dec\n");
2091 goto unreg_m2m_sf_enc_mc;
2094 ret = v4l2_m2m_register_media_controller(dev->stateless_dec.m2m_dev,
2095 &dev->stateless_dec.vfd,
2096 MEDIA_ENT_F_PROC_VIDEO_DECODER);
2098 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for stateless dec\n");
2099 goto unreg_m2m_sf_dec_mc;
2102 ret = media_device_register(&dev->mdev);
2104 v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n");
2105 goto unreg_m2m_sl_dec_mc;
2110 #ifdef CONFIG_MEDIA_CONTROLLER
2111 unreg_m2m_sl_dec_mc:
2112 v4l2_m2m_unregister_media_controller(dev->stateless_dec.m2m_dev);
2113 unreg_m2m_sf_dec_mc:
2114 v4l2_m2m_unregister_media_controller(dev->stateful_dec.m2m_dev);
2115 unreg_m2m_sf_enc_mc:
2116 v4l2_m2m_unregister_media_controller(dev->stateful_enc.m2m_dev);
2118 video_unregister_device(&dev->stateless_dec.vfd);
2119 v4l2_m2m_release(dev->stateless_dec.m2m_dev);
2122 video_unregister_device(&dev->stateful_dec.vfd);
2123 v4l2_m2m_release(dev->stateful_dec.m2m_dev);
2125 video_unregister_device(&dev->stateful_enc.vfd);
2126 v4l2_m2m_release(dev->stateful_enc.m2m_dev);
2128 v4l2_device_unregister(&dev->v4l2_dev);
2135 static int vicodec_remove(struct platform_device *pdev)
2137 struct vicodec_dev *dev = platform_get_drvdata(pdev);
2139 v4l2_info(&dev->v4l2_dev, "Removing " VICODEC_NAME);
2141 #ifdef CONFIG_MEDIA_CONTROLLER
2142 media_device_unregister(&dev->mdev);
2143 v4l2_m2m_unregister_media_controller(dev->stateful_enc.m2m_dev);
2144 v4l2_m2m_unregister_media_controller(dev->stateful_dec.m2m_dev);
2145 v4l2_m2m_unregister_media_controller(dev->stateless_dec.m2m_dev);
2146 media_device_cleanup(&dev->mdev);
2149 video_unregister_device(&dev->stateful_enc.vfd);
2150 video_unregister_device(&dev->stateful_dec.vfd);
2151 video_unregister_device(&dev->stateless_dec.vfd);
2152 v4l2_device_put(&dev->v4l2_dev);
2157 static struct platform_driver vicodec_pdrv = {
2158 .probe = vicodec_probe,
2159 .remove = vicodec_remove,
2161 .name = VICODEC_NAME,
2165 static void __exit vicodec_exit(void)
2167 platform_driver_unregister(&vicodec_pdrv);
2168 platform_device_unregister(&vicodec_pdev);
2171 static int __init vicodec_init(void)
2175 ret = platform_device_register(&vicodec_pdev);
2179 ret = platform_driver_register(&vicodec_pdrv);
2181 platform_device_unregister(&vicodec_pdev);
2186 module_init(vicodec_init);
2187 module_exit(vicodec_exit);