cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vicodec-core.c (62029B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * A virtual codec example device.
      4 *
      5 * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
      6 *
      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.
     10 */
     11
     12#include <linux/module.h>
     13#include <linux/delay.h>
     14#include <linux/fs.h>
     15#include <linux/sched.h>
     16#include <linux/slab.h>
     17
     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>
     25
     26#include "codec-v4l2-fwht.h"
     27
     28MODULE_DESCRIPTION("Virtual codec device");
     29MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
     30MODULE_LICENSE("GPL v2");
     31
     32static bool multiplanar;
     33module_param(multiplanar, bool, 0444);
     34MODULE_PARM_DESC(multiplanar,
     35		 " use multi-planar API instead of single-planar API");
     36
     37static unsigned int debug;
     38module_param(debug, uint, 0644);
     39MODULE_PARM_DESC(debug, " activates debug info");
     40
     41#define VICODEC_NAME		"vicodec"
     42#define MAX_WIDTH		4096U
     43#define MIN_WIDTH		640U
     44#define MAX_HEIGHT		2160U
     45#define MIN_HEIGHT		360U
     46
     47#define dprintk(dev, fmt, arg...) \
     48	v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
     49
     50
     51struct pixfmt_info {
     52	u32 id;
     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;
     61};
     62
     63static const struct v4l2_fwht_pixfmt_info pixfmt_fwht = {
     64	V4L2_PIX_FMT_FWHT, 0, 3, 1, 1, 1, 1, 1, 0, 1
     65};
     66
     67static const struct v4l2_fwht_pixfmt_info pixfmt_stateless_fwht = {
     68	V4L2_PIX_FMT_FWHT_STATELESS, 0, 3, 1, 1, 1, 1, 1, 0, 1
     69};
     70
     71static void vicodec_dev_release(struct device *dev)
     72{
     73}
     74
     75static struct platform_device vicodec_pdev = {
     76	.name		= VICODEC_NAME,
     77	.dev.release	= vicodec_dev_release,
     78};
     79
     80/* Per-queue, driver-specific private data */
     81struct vicodec_q_data {
     82	unsigned int		coded_width;
     83	unsigned int		coded_height;
     84	unsigned int		visible_width;
     85	unsigned int		visible_height;
     86	unsigned int		sizeimage;
     87	unsigned int		vb2_sizeimage;
     88	unsigned int		sequence;
     89	const struct v4l2_fwht_pixfmt_info *info;
     90};
     91
     92enum {
     93	V4L2_M2M_SRC = 0,
     94	V4L2_M2M_DST = 1,
     95};
     96
     97struct vicodec_dev_instance {
     98	struct video_device     vfd;
     99	struct mutex            mutex;
    100	spinlock_t              lock;
    101	struct v4l2_m2m_dev     *m2m_dev;
    102};
    103
    104struct vicodec_dev {
    105	struct v4l2_device	v4l2_dev;
    106	struct vicodec_dev_instance stateful_enc;
    107	struct vicodec_dev_instance stateful_dec;
    108	struct vicodec_dev_instance stateless_dec;
    109#ifdef CONFIG_MEDIA_CONTROLLER
    110	struct media_device	mdev;
    111#endif
    112
    113};
    114
    115struct vicodec_ctx {
    116	struct v4l2_fh		fh;
    117	struct vicodec_dev	*dev;
    118	bool			is_enc;
    119	bool			is_stateless;
    120	spinlock_t		*lock;
    121
    122	struct v4l2_ctrl_handler hdl;
    123
    124	/* Source and destination queue data */
    125	struct vicodec_q_data   q_data[2];
    126	struct v4l2_fwht_state	state;
    127
    128	u32			cur_buf_offset;
    129	u32			comp_max_size;
    130	u32			comp_size;
    131	u32			header_size;
    132	u32			comp_magic_cnt;
    133	bool			comp_has_frame;
    134	bool			comp_has_next_frame;
    135	bool			first_source_change_sent;
    136	bool			source_changed;
    137};
    138
    139static const struct v4l2_event vicodec_eos_event = {
    140	.type = V4L2_EVENT_EOS
    141};
    142
    143static inline struct vicodec_ctx *file2ctx(struct file *file)
    144{
    145	return container_of(file->private_data, struct vicodec_ctx, fh);
    146}
    147
    148static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx,
    149					 enum v4l2_buf_type type)
    150{
    151	switch (type) {
    152	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
    153	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
    154		return &ctx->q_data[V4L2_M2M_SRC];
    155	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
    156	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
    157		return &ctx->q_data[V4L2_M2M_DST];
    158	default:
    159		break;
    160	}
    161	return NULL;
    162}
    163
    164static void copy_cap_to_ref(const u8 *cap, const struct v4l2_fwht_pixfmt_info *info,
    165		struct v4l2_fwht_state *state)
    166{
    167	int plane_idx;
    168	u8 *p_ref = state->ref_frame.buf;
    169	unsigned int cap_stride = state->stride;
    170	unsigned int ref_stride = state->ref_stride;
    171
    172	for (plane_idx = 0; plane_idx < info->planes_num; plane_idx++) {
    173		int i;
    174		unsigned int h_div = (plane_idx == 1 || plane_idx == 2) ?
    175			info->height_div : 1;
    176		const u8 *row_cap = cap;
    177		u8 *row_ref = p_ref;
    178
    179		if (info->planes_num == 3 && plane_idx == 1) {
    180			cap_stride /= 2;
    181			ref_stride /= 2;
    182		}
    183
    184		if (plane_idx == 1 &&
    185		    (info->id == V4L2_PIX_FMT_NV24 ||
    186		     info->id == V4L2_PIX_FMT_NV42)) {
    187			cap_stride *= 2;
    188			ref_stride *= 2;
    189		}
    190
    191		for (i = 0; i < state->visible_height / h_div; i++) {
    192			memcpy(row_ref, row_cap, ref_stride);
    193			row_ref += ref_stride;
    194			row_cap += cap_stride;
    195		}
    196		cap += cap_stride * (state->coded_height / h_div);
    197		p_ref += ref_stride * (state->coded_height / h_div);
    198	}
    199}
    200
    201static bool validate_by_version(unsigned int flags, unsigned int version)
    202{
    203	if (!version || version > V4L2_FWHT_VERSION)
    204		return false;
    205
    206	if (version >= 2) {
    207		unsigned int components_num = 1 +
    208			((flags & V4L2_FWHT_FL_COMPONENTS_NUM_MSK) >>
    209			 V4L2_FWHT_FL_COMPONENTS_NUM_OFFSET);
    210		unsigned int pixenc = flags & V4L2_FWHT_FL_PIXENC_MSK;
    211
    212		if (components_num == 0 || components_num > 4 || !pixenc)
    213			return false;
    214	}
    215	return true;
    216}
    217
    218static bool validate_stateless_params_flags(const struct v4l2_ctrl_fwht_params *params,
    219					    const struct v4l2_fwht_pixfmt_info *cur_info)
    220{
    221	unsigned int width_div =
    222		(params->flags & V4L2_FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
    223	unsigned int height_div =
    224		(params->flags & V4L2_FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
    225	unsigned int components_num = 3;
    226	unsigned int pixenc = 0;
    227
    228	if (params->version < 3)
    229		return false;
    230
    231	components_num = 1 + ((params->flags & V4L2_FWHT_FL_COMPONENTS_NUM_MSK) >>
    232			      V4L2_FWHT_FL_COMPONENTS_NUM_OFFSET);
    233	pixenc = (params->flags & V4L2_FWHT_FL_PIXENC_MSK);
    234	if (v4l2_fwht_validate_fmt(cur_info, width_div, height_div,
    235				    components_num, pixenc))
    236		return true;
    237	return false;
    238}
    239
    240
    241static void update_state_from_header(struct vicodec_ctx *ctx)
    242{
    243	const struct fwht_cframe_hdr *p_hdr = &ctx->state.header;
    244
    245	ctx->state.visible_width = ntohl(p_hdr->width);
    246	ctx->state.visible_height = ntohl(p_hdr->height);
    247	ctx->state.colorspace = ntohl(p_hdr->colorspace);
    248	ctx->state.xfer_func = ntohl(p_hdr->xfer_func);
    249	ctx->state.ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
    250	ctx->state.quantization = ntohl(p_hdr->quantization);
    251}
    252
    253static int device_process(struct vicodec_ctx *ctx,
    254			  struct vb2_v4l2_buffer *src_vb,
    255			  struct vb2_v4l2_buffer *dst_vb)
    256{
    257	struct vicodec_dev *dev = ctx->dev;
    258	struct v4l2_fwht_state *state = &ctx->state;
    259	u8 *p_src, *p_dst;
    260	int ret = 0;
    261
    262	if (ctx->is_enc || ctx->is_stateless)
    263		p_src = vb2_plane_vaddr(&src_vb->vb2_buf, 0);
    264	else
    265		p_src = state->compressed_frame;
    266
    267	if (ctx->is_stateless) {
    268		struct media_request *src_req = src_vb->vb2_buf.req_obj.req;
    269
    270		ret = v4l2_ctrl_request_setup(src_req, &ctx->hdl);
    271		if (ret)
    272			return ret;
    273		update_state_from_header(ctx);
    274
    275		ctx->state.header.size =
    276			htonl(vb2_get_plane_payload(&src_vb->vb2_buf, 0));
    277		/*
    278		 * set the reference buffer from the reference timestamp
    279		 * only if this is a P-frame
    280		 */
    281		if (!(ntohl(ctx->state.header.flags) & V4L2_FWHT_FL_I_FRAME)) {
    282			struct vb2_buffer *ref_vb2_buf;
    283			int ref_buf_idx;
    284			struct vb2_queue *vq_cap =
    285				v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
    286						V4L2_BUF_TYPE_VIDEO_CAPTURE);
    287
    288			ref_buf_idx = vb2_find_timestamp(vq_cap,
    289							 ctx->state.ref_frame_ts, 0);
    290			if (ref_buf_idx < 0)
    291				return -EINVAL;
    292
    293			ref_vb2_buf = vq_cap->bufs[ref_buf_idx];
    294			if (ref_vb2_buf->state == VB2_BUF_STATE_ERROR)
    295				ret = -EINVAL;
    296			ctx->state.ref_frame.buf =
    297				vb2_plane_vaddr(ref_vb2_buf, 0);
    298		} else {
    299			ctx->state.ref_frame.buf = NULL;
    300		}
    301	}
    302	p_dst = vb2_plane_vaddr(&dst_vb->vb2_buf, 0);
    303	if (!p_src || !p_dst) {
    304		v4l2_err(&dev->v4l2_dev,
    305			 "Acquiring kernel pointers to buffers failed\n");
    306		return -EFAULT;
    307	}
    308
    309	if (ctx->is_enc) {
    310		struct vicodec_q_data *q_src;
    311		int comp_sz_or_errcode;
    312
    313		q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
    314		state->info = q_src->info;
    315		comp_sz_or_errcode = v4l2_fwht_encode(state, p_src, p_dst);
    316		if (comp_sz_or_errcode < 0)
    317			return comp_sz_or_errcode;
    318		vb2_set_plane_payload(&dst_vb->vb2_buf, 0, comp_sz_or_errcode);
    319	} else {
    320		struct vicodec_q_data *q_dst;
    321		unsigned int comp_frame_size = ntohl(ctx->state.header.size);
    322
    323		q_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
    324		if (comp_frame_size > ctx->comp_max_size)
    325			return -EINVAL;
    326		state->info = q_dst->info;
    327		ret = v4l2_fwht_decode(state, p_src, p_dst);
    328		if (ret < 0)
    329			return ret;
    330		if (!ctx->is_stateless)
    331			copy_cap_to_ref(p_dst, ctx->state.info, &ctx->state);
    332
    333		vb2_set_plane_payload(&dst_vb->vb2_buf, 0, q_dst->sizeimage);
    334		if (ntohl(ctx->state.header.flags) & V4L2_FWHT_FL_I_FRAME)
    335			dst_vb->flags |= V4L2_BUF_FLAG_KEYFRAME;
    336		else
    337			dst_vb->flags |= V4L2_BUF_FLAG_PFRAME;
    338	}
    339	return ret;
    340}
    341
    342/*
    343 * mem2mem callbacks
    344 */
    345static enum vb2_buffer_state get_next_header(struct vicodec_ctx *ctx,
    346					     u8 **pp, u32 sz)
    347{
    348	static const u8 magic[] = {
    349		0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
    350	};
    351	u8 *p = *pp;
    352	u32 state;
    353	u8 *header = (u8 *)&ctx->state.header;
    354
    355	state = VB2_BUF_STATE_DONE;
    356
    357	if (!ctx->header_size) {
    358		state = VB2_BUF_STATE_ERROR;
    359		for (; p < *pp + sz; p++) {
    360			u32 copy;
    361
    362			p = memchr(p, magic[ctx->comp_magic_cnt],
    363				   *pp + sz - p);
    364			if (!p) {
    365				ctx->comp_magic_cnt = 0;
    366				p = *pp + sz;
    367				break;
    368			}
    369			copy = sizeof(magic) - ctx->comp_magic_cnt;
    370			if (*pp + sz - p < copy)
    371				copy = *pp + sz - p;
    372
    373			memcpy(header + ctx->comp_magic_cnt, p, copy);
    374			ctx->comp_magic_cnt += copy;
    375			if (!memcmp(header, magic, ctx->comp_magic_cnt)) {
    376				p += copy;
    377				state = VB2_BUF_STATE_DONE;
    378				break;
    379			}
    380			ctx->comp_magic_cnt = 0;
    381		}
    382		if (ctx->comp_magic_cnt < sizeof(magic)) {
    383			*pp = p;
    384			return state;
    385		}
    386		ctx->header_size = sizeof(magic);
    387	}
    388
    389	if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
    390		u32 copy = sizeof(struct fwht_cframe_hdr) - ctx->header_size;
    391
    392		if (*pp + sz - p < copy)
    393			copy = *pp + sz - p;
    394
    395		memcpy(header + ctx->header_size, p, copy);
    396		p += copy;
    397		ctx->header_size += copy;
    398	}
    399	*pp = p;
    400	return state;
    401}
    402
    403/* device_run() - prepares and starts the device */
    404static void device_run(void *priv)
    405{
    406	struct vicodec_ctx *ctx = priv;
    407	struct vicodec_dev *dev = ctx->dev;
    408	struct vb2_v4l2_buffer *src_buf, *dst_buf;
    409	struct vicodec_q_data *q_src, *q_dst;
    410	u32 state;
    411	struct media_request *src_req;
    412
    413	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
    414	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
    415	src_req = src_buf->vb2_buf.req_obj.req;
    416
    417	q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
    418	q_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
    419
    420	state = VB2_BUF_STATE_DONE;
    421	if (device_process(ctx, src_buf, dst_buf))
    422		state = VB2_BUF_STATE_ERROR;
    423	else
    424		dst_buf->sequence = q_dst->sequence++;
    425	dst_buf->flags &= ~V4L2_BUF_FLAG_LAST;
    426	v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
    427
    428	spin_lock(ctx->lock);
    429	if (!ctx->comp_has_next_frame &&
    430	    v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) {
    431		dst_buf->flags |= V4L2_BUF_FLAG_LAST;
    432		v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
    433		v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);
    434	}
    435	if (ctx->is_enc || ctx->is_stateless) {
    436		src_buf->sequence = q_src->sequence++;
    437		src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
    438		v4l2_m2m_buf_done(src_buf, state);
    439	} else if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == ctx->cur_buf_offset) {
    440		src_buf->sequence = q_src->sequence++;
    441		src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
    442		v4l2_m2m_buf_done(src_buf, state);
    443		ctx->cur_buf_offset = 0;
    444		ctx->comp_has_next_frame = false;
    445	}
    446	v4l2_m2m_buf_done(dst_buf, state);
    447
    448	ctx->comp_size = 0;
    449	ctx->header_size = 0;
    450	ctx->comp_magic_cnt = 0;
    451	ctx->comp_has_frame = false;
    452	spin_unlock(ctx->lock);
    453	if (ctx->is_stateless && src_req)
    454		v4l2_ctrl_request_complete(src_req, &ctx->hdl);
    455
    456	if (ctx->is_enc)
    457		v4l2_m2m_job_finish(dev->stateful_enc.m2m_dev, ctx->fh.m2m_ctx);
    458	else if (ctx->is_stateless)
    459		v4l2_m2m_job_finish(dev->stateless_dec.m2m_dev,
    460				    ctx->fh.m2m_ctx);
    461	else
    462		v4l2_m2m_job_finish(dev->stateful_dec.m2m_dev, ctx->fh.m2m_ctx);
    463}
    464
    465static void job_remove_src_buf(struct vicodec_ctx *ctx, u32 state)
    466{
    467	struct vb2_v4l2_buffer *src_buf;
    468	struct vicodec_q_data *q_src;
    469
    470	q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
    471	spin_lock(ctx->lock);
    472	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
    473	src_buf->sequence = q_src->sequence++;
    474	v4l2_m2m_buf_done(src_buf, state);
    475	ctx->cur_buf_offset = 0;
    476	spin_unlock(ctx->lock);
    477}
    478
    479static const struct v4l2_fwht_pixfmt_info *
    480info_from_header(const struct fwht_cframe_hdr *p_hdr)
    481{
    482	unsigned int flags = ntohl(p_hdr->flags);
    483	unsigned int width_div = (flags & V4L2_FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
    484	unsigned int height_div = (flags & V4L2_FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
    485	unsigned int components_num = 3;
    486	unsigned int pixenc = 0;
    487	unsigned int version = ntohl(p_hdr->version);
    488
    489	if (version >= 2) {
    490		components_num = 1 + ((flags & V4L2_FWHT_FL_COMPONENTS_NUM_MSK) >>
    491				V4L2_FWHT_FL_COMPONENTS_NUM_OFFSET);
    492		pixenc = (flags & V4L2_FWHT_FL_PIXENC_MSK);
    493	}
    494	return v4l2_fwht_find_nth_fmt(width_div, height_div,
    495				     components_num, pixenc, 0);
    496}
    497
    498static bool is_header_valid(const struct fwht_cframe_hdr *p_hdr)
    499{
    500	const struct v4l2_fwht_pixfmt_info *info;
    501	unsigned int w = ntohl(p_hdr->width);
    502	unsigned int h = ntohl(p_hdr->height);
    503	unsigned int version = ntohl(p_hdr->version);
    504	unsigned int flags = ntohl(p_hdr->flags);
    505
    506	if (w < MIN_WIDTH || w > MAX_WIDTH || h < MIN_HEIGHT || h > MAX_HEIGHT)
    507		return false;
    508
    509	if (!validate_by_version(flags, version))
    510		return false;
    511
    512	info = info_from_header(p_hdr);
    513	if (!info)
    514		return false;
    515	return true;
    516}
    517
    518static void update_capture_data_from_header(struct vicodec_ctx *ctx)
    519{
    520	struct vicodec_q_data *q_dst = get_q_data(ctx,
    521						  V4L2_BUF_TYPE_VIDEO_CAPTURE);
    522	const struct fwht_cframe_hdr *p_hdr = &ctx->state.header;
    523	const struct v4l2_fwht_pixfmt_info *info = info_from_header(p_hdr);
    524	unsigned int flags = ntohl(p_hdr->flags);
    525	unsigned int hdr_width_div = (flags & V4L2_FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
    526	unsigned int hdr_height_div = (flags & V4L2_FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
    527
    528	/*
    529	 * This function should not be used by a stateless codec since
    530	 * it changes values in q_data that are not request specific
    531	 */
    532	WARN_ON(ctx->is_stateless);
    533
    534	q_dst->info = info;
    535	q_dst->visible_width = ntohl(p_hdr->width);
    536	q_dst->visible_height = ntohl(p_hdr->height);
    537	q_dst->coded_width = vic_round_dim(q_dst->visible_width, hdr_width_div);
    538	q_dst->coded_height = vic_round_dim(q_dst->visible_height,
    539					    hdr_height_div);
    540
    541	q_dst->sizeimage = q_dst->coded_width * q_dst->coded_height *
    542		q_dst->info->sizeimage_mult / q_dst->info->sizeimage_div;
    543	ctx->state.colorspace = ntohl(p_hdr->colorspace);
    544
    545	ctx->state.xfer_func = ntohl(p_hdr->xfer_func);
    546	ctx->state.ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
    547	ctx->state.quantization = ntohl(p_hdr->quantization);
    548}
    549
    550static void set_last_buffer(struct vb2_v4l2_buffer *dst_buf,
    551			    const struct vb2_v4l2_buffer *src_buf,
    552			    struct vicodec_ctx *ctx)
    553{
    554	struct vicodec_q_data *q_dst = get_q_data(ctx,
    555						  V4L2_BUF_TYPE_VIDEO_CAPTURE);
    556
    557	vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0);
    558	dst_buf->sequence = q_dst->sequence++;
    559
    560	v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, !ctx->is_enc);
    561	dst_buf->flags |= V4L2_BUF_FLAG_LAST;
    562	v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
    563}
    564
    565static int job_ready(void *priv)
    566{
    567	static const u8 magic[] = {
    568		0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
    569	};
    570	struct vicodec_ctx *ctx = priv;
    571	struct vb2_v4l2_buffer *src_buf;
    572	u8 *p_src;
    573	u8 *p;
    574	u32 sz;
    575	u32 state;
    576	struct vicodec_q_data *q_dst = get_q_data(ctx,
    577						  V4L2_BUF_TYPE_VIDEO_CAPTURE);
    578	unsigned int flags;
    579	unsigned int hdr_width_div;
    580	unsigned int hdr_height_div;
    581	unsigned int max_to_copy;
    582	unsigned int comp_frame_size;
    583
    584	if (ctx->source_changed)
    585		return 0;
    586	if (ctx->is_stateless || ctx->is_enc || ctx->comp_has_frame)
    587		return 1;
    588
    589restart:
    590	ctx->comp_has_next_frame = false;
    591	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
    592	if (!src_buf)
    593		return 0;
    594	p_src = vb2_plane_vaddr(&src_buf->vb2_buf, 0);
    595	sz = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
    596	p = p_src + ctx->cur_buf_offset;
    597
    598	state = VB2_BUF_STATE_DONE;
    599
    600	if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
    601		state = get_next_header(ctx, &p, p_src + sz - p);
    602		if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
    603			if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx,
    604							      src_buf))
    605				return 1;
    606			job_remove_src_buf(ctx, state);
    607			goto restart;
    608		}
    609	}
    610
    611	comp_frame_size = ntohl(ctx->state.header.size);
    612
    613	/*
    614	 * The current scanned frame might be the first frame of a new
    615	 * resolution so its size might be larger than ctx->comp_max_size.
    616	 * In that case it is copied up to the current buffer capacity and
    617	 * the copy will continue after allocating new large enough buffer
    618	 * when restreaming
    619	 */
    620	max_to_copy = min(comp_frame_size, ctx->comp_max_size);
    621
    622	if (ctx->comp_size < max_to_copy) {
    623		u32 copy = max_to_copy - ctx->comp_size;
    624
    625		if (copy > p_src + sz - p)
    626			copy = p_src + sz - p;
    627
    628		memcpy(ctx->state.compressed_frame + ctx->comp_size,
    629		       p, copy);
    630		p += copy;
    631		ctx->comp_size += copy;
    632		if (ctx->comp_size < max_to_copy) {
    633			if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx,
    634							      src_buf))
    635				return 1;
    636			job_remove_src_buf(ctx, state);
    637			goto restart;
    638		}
    639	}
    640	ctx->cur_buf_offset = p - p_src;
    641	if (ctx->comp_size == comp_frame_size)
    642		ctx->comp_has_frame = true;
    643	ctx->comp_has_next_frame = false;
    644	if (ctx->comp_has_frame && sz - ctx->cur_buf_offset >=
    645			sizeof(struct fwht_cframe_hdr)) {
    646		struct fwht_cframe_hdr *p_hdr = (struct fwht_cframe_hdr *)p;
    647		u32 frame_size = ntohl(p_hdr->size);
    648		u32 remaining = sz - ctx->cur_buf_offset - sizeof(*p_hdr);
    649
    650		if (!memcmp(p, magic, sizeof(magic)))
    651			ctx->comp_has_next_frame = remaining >= frame_size;
    652	}
    653	/*
    654	 * if the header is invalid the device_run will just drop the frame
    655	 * with an error
    656	 */
    657	if (!is_header_valid(&ctx->state.header) && ctx->comp_has_frame)
    658		return 1;
    659	flags = ntohl(ctx->state.header.flags);
    660	hdr_width_div = (flags & V4L2_FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
    661	hdr_height_div = (flags & V4L2_FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
    662
    663	if (ntohl(ctx->state.header.width) != q_dst->visible_width ||
    664	    ntohl(ctx->state.header.height) != q_dst->visible_height ||
    665	    !q_dst->info ||
    666	    hdr_width_div != q_dst->info->width_div ||
    667	    hdr_height_div != q_dst->info->height_div) {
    668		static const struct v4l2_event rs_event = {
    669			.type = V4L2_EVENT_SOURCE_CHANGE,
    670			.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
    671		};
    672
    673		struct vb2_v4l2_buffer *dst_buf =
    674			v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
    675
    676		update_capture_data_from_header(ctx);
    677		v4l2_event_queue_fh(&ctx->fh, &rs_event);
    678		set_last_buffer(dst_buf, src_buf, ctx);
    679		ctx->source_changed = true;
    680		return 0;
    681	}
    682	return 1;
    683}
    684
    685/*
    686 * video ioctls
    687 */
    688
    689static const struct v4l2_fwht_pixfmt_info *find_fmt(u32 fmt)
    690{
    691	const struct v4l2_fwht_pixfmt_info *info =
    692		v4l2_fwht_find_pixfmt(fmt);
    693
    694	if (!info)
    695		info = v4l2_fwht_get_pixfmt(0);
    696	return info;
    697}
    698
    699static int vidioc_querycap(struct file *file, void *priv,
    700			   struct v4l2_capability *cap)
    701{
    702	strscpy(cap->driver, VICODEC_NAME, sizeof(cap->driver));
    703	strscpy(cap->card, VICODEC_NAME, sizeof(cap->card));
    704	snprintf(cap->bus_info, sizeof(cap->bus_info),
    705			"platform:%s", VICODEC_NAME);
    706	return 0;
    707}
    708
    709static int enum_fmt(struct v4l2_fmtdesc *f, struct vicodec_ctx *ctx,
    710		    bool is_out)
    711{
    712	bool is_uncomp = (ctx->is_enc && is_out) || (!ctx->is_enc && !is_out);
    713
    714	if (V4L2_TYPE_IS_MULTIPLANAR(f->type) && !multiplanar)
    715		return -EINVAL;
    716	if (!V4L2_TYPE_IS_MULTIPLANAR(f->type) && multiplanar)
    717		return -EINVAL;
    718
    719	if (is_uncomp) {
    720		const struct v4l2_fwht_pixfmt_info *info =
    721					get_q_data(ctx, f->type)->info;
    722
    723		if (ctx->is_enc ||
    724		    !vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q))
    725			info = v4l2_fwht_get_pixfmt(f->index);
    726		else
    727			info = v4l2_fwht_find_nth_fmt(info->width_div,
    728						     info->height_div,
    729						     info->components_num,
    730						     info->pixenc,
    731						     f->index);
    732		if (!info)
    733			return -EINVAL;
    734		f->pixelformat = info->id;
    735	} else {
    736		if (f->index)
    737			return -EINVAL;
    738		f->pixelformat = ctx->is_stateless ?
    739			V4L2_PIX_FMT_FWHT_STATELESS : V4L2_PIX_FMT_FWHT;
    740		if (!ctx->is_enc && !ctx->is_stateless)
    741			f->flags = V4L2_FMT_FLAG_DYN_RESOLUTION |
    742				   V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM;
    743	}
    744	return 0;
    745}
    746
    747static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
    748				   struct v4l2_fmtdesc *f)
    749{
    750	struct vicodec_ctx *ctx = file2ctx(file);
    751
    752	return enum_fmt(f, ctx, false);
    753}
    754
    755static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
    756				   struct v4l2_fmtdesc *f)
    757{
    758	struct vicodec_ctx *ctx = file2ctx(file);
    759
    760	return enum_fmt(f, ctx, true);
    761}
    762
    763static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
    764{
    765	struct vb2_queue *vq;
    766	struct vicodec_q_data *q_data;
    767	struct v4l2_pix_format_mplane *pix_mp;
    768	struct v4l2_pix_format *pix;
    769	const struct v4l2_fwht_pixfmt_info *info;
    770
    771	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
    772	if (!vq)
    773		return -EINVAL;
    774
    775	q_data = get_q_data(ctx, f->type);
    776	info = q_data->info;
    777
    778	switch (f->type) {
    779	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
    780	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
    781		if (multiplanar)
    782			return -EINVAL;
    783		pix = &f->fmt.pix;
    784		pix->width = q_data->coded_width;
    785		pix->height = q_data->coded_height;
    786		pix->field = V4L2_FIELD_NONE;
    787		pix->pixelformat = info->id;
    788		pix->bytesperline = q_data->coded_width *
    789					info->bytesperline_mult;
    790		pix->sizeimage = q_data->sizeimage;
    791		pix->colorspace = ctx->state.colorspace;
    792		pix->xfer_func = ctx->state.xfer_func;
    793		pix->ycbcr_enc = ctx->state.ycbcr_enc;
    794		pix->quantization = ctx->state.quantization;
    795		break;
    796
    797	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
    798	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
    799		if (!multiplanar)
    800			return -EINVAL;
    801		pix_mp = &f->fmt.pix_mp;
    802		pix_mp->width = q_data->coded_width;
    803		pix_mp->height = q_data->coded_height;
    804		pix_mp->field = V4L2_FIELD_NONE;
    805		pix_mp->pixelformat = info->id;
    806		pix_mp->num_planes = 1;
    807		pix_mp->plane_fmt[0].bytesperline =
    808				q_data->coded_width * info->bytesperline_mult;
    809		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage;
    810		pix_mp->colorspace = ctx->state.colorspace;
    811		pix_mp->xfer_func = ctx->state.xfer_func;
    812		pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
    813		pix_mp->quantization = ctx->state.quantization;
    814		break;
    815	default:
    816		return -EINVAL;
    817	}
    818	return 0;
    819}
    820
    821static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
    822				struct v4l2_format *f)
    823{
    824	return vidioc_g_fmt(file2ctx(file), f);
    825}
    826
    827static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
    828				struct v4l2_format *f)
    829{
    830	return vidioc_g_fmt(file2ctx(file), f);
    831}
    832
    833static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
    834{
    835	struct v4l2_pix_format_mplane *pix_mp;
    836	struct v4l2_pix_format *pix;
    837	struct v4l2_plane_pix_format *plane;
    838	const struct v4l2_fwht_pixfmt_info *info = ctx->is_stateless ?
    839		&pixfmt_stateless_fwht : &pixfmt_fwht;
    840
    841	switch (f->type) {
    842	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
    843	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
    844		pix = &f->fmt.pix;
    845		if (pix->pixelformat != V4L2_PIX_FMT_FWHT &&
    846		    pix->pixelformat != V4L2_PIX_FMT_FWHT_STATELESS)
    847			info = find_fmt(pix->pixelformat);
    848
    849		pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH);
    850		pix->width = vic_round_dim(pix->width, info->width_div);
    851
    852		pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT);
    853		pix->height = vic_round_dim(pix->height, info->height_div);
    854
    855		pix->field = V4L2_FIELD_NONE;
    856		pix->bytesperline =
    857			pix->width * info->bytesperline_mult;
    858		pix->sizeimage = pix->width * pix->height *
    859			info->sizeimage_mult / info->sizeimage_div;
    860		if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
    861			pix->sizeimage += sizeof(struct fwht_cframe_hdr);
    862		break;
    863	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
    864	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
    865		pix_mp = &f->fmt.pix_mp;
    866		plane = pix_mp->plane_fmt;
    867		if (pix_mp->pixelformat != V4L2_PIX_FMT_FWHT &&
    868		    pix_mp->pixelformat != V4L2_PIX_FMT_FWHT_STATELESS)
    869			info = find_fmt(pix_mp->pixelformat);
    870		pix_mp->num_planes = 1;
    871
    872		pix_mp->width = clamp(pix_mp->width, MIN_WIDTH, MAX_WIDTH);
    873		pix_mp->width = vic_round_dim(pix_mp->width, info->width_div);
    874
    875		pix_mp->height = clamp(pix_mp->height, MIN_HEIGHT, MAX_HEIGHT);
    876		pix_mp->height = vic_round_dim(pix_mp->height,
    877					       info->height_div);
    878
    879		pix_mp->field = V4L2_FIELD_NONE;
    880		plane->bytesperline =
    881			pix_mp->width * info->bytesperline_mult;
    882		plane->sizeimage = pix_mp->width * pix_mp->height *
    883			info->sizeimage_mult / info->sizeimage_div;
    884		if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
    885			plane->sizeimage += sizeof(struct fwht_cframe_hdr);
    886		break;
    887	default:
    888		return -EINVAL;
    889	}
    890
    891	return 0;
    892}
    893
    894static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
    895				  struct v4l2_format *f)
    896{
    897	struct vicodec_ctx *ctx = file2ctx(file);
    898	struct v4l2_pix_format_mplane *pix_mp;
    899	struct v4l2_pix_format *pix;
    900
    901	switch (f->type) {
    902	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
    903		if (multiplanar)
    904			return -EINVAL;
    905		pix = &f->fmt.pix;
    906		pix->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
    907				   find_fmt(f->fmt.pix.pixelformat)->id;
    908		pix->colorspace = ctx->state.colorspace;
    909		pix->xfer_func = ctx->state.xfer_func;
    910		pix->ycbcr_enc = ctx->state.ycbcr_enc;
    911		pix->quantization = ctx->state.quantization;
    912		break;
    913	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
    914		if (!multiplanar)
    915			return -EINVAL;
    916		pix_mp = &f->fmt.pix_mp;
    917		pix_mp->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
    918				      find_fmt(pix_mp->pixelformat)->id;
    919		pix_mp->colorspace = ctx->state.colorspace;
    920		pix_mp->xfer_func = ctx->state.xfer_func;
    921		pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
    922		pix_mp->quantization = ctx->state.quantization;
    923		break;
    924	default:
    925		return -EINVAL;
    926	}
    927
    928	return vidioc_try_fmt(ctx, f);
    929}
    930
    931static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
    932				  struct v4l2_format *f)
    933{
    934	struct vicodec_ctx *ctx = file2ctx(file);
    935	struct v4l2_pix_format_mplane *pix_mp;
    936	struct v4l2_pix_format *pix;
    937
    938	switch (f->type) {
    939	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
    940		if (multiplanar)
    941			return -EINVAL;
    942		pix = &f->fmt.pix;
    943		if (ctx->is_enc)
    944			pix->pixelformat = find_fmt(pix->pixelformat)->id;
    945		else if (ctx->is_stateless)
    946			pix->pixelformat = V4L2_PIX_FMT_FWHT_STATELESS;
    947		else
    948			pix->pixelformat = V4L2_PIX_FMT_FWHT;
    949		if (!pix->colorspace)
    950			pix->colorspace = V4L2_COLORSPACE_REC709;
    951		break;
    952	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
    953		if (!multiplanar)
    954			return -EINVAL;
    955		pix_mp = &f->fmt.pix_mp;
    956		if (ctx->is_enc)
    957			pix_mp->pixelformat = find_fmt(pix_mp->pixelformat)->id;
    958		else if (ctx->is_stateless)
    959			pix_mp->pixelformat = V4L2_PIX_FMT_FWHT_STATELESS;
    960		else
    961			pix_mp->pixelformat = V4L2_PIX_FMT_FWHT;
    962		if (!pix_mp->colorspace)
    963			pix_mp->colorspace = V4L2_COLORSPACE_REC709;
    964		break;
    965	default:
    966		return -EINVAL;
    967	}
    968
    969	return vidioc_try_fmt(ctx, f);
    970}
    971
    972static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
    973{
    974	struct vicodec_q_data *q_data;
    975	struct vb2_queue *vq;
    976	bool fmt_changed = true;
    977	struct v4l2_pix_format_mplane *pix_mp;
    978	struct v4l2_pix_format *pix;
    979
    980	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
    981	if (!vq)
    982		return -EINVAL;
    983
    984	q_data = get_q_data(ctx, f->type);
    985	if (!q_data)
    986		return -EINVAL;
    987
    988	switch (f->type) {
    989	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
    990	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
    991		pix = &f->fmt.pix;
    992		if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
    993			fmt_changed =
    994				!q_data->info ||
    995				q_data->info->id != pix->pixelformat ||
    996				q_data->coded_width != pix->width ||
    997				q_data->coded_height != pix->height;
    998
    999		if (vb2_is_busy(vq) && fmt_changed)
   1000			return -EBUSY;
   1001
   1002		if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
   1003			q_data->info = &pixfmt_fwht;
   1004		else if (pix->pixelformat == V4L2_PIX_FMT_FWHT_STATELESS)
   1005			q_data->info = &pixfmt_stateless_fwht;
   1006		else
   1007			q_data->info = find_fmt(pix->pixelformat);
   1008		q_data->coded_width = pix->width;
   1009		q_data->coded_height = pix->height;
   1010		q_data->sizeimage = pix->sizeimage;
   1011		break;
   1012	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
   1013	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
   1014		pix_mp = &f->fmt.pix_mp;
   1015		if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
   1016			fmt_changed =
   1017				!q_data->info ||
   1018				q_data->info->id != pix_mp->pixelformat ||
   1019				q_data->coded_width != pix_mp->width ||
   1020				q_data->coded_height != pix_mp->height;
   1021
   1022		if (vb2_is_busy(vq) && fmt_changed)
   1023			return -EBUSY;
   1024
   1025		if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
   1026			q_data->info = &pixfmt_fwht;
   1027		else if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT_STATELESS)
   1028			q_data->info = &pixfmt_stateless_fwht;
   1029		else
   1030			q_data->info = find_fmt(pix_mp->pixelformat);
   1031		q_data->coded_width = pix_mp->width;
   1032		q_data->coded_height = pix_mp->height;
   1033		q_data->sizeimage = pix_mp->plane_fmt[0].sizeimage;
   1034		break;
   1035	default:
   1036		return -EINVAL;
   1037	}
   1038
   1039	dprintk(ctx->dev,
   1040		"Setting format for type %d, coded wxh: %dx%d, fourcc: 0x%08x\n",
   1041		f->type, q_data->coded_width, q_data->coded_height,
   1042		q_data->info->id);
   1043
   1044	return 0;
   1045}
   1046
   1047static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
   1048				struct v4l2_format *f)
   1049{
   1050	int ret;
   1051
   1052	ret = vidioc_try_fmt_vid_cap(file, priv, f);
   1053	if (ret)
   1054		return ret;
   1055
   1056	return vidioc_s_fmt(file2ctx(file), f);
   1057}
   1058
   1059static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
   1060				struct v4l2_format *f)
   1061{
   1062	struct vicodec_ctx *ctx = file2ctx(file);
   1063	struct vicodec_q_data *q_data;
   1064	struct vicodec_q_data *q_data_cap;
   1065	struct v4l2_pix_format *pix;
   1066	struct v4l2_pix_format_mplane *pix_mp;
   1067	u32 coded_w = 0, coded_h = 0;
   1068	unsigned int size = 0;
   1069	int ret;
   1070
   1071	q_data = get_q_data(ctx, f->type);
   1072	q_data_cap = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
   1073
   1074	ret = vidioc_try_fmt_vid_out(file, priv, f);
   1075	if (ret)
   1076		return ret;
   1077
   1078	if (ctx->is_enc) {
   1079		struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
   1080		struct vb2_queue *vq_cap = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
   1081							   V4L2_BUF_TYPE_VIDEO_CAPTURE);
   1082		const struct v4l2_fwht_pixfmt_info *info = ctx->is_stateless ?
   1083			&pixfmt_stateless_fwht : &pixfmt_fwht;
   1084
   1085		if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
   1086			coded_w = f->fmt.pix.width;
   1087			coded_h = f->fmt.pix.height;
   1088		} else {
   1089			coded_w = f->fmt.pix_mp.width;
   1090			coded_h = f->fmt.pix_mp.height;
   1091		}
   1092		if (vb2_is_busy(vq) && (coded_w != q_data->coded_width ||
   1093					coded_h != q_data->coded_height))
   1094			return -EBUSY;
   1095		size = coded_w * coded_h *
   1096			info->sizeimage_mult / info->sizeimage_div;
   1097		if (!ctx->is_stateless)
   1098			size += sizeof(struct fwht_cframe_hdr);
   1099
   1100		if (vb2_is_busy(vq_cap) && size > q_data_cap->sizeimage)
   1101			return -EBUSY;
   1102	}
   1103
   1104	ret = vidioc_s_fmt(file2ctx(file), f);
   1105	if (!ret) {
   1106		if (ctx->is_enc) {
   1107			q_data->visible_width = coded_w;
   1108			q_data->visible_height = coded_h;
   1109			q_data_cap->coded_width = coded_w;
   1110			q_data_cap->coded_height = coded_h;
   1111			q_data_cap->sizeimage = size;
   1112		}
   1113
   1114		switch (f->type) {
   1115		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
   1116			pix = &f->fmt.pix;
   1117			ctx->state.colorspace = pix->colorspace;
   1118			ctx->state.xfer_func = pix->xfer_func;
   1119			ctx->state.ycbcr_enc = pix->ycbcr_enc;
   1120			ctx->state.quantization = pix->quantization;
   1121			break;
   1122		case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
   1123			pix_mp = &f->fmt.pix_mp;
   1124			ctx->state.colorspace = pix_mp->colorspace;
   1125			ctx->state.xfer_func = pix_mp->xfer_func;
   1126			ctx->state.ycbcr_enc = pix_mp->ycbcr_enc;
   1127			ctx->state.quantization = pix_mp->quantization;
   1128			break;
   1129		default:
   1130			break;
   1131		}
   1132	}
   1133	return ret;
   1134}
   1135
   1136static int vidioc_g_selection(struct file *file, void *priv,
   1137			      struct v4l2_selection *s)
   1138{
   1139	struct vicodec_ctx *ctx = file2ctx(file);
   1140	struct vicodec_q_data *q_data;
   1141
   1142	q_data = get_q_data(ctx, s->type);
   1143	if (!q_data)
   1144		return -EINVAL;
   1145	/*
   1146	 * encoder supports only cropping on the OUTPUT buffer
   1147	 * decoder supports only composing on the CAPTURE buffer
   1148	 */
   1149	if (ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
   1150		switch (s->target) {
   1151		case V4L2_SEL_TGT_CROP:
   1152			s->r.left = 0;
   1153			s->r.top = 0;
   1154			s->r.width = q_data->visible_width;
   1155			s->r.height = q_data->visible_height;
   1156			return 0;
   1157		case V4L2_SEL_TGT_CROP_DEFAULT:
   1158		case V4L2_SEL_TGT_CROP_BOUNDS:
   1159			s->r.left = 0;
   1160			s->r.top = 0;
   1161			s->r.width = q_data->coded_width;
   1162			s->r.height = q_data->coded_height;
   1163			return 0;
   1164		}
   1165	} else if (!ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
   1166		switch (s->target) {
   1167		case V4L2_SEL_TGT_COMPOSE:
   1168			s->r.left = 0;
   1169			s->r.top = 0;
   1170			s->r.width = q_data->visible_width;
   1171			s->r.height = q_data->visible_height;
   1172			return 0;
   1173		case V4L2_SEL_TGT_COMPOSE_DEFAULT:
   1174		case V4L2_SEL_TGT_COMPOSE_BOUNDS:
   1175			s->r.left = 0;
   1176			s->r.top = 0;
   1177			s->r.width = q_data->coded_width;
   1178			s->r.height = q_data->coded_height;
   1179			return 0;
   1180		}
   1181	}
   1182	return -EINVAL;
   1183}
   1184
   1185static int vidioc_s_selection(struct file *file, void *priv,
   1186			      struct v4l2_selection *s)
   1187{
   1188	struct vicodec_ctx *ctx = file2ctx(file);
   1189	struct vicodec_q_data *q_data;
   1190
   1191	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
   1192		return -EINVAL;
   1193
   1194	q_data = get_q_data(ctx, s->type);
   1195	if (!q_data)
   1196		return -EINVAL;
   1197
   1198	if (!ctx->is_enc || s->target != V4L2_SEL_TGT_CROP)
   1199		return -EINVAL;
   1200
   1201	s->r.left = 0;
   1202	s->r.top = 0;
   1203	q_data->visible_width = clamp(s->r.width, MIN_WIDTH,
   1204				      q_data->coded_width);
   1205	s->r.width = q_data->visible_width;
   1206	q_data->visible_height = clamp(s->r.height, MIN_HEIGHT,
   1207				       q_data->coded_height);
   1208	s->r.height = q_data->visible_height;
   1209	return 0;
   1210}
   1211
   1212static int vicodec_encoder_cmd(struct file *file, void *fh,
   1213			    struct v4l2_encoder_cmd *ec)
   1214{
   1215	struct vicodec_ctx *ctx = file2ctx(file);
   1216	int ret;
   1217
   1218	ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec);
   1219	if (ret < 0)
   1220		return ret;
   1221
   1222	if (!vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q) ||
   1223	    !vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q))
   1224		return 0;
   1225
   1226	ret = v4l2_m2m_ioctl_encoder_cmd(file, fh, ec);
   1227	if (ret < 0)
   1228		return ret;
   1229
   1230	if (ec->cmd == V4L2_ENC_CMD_STOP &&
   1231	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
   1232		v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
   1233
   1234	if (ec->cmd == V4L2_ENC_CMD_START &&
   1235	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
   1236		vb2_clear_last_buffer_dequeued(&ctx->fh.m2m_ctx->cap_q_ctx.q);
   1237
   1238	return 0;
   1239}
   1240
   1241static int vicodec_decoder_cmd(struct file *file, void *fh,
   1242			    struct v4l2_decoder_cmd *dc)
   1243{
   1244	struct vicodec_ctx *ctx = file2ctx(file);
   1245	int ret;
   1246
   1247	ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc);
   1248	if (ret < 0)
   1249		return ret;
   1250
   1251	if (!vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q) ||
   1252	    !vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q))
   1253		return 0;
   1254
   1255	ret = v4l2_m2m_ioctl_decoder_cmd(file, fh, dc);
   1256	if (ret < 0)
   1257		return ret;
   1258
   1259	if (dc->cmd == V4L2_DEC_CMD_STOP &&
   1260	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
   1261		v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
   1262
   1263	if (dc->cmd == V4L2_DEC_CMD_START &&
   1264	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
   1265		vb2_clear_last_buffer_dequeued(&ctx->fh.m2m_ctx->cap_q_ctx.q);
   1266
   1267	return 0;
   1268}
   1269
   1270static int vicodec_enum_framesizes(struct file *file, void *fh,
   1271				   struct v4l2_frmsizeenum *fsize)
   1272{
   1273	switch (fsize->pixel_format) {
   1274	case V4L2_PIX_FMT_FWHT_STATELESS:
   1275		break;
   1276	case V4L2_PIX_FMT_FWHT:
   1277		break;
   1278	default:
   1279		if (find_fmt(fsize->pixel_format)->id == fsize->pixel_format)
   1280			break;
   1281		return -EINVAL;
   1282	}
   1283
   1284	if (fsize->index)
   1285		return -EINVAL;
   1286
   1287	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
   1288
   1289	fsize->stepwise.min_width = MIN_WIDTH;
   1290	fsize->stepwise.max_width = MAX_WIDTH;
   1291	fsize->stepwise.step_width = 8;
   1292	fsize->stepwise.min_height = MIN_HEIGHT;
   1293	fsize->stepwise.max_height = MAX_HEIGHT;
   1294	fsize->stepwise.step_height = 8;
   1295
   1296	return 0;
   1297}
   1298
   1299static int vicodec_subscribe_event(struct v4l2_fh *fh,
   1300				const struct v4l2_event_subscription *sub)
   1301{
   1302	struct vicodec_ctx *ctx = container_of(fh, struct vicodec_ctx, fh);
   1303
   1304	switch (sub->type) {
   1305	case V4L2_EVENT_SOURCE_CHANGE:
   1306		if (ctx->is_enc)
   1307			return -EINVAL;
   1308		fallthrough;
   1309	case V4L2_EVENT_EOS:
   1310		if (ctx->is_stateless)
   1311			return -EINVAL;
   1312		return v4l2_event_subscribe(fh, sub, 0, NULL);
   1313	default:
   1314		return v4l2_ctrl_subscribe_event(fh, sub);
   1315	}
   1316}
   1317
   1318static const struct v4l2_ioctl_ops vicodec_ioctl_ops = {
   1319	.vidioc_querycap	= vidioc_querycap,
   1320
   1321	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
   1322	.vidioc_g_fmt_vid_cap	= vidioc_g_fmt_vid_cap,
   1323	.vidioc_try_fmt_vid_cap	= vidioc_try_fmt_vid_cap,
   1324	.vidioc_s_fmt_vid_cap	= vidioc_s_fmt_vid_cap,
   1325
   1326	.vidioc_g_fmt_vid_cap_mplane	= vidioc_g_fmt_vid_cap,
   1327	.vidioc_try_fmt_vid_cap_mplane	= vidioc_try_fmt_vid_cap,
   1328	.vidioc_s_fmt_vid_cap_mplane	= vidioc_s_fmt_vid_cap,
   1329
   1330	.vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
   1331	.vidioc_g_fmt_vid_out	= vidioc_g_fmt_vid_out,
   1332	.vidioc_try_fmt_vid_out	= vidioc_try_fmt_vid_out,
   1333	.vidioc_s_fmt_vid_out	= vidioc_s_fmt_vid_out,
   1334
   1335	.vidioc_g_fmt_vid_out_mplane	= vidioc_g_fmt_vid_out,
   1336	.vidioc_try_fmt_vid_out_mplane	= vidioc_try_fmt_vid_out,
   1337	.vidioc_s_fmt_vid_out_mplane	= vidioc_s_fmt_vid_out,
   1338
   1339	.vidioc_reqbufs		= v4l2_m2m_ioctl_reqbufs,
   1340	.vidioc_querybuf	= v4l2_m2m_ioctl_querybuf,
   1341	.vidioc_qbuf		= v4l2_m2m_ioctl_qbuf,
   1342	.vidioc_dqbuf		= v4l2_m2m_ioctl_dqbuf,
   1343	.vidioc_prepare_buf	= v4l2_m2m_ioctl_prepare_buf,
   1344	.vidioc_create_bufs	= v4l2_m2m_ioctl_create_bufs,
   1345	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
   1346
   1347	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
   1348	.vidioc_streamoff	= v4l2_m2m_ioctl_streamoff,
   1349
   1350	.vidioc_g_selection	= vidioc_g_selection,
   1351	.vidioc_s_selection	= vidioc_s_selection,
   1352
   1353	.vidioc_try_encoder_cmd	= v4l2_m2m_ioctl_try_encoder_cmd,
   1354	.vidioc_encoder_cmd	= vicodec_encoder_cmd,
   1355	.vidioc_try_decoder_cmd	= v4l2_m2m_ioctl_try_decoder_cmd,
   1356	.vidioc_decoder_cmd	= vicodec_decoder_cmd,
   1357	.vidioc_enum_framesizes = vicodec_enum_framesizes,
   1358
   1359	.vidioc_subscribe_event = vicodec_subscribe_event,
   1360	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
   1361};
   1362
   1363
   1364/*
   1365 * Queue operations
   1366 */
   1367
   1368static int vicodec_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
   1369			       unsigned int *nplanes, unsigned int sizes[],
   1370			       struct device *alloc_devs[])
   1371{
   1372	struct vicodec_ctx *ctx = vb2_get_drv_priv(vq);
   1373	struct vicodec_q_data *q_data = get_q_data(ctx, vq->type);
   1374	unsigned int size = q_data->sizeimage;
   1375
   1376	if (*nplanes)
   1377		return sizes[0] < size ? -EINVAL : 0;
   1378
   1379	*nplanes = 1;
   1380	sizes[0] = size;
   1381	q_data->vb2_sizeimage = size;
   1382	return 0;
   1383}
   1384
   1385static int vicodec_buf_out_validate(struct vb2_buffer *vb)
   1386{
   1387	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
   1388
   1389	vbuf->field = V4L2_FIELD_NONE;
   1390	return 0;
   1391}
   1392
   1393static int vicodec_buf_prepare(struct vb2_buffer *vb)
   1394{
   1395	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
   1396	struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
   1397	struct vicodec_q_data *q_data;
   1398
   1399	dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
   1400
   1401	q_data = get_q_data(ctx, vb->vb2_queue->type);
   1402	if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
   1403		if (vbuf->field == V4L2_FIELD_ANY)
   1404			vbuf->field = V4L2_FIELD_NONE;
   1405		if (vbuf->field != V4L2_FIELD_NONE) {
   1406			dprintk(ctx->dev, "%s field isn't supported\n",
   1407					__func__);
   1408			return -EINVAL;
   1409		}
   1410	}
   1411
   1412	if (vb2_plane_size(vb, 0) < q_data->vb2_sizeimage) {
   1413		dprintk(ctx->dev,
   1414			"%s data will not fit into plane (%lu < %lu)\n",
   1415			__func__, vb2_plane_size(vb, 0),
   1416			(long)q_data->vb2_sizeimage);
   1417		return -EINVAL;
   1418	}
   1419
   1420	return 0;
   1421}
   1422
   1423static void vicodec_buf_queue(struct vb2_buffer *vb)
   1424{
   1425	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
   1426	struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
   1427	unsigned int sz = vb2_get_plane_payload(&vbuf->vb2_buf, 0);
   1428	u8 *p_src = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
   1429	u8 *p = p_src;
   1430	struct vb2_queue *vq_out = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
   1431						   V4L2_BUF_TYPE_VIDEO_OUTPUT);
   1432	struct vb2_queue *vq_cap = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
   1433						   V4L2_BUF_TYPE_VIDEO_CAPTURE);
   1434	bool header_valid = false;
   1435	static const struct v4l2_event rs_event = {
   1436		.type = V4L2_EVENT_SOURCE_CHANGE,
   1437		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
   1438	};
   1439
   1440	if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) &&
   1441	    vb2_is_streaming(vb->vb2_queue) &&
   1442	    v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) {
   1443		unsigned int i;
   1444
   1445		for (i = 0; i < vb->num_planes; i++)
   1446			vb2_set_plane_payload(vb, i, 0);
   1447
   1448		vbuf->field = V4L2_FIELD_NONE;
   1449		vbuf->sequence =
   1450			get_q_data(ctx, vb->vb2_queue->type)->sequence++;
   1451
   1452		v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf);
   1453		v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
   1454		return;
   1455	}
   1456
   1457	/* buf_queue handles only the first source change event */
   1458	if (ctx->first_source_change_sent) {
   1459		v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
   1460		return;
   1461	}
   1462
   1463	/*
   1464	 * if both queues are streaming, the source change event is
   1465	 * handled in job_ready
   1466	 */
   1467	if (vb2_is_streaming(vq_cap) && vb2_is_streaming(vq_out)) {
   1468		v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
   1469		return;
   1470	}
   1471
   1472	/*
   1473	 * source change event is relevant only for the stateful decoder
   1474	 * in the compressed stream
   1475	 */
   1476	if (ctx->is_stateless || ctx->is_enc ||
   1477	    V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) {
   1478		v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
   1479		return;
   1480	}
   1481
   1482	do {
   1483		enum vb2_buffer_state state =
   1484			get_next_header(ctx, &p, p_src + sz - p);
   1485
   1486		if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
   1487			v4l2_m2m_buf_done(vbuf, state);
   1488			return;
   1489		}
   1490		header_valid = is_header_valid(&ctx->state.header);
   1491		/*
   1492		 * p points right after the end of the header in the
   1493		 * buffer. If the header is invalid we set p to point
   1494		 * to the next byte after the start of the header
   1495		 */
   1496		if (!header_valid) {
   1497			p = p - sizeof(struct fwht_cframe_hdr) + 1;
   1498			if (p < p_src)
   1499				p = p_src;
   1500			ctx->header_size = 0;
   1501			ctx->comp_magic_cnt = 0;
   1502		}
   1503
   1504	} while (!header_valid);
   1505
   1506	ctx->cur_buf_offset = p - p_src;
   1507	update_capture_data_from_header(ctx);
   1508	ctx->first_source_change_sent = true;
   1509	v4l2_event_queue_fh(&ctx->fh, &rs_event);
   1510	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
   1511}
   1512
   1513static void vicodec_return_bufs(struct vb2_queue *q, u32 state)
   1514{
   1515	struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
   1516	struct vb2_v4l2_buffer *vbuf;
   1517
   1518	for (;;) {
   1519		if (V4L2_TYPE_IS_OUTPUT(q->type))
   1520			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
   1521		else
   1522			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
   1523		if (vbuf == NULL)
   1524			return;
   1525		v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
   1526					   &ctx->hdl);
   1527		spin_lock(ctx->lock);
   1528		v4l2_m2m_buf_done(vbuf, state);
   1529		spin_unlock(ctx->lock);
   1530	}
   1531}
   1532
   1533static unsigned int total_frame_size(struct vicodec_q_data *q_data)
   1534{
   1535	unsigned int size;
   1536	unsigned int chroma_div;
   1537
   1538	if (!q_data->info) {
   1539		WARN_ON(1);
   1540		return 0;
   1541	}
   1542	size = q_data->coded_width * q_data->coded_height;
   1543	chroma_div = q_data->info->width_div * q_data->info->height_div;
   1544
   1545	if (q_data->info->components_num == 4)
   1546		return 2 * size + 2 * (size / chroma_div);
   1547	else if (q_data->info->components_num == 3)
   1548		return size + 2 * (size / chroma_div);
   1549	return size;
   1550}
   1551
   1552static int vicodec_start_streaming(struct vb2_queue *q,
   1553				   unsigned int count)
   1554{
   1555	struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
   1556	struct vicodec_q_data *q_data = get_q_data(ctx, q->type);
   1557	struct v4l2_fwht_state *state = &ctx->state;
   1558	const struct v4l2_fwht_pixfmt_info *info = q_data->info;
   1559	unsigned int size = q_data->coded_width * q_data->coded_height;
   1560	unsigned int chroma_div;
   1561	unsigned int total_planes_size;
   1562	u8 *new_comp_frame = NULL;
   1563
   1564	chroma_div = info->width_div * info->height_div;
   1565	q_data->sequence = 0;
   1566
   1567	v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q);
   1568
   1569	state->gop_cnt = 0;
   1570
   1571	if ((V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) ||
   1572	    (V4L2_TYPE_IS_CAPTURE(q->type) && ctx->is_enc))
   1573		return 0;
   1574
   1575	if (info->id == V4L2_PIX_FMT_FWHT ||
   1576	    info->id == V4L2_PIX_FMT_FWHT_STATELESS) {
   1577		vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
   1578		return -EINVAL;
   1579	}
   1580	total_planes_size = total_frame_size(q_data);
   1581	ctx->comp_max_size = total_planes_size;
   1582
   1583	state->visible_width = q_data->visible_width;
   1584	state->visible_height = q_data->visible_height;
   1585	state->coded_width = q_data->coded_width;
   1586	state->coded_height = q_data->coded_height;
   1587	state->stride = q_data->coded_width *
   1588				info->bytesperline_mult;
   1589
   1590	if (ctx->is_stateless) {
   1591		state->ref_stride = state->stride;
   1592		return 0;
   1593	}
   1594	state->ref_stride = q_data->coded_width * info->luma_alpha_step;
   1595
   1596	state->ref_frame.buf = kvmalloc(total_planes_size, GFP_KERNEL);
   1597	state->ref_frame.luma = state->ref_frame.buf;
   1598	new_comp_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL);
   1599
   1600	if (!state->ref_frame.luma || !new_comp_frame) {
   1601		kvfree(state->ref_frame.luma);
   1602		kvfree(new_comp_frame);
   1603		vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
   1604		return -ENOMEM;
   1605	}
   1606	/*
   1607	 * if state->compressed_frame was already allocated then
   1608	 * it contain data of the first frame of the new resolution
   1609	 */
   1610	if (state->compressed_frame) {
   1611		if (ctx->comp_size > ctx->comp_max_size)
   1612			ctx->comp_size = ctx->comp_max_size;
   1613
   1614		memcpy(new_comp_frame,
   1615		       state->compressed_frame, ctx->comp_size);
   1616	}
   1617
   1618	kvfree(state->compressed_frame);
   1619	state->compressed_frame = new_comp_frame;
   1620
   1621	if (info->components_num < 3) {
   1622		state->ref_frame.cb = NULL;
   1623		state->ref_frame.cr = NULL;
   1624		state->ref_frame.alpha = NULL;
   1625		return 0;
   1626	}
   1627
   1628	state->ref_frame.cb = state->ref_frame.luma + size;
   1629	state->ref_frame.cr = state->ref_frame.cb + size / chroma_div;
   1630
   1631	if (info->components_num == 4)
   1632		state->ref_frame.alpha =
   1633			state->ref_frame.cr + size / chroma_div;
   1634	else
   1635		state->ref_frame.alpha = NULL;
   1636
   1637	return 0;
   1638}
   1639
   1640static void vicodec_stop_streaming(struct vb2_queue *q)
   1641{
   1642	struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
   1643
   1644	vicodec_return_bufs(q, VB2_BUF_STATE_ERROR);
   1645
   1646	v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q);
   1647
   1648	if (V4L2_TYPE_IS_OUTPUT(q->type) &&
   1649	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
   1650		v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
   1651
   1652	if (!ctx->is_enc && V4L2_TYPE_IS_OUTPUT(q->type))
   1653		ctx->first_source_change_sent = false;
   1654
   1655	if ((!V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) ||
   1656	    (V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc)) {
   1657		if (!ctx->is_stateless)
   1658			kvfree(ctx->state.ref_frame.buf);
   1659		ctx->state.ref_frame.buf = NULL;
   1660		ctx->state.ref_frame.luma = NULL;
   1661		ctx->comp_max_size = 0;
   1662		ctx->source_changed = false;
   1663	}
   1664	if (V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) {
   1665		ctx->cur_buf_offset = 0;
   1666		ctx->comp_size = 0;
   1667		ctx->header_size = 0;
   1668		ctx->comp_magic_cnt = 0;
   1669		ctx->comp_has_frame = false;
   1670		ctx->comp_has_next_frame = false;
   1671	}
   1672}
   1673
   1674static void vicodec_buf_request_complete(struct vb2_buffer *vb)
   1675{
   1676	struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
   1677
   1678	v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
   1679}
   1680
   1681
   1682static const struct vb2_ops vicodec_qops = {
   1683	.queue_setup		= vicodec_queue_setup,
   1684	.buf_out_validate	= vicodec_buf_out_validate,
   1685	.buf_prepare		= vicodec_buf_prepare,
   1686	.buf_queue		= vicodec_buf_queue,
   1687	.buf_request_complete	= vicodec_buf_request_complete,
   1688	.start_streaming	= vicodec_start_streaming,
   1689	.stop_streaming		= vicodec_stop_streaming,
   1690	.wait_prepare		= vb2_ops_wait_prepare,
   1691	.wait_finish		= vb2_ops_wait_finish,
   1692};
   1693
   1694static int queue_init(void *priv, struct vb2_queue *src_vq,
   1695		      struct vb2_queue *dst_vq)
   1696{
   1697	struct vicodec_ctx *ctx = priv;
   1698	int ret;
   1699
   1700	src_vq->type = (multiplanar ?
   1701			V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
   1702			V4L2_BUF_TYPE_VIDEO_OUTPUT);
   1703	src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
   1704	src_vq->drv_priv = ctx;
   1705	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
   1706	src_vq->ops = &vicodec_qops;
   1707	src_vq->mem_ops = &vb2_vmalloc_memops;
   1708	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
   1709	if (ctx->is_enc)
   1710		src_vq->lock = &ctx->dev->stateful_enc.mutex;
   1711	else if (ctx->is_stateless)
   1712		src_vq->lock = &ctx->dev->stateless_dec.mutex;
   1713	else
   1714		src_vq->lock = &ctx->dev->stateful_dec.mutex;
   1715	src_vq->supports_requests = ctx->is_stateless;
   1716	src_vq->requires_requests = ctx->is_stateless;
   1717	ret = vb2_queue_init(src_vq);
   1718	if (ret)
   1719		return ret;
   1720
   1721	dst_vq->type = (multiplanar ?
   1722			V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
   1723			V4L2_BUF_TYPE_VIDEO_CAPTURE);
   1724	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
   1725	dst_vq->drv_priv = ctx;
   1726	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
   1727	dst_vq->ops = &vicodec_qops;
   1728	dst_vq->mem_ops = &vb2_vmalloc_memops;
   1729	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
   1730	dst_vq->lock = src_vq->lock;
   1731
   1732	return vb2_queue_init(dst_vq);
   1733}
   1734
   1735static int vicodec_try_ctrl(struct v4l2_ctrl *ctrl)
   1736{
   1737	struct vicodec_ctx *ctx = container_of(ctrl->handler,
   1738			struct vicodec_ctx, hdl);
   1739	const struct v4l2_ctrl_fwht_params *params;
   1740	struct vicodec_q_data *q_dst = get_q_data(ctx,
   1741			V4L2_BUF_TYPE_VIDEO_CAPTURE);
   1742
   1743	switch (ctrl->id) {
   1744	case V4L2_CID_STATELESS_FWHT_PARAMS:
   1745		if (!q_dst->info)
   1746			return -EINVAL;
   1747		params = ctrl->p_new.p_fwht_params;
   1748		if (params->width > q_dst->coded_width ||
   1749		    params->width < MIN_WIDTH ||
   1750		    params->height > q_dst->coded_height ||
   1751		    params->height < MIN_HEIGHT)
   1752			return -EINVAL;
   1753		if (!validate_by_version(params->flags, params->version))
   1754			return -EINVAL;
   1755		if (!validate_stateless_params_flags(params, q_dst->info))
   1756			return -EINVAL;
   1757		return 0;
   1758	default:
   1759		return 0;
   1760	}
   1761	return 0;
   1762}
   1763
   1764static void update_header_from_stateless_params(struct vicodec_ctx *ctx,
   1765						const struct v4l2_ctrl_fwht_params *params)
   1766{
   1767	struct fwht_cframe_hdr *p_hdr = &ctx->state.header;
   1768
   1769	p_hdr->magic1 = FWHT_MAGIC1;
   1770	p_hdr->magic2 = FWHT_MAGIC2;
   1771	p_hdr->version = htonl(params->version);
   1772	p_hdr->width = htonl(params->width);
   1773	p_hdr->height = htonl(params->height);
   1774	p_hdr->flags = htonl(params->flags);
   1775	p_hdr->colorspace = htonl(params->colorspace);
   1776	p_hdr->xfer_func = htonl(params->xfer_func);
   1777	p_hdr->ycbcr_enc = htonl(params->ycbcr_enc);
   1778	p_hdr->quantization = htonl(params->quantization);
   1779}
   1780
   1781static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl)
   1782{
   1783	struct vicodec_ctx *ctx = container_of(ctrl->handler,
   1784					       struct vicodec_ctx, hdl);
   1785	const struct v4l2_ctrl_fwht_params *params;
   1786
   1787	switch (ctrl->id) {
   1788	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
   1789		ctx->state.gop_size = ctrl->val;
   1790		return 0;
   1791	case V4L2_CID_FWHT_I_FRAME_QP:
   1792		ctx->state.i_frame_qp = ctrl->val;
   1793		return 0;
   1794	case V4L2_CID_FWHT_P_FRAME_QP:
   1795		ctx->state.p_frame_qp = ctrl->val;
   1796		return 0;
   1797	case V4L2_CID_STATELESS_FWHT_PARAMS:
   1798		params = ctrl->p_new.p_fwht_params;
   1799		update_header_from_stateless_params(ctx, params);
   1800		ctx->state.ref_frame_ts = params->backward_ref_ts;
   1801		return 0;
   1802	}
   1803	return -EINVAL;
   1804}
   1805
   1806static const struct v4l2_ctrl_ops vicodec_ctrl_ops = {
   1807	.s_ctrl = vicodec_s_ctrl,
   1808	.try_ctrl = vicodec_try_ctrl,
   1809};
   1810
   1811static const struct v4l2_ctrl_config vicodec_ctrl_stateless_state = {
   1812	.ops		= &vicodec_ctrl_ops,
   1813	.id		= V4L2_CID_STATELESS_FWHT_PARAMS,
   1814	.elem_size      = sizeof(struct v4l2_ctrl_fwht_params),
   1815};
   1816
   1817/*
   1818 * File operations
   1819 */
   1820static int vicodec_open(struct file *file)
   1821{
   1822	const struct v4l2_fwht_pixfmt_info *info = v4l2_fwht_get_pixfmt(0);
   1823	struct video_device *vfd = video_devdata(file);
   1824	struct vicodec_dev *dev = video_drvdata(file);
   1825	struct vicodec_ctx *ctx = NULL;
   1826	struct v4l2_ctrl_handler *hdl;
   1827	unsigned int raw_size;
   1828	unsigned int comp_size;
   1829	int rc = 0;
   1830
   1831	if (mutex_lock_interruptible(vfd->lock))
   1832		return -ERESTARTSYS;
   1833	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
   1834	if (!ctx) {
   1835		rc = -ENOMEM;
   1836		goto open_unlock;
   1837	}
   1838
   1839	if (vfd == &dev->stateful_enc.vfd)
   1840		ctx->is_enc = true;
   1841	else if (vfd == &dev->stateless_dec.vfd)
   1842		ctx->is_stateless = true;
   1843
   1844	v4l2_fh_init(&ctx->fh, video_devdata(file));
   1845	file->private_data = &ctx->fh;
   1846	ctx->dev = dev;
   1847	hdl = &ctx->hdl;
   1848	v4l2_ctrl_handler_init(hdl, 5);
   1849	v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE,
   1850			  1, 16, 1, 10);
   1851	v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_I_FRAME_QP,
   1852			  1, 31, 1, 20);
   1853	v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_P_FRAME_QP,
   1854			  1, 31, 1, 20);
   1855	if (ctx->is_enc)
   1856		v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops,
   1857				  V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 1, 1, 1);
   1858	if (ctx->is_stateless)
   1859		v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_stateless_state, NULL);
   1860	if (hdl->error) {
   1861		rc = hdl->error;
   1862		v4l2_ctrl_handler_free(hdl);
   1863		kfree(ctx);
   1864		goto open_unlock;
   1865	}
   1866	ctx->fh.ctrl_handler = hdl;
   1867	v4l2_ctrl_handler_setup(hdl);
   1868
   1869	if (ctx->is_enc)
   1870		ctx->q_data[V4L2_M2M_SRC].info = info;
   1871	else if (ctx->is_stateless)
   1872		ctx->q_data[V4L2_M2M_SRC].info = &pixfmt_stateless_fwht;
   1873	else
   1874		ctx->q_data[V4L2_M2M_SRC].info = &pixfmt_fwht;
   1875	ctx->q_data[V4L2_M2M_SRC].coded_width = 1280;
   1876	ctx->q_data[V4L2_M2M_SRC].coded_height = 720;
   1877	ctx->q_data[V4L2_M2M_SRC].visible_width = 1280;
   1878	ctx->q_data[V4L2_M2M_SRC].visible_height = 720;
   1879	raw_size = 1280 * 720 * info->sizeimage_mult / info->sizeimage_div;
   1880	comp_size = 1280 * 720 * pixfmt_fwht.sizeimage_mult /
   1881				 pixfmt_fwht.sizeimage_div;
   1882	if (ctx->is_enc)
   1883		ctx->q_data[V4L2_M2M_SRC].sizeimage = raw_size;
   1884	else if (ctx->is_stateless)
   1885		ctx->q_data[V4L2_M2M_SRC].sizeimage = comp_size;
   1886	else
   1887		ctx->q_data[V4L2_M2M_SRC].sizeimage =
   1888			comp_size + sizeof(struct fwht_cframe_hdr);
   1889	ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
   1890	if (ctx->is_enc) {
   1891		ctx->q_data[V4L2_M2M_DST].info = &pixfmt_fwht;
   1892		ctx->q_data[V4L2_M2M_DST].sizeimage =
   1893			comp_size + sizeof(struct fwht_cframe_hdr);
   1894	} else {
   1895		ctx->q_data[V4L2_M2M_DST].info = info;
   1896		ctx->q_data[V4L2_M2M_DST].sizeimage = raw_size;
   1897	}
   1898
   1899	ctx->state.colorspace = V4L2_COLORSPACE_REC709;
   1900
   1901	if (ctx->is_enc) {
   1902		ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateful_enc.m2m_dev,
   1903						    ctx, &queue_init);
   1904		ctx->lock = &dev->stateful_enc.lock;
   1905	} else if (ctx->is_stateless) {
   1906		ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateless_dec.m2m_dev,
   1907						    ctx, &queue_init);
   1908		ctx->lock = &dev->stateless_dec.lock;
   1909	} else {
   1910		ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateful_dec.m2m_dev,
   1911						    ctx, &queue_init);
   1912		ctx->lock = &dev->stateful_dec.lock;
   1913	}
   1914
   1915	if (IS_ERR(ctx->fh.m2m_ctx)) {
   1916		rc = PTR_ERR(ctx->fh.m2m_ctx);
   1917
   1918		v4l2_ctrl_handler_free(hdl);
   1919		v4l2_fh_exit(&ctx->fh);
   1920		kfree(ctx);
   1921		goto open_unlock;
   1922	}
   1923
   1924	v4l2_fh_add(&ctx->fh);
   1925
   1926open_unlock:
   1927	mutex_unlock(vfd->lock);
   1928	return rc;
   1929}
   1930
   1931static int vicodec_release(struct file *file)
   1932{
   1933	struct video_device *vfd = video_devdata(file);
   1934	struct vicodec_ctx *ctx = file2ctx(file);
   1935
   1936	mutex_lock(vfd->lock);
   1937	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
   1938	mutex_unlock(vfd->lock);
   1939	v4l2_fh_del(&ctx->fh);
   1940	v4l2_fh_exit(&ctx->fh);
   1941	v4l2_ctrl_handler_free(&ctx->hdl);
   1942	kvfree(ctx->state.compressed_frame);
   1943	kfree(ctx);
   1944
   1945	return 0;
   1946}
   1947
   1948static int vicodec_request_validate(struct media_request *req)
   1949{
   1950	struct media_request_object *obj;
   1951	struct v4l2_ctrl_handler *parent_hdl, *hdl;
   1952	struct vicodec_ctx *ctx = NULL;
   1953	struct v4l2_ctrl *ctrl;
   1954	unsigned int count;
   1955
   1956	list_for_each_entry(obj, &req->objects, list) {
   1957		struct vb2_buffer *vb;
   1958
   1959		if (vb2_request_object_is_buffer(obj)) {
   1960			vb = container_of(obj, struct vb2_buffer, req_obj);
   1961			ctx = vb2_get_drv_priv(vb->vb2_queue);
   1962
   1963			break;
   1964		}
   1965	}
   1966
   1967	if (!ctx) {
   1968		pr_err("No buffer was provided with the request\n");
   1969		return -ENOENT;
   1970	}
   1971
   1972	count = vb2_request_buffer_cnt(req);
   1973	if (!count) {
   1974		v4l2_info(&ctx->dev->v4l2_dev,
   1975			  "No buffer was provided with the request\n");
   1976		return -ENOENT;
   1977	} else if (count > 1) {
   1978		v4l2_info(&ctx->dev->v4l2_dev,
   1979			  "More than one buffer was provided with the request\n");
   1980		return -EINVAL;
   1981	}
   1982
   1983	parent_hdl = &ctx->hdl;
   1984
   1985	hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl);
   1986	if (!hdl) {
   1987		v4l2_info(&ctx->dev->v4l2_dev, "Missing codec control\n");
   1988		return -ENOENT;
   1989	}
   1990	ctrl = v4l2_ctrl_request_hdl_ctrl_find(hdl,
   1991					       vicodec_ctrl_stateless_state.id);
   1992	v4l2_ctrl_request_hdl_put(hdl);
   1993	if (!ctrl) {
   1994		v4l2_info(&ctx->dev->v4l2_dev,
   1995			  "Missing required codec control\n");
   1996		return -ENOENT;
   1997	}
   1998
   1999	return vb2_request_validate(req);
   2000}
   2001
   2002static const struct v4l2_file_operations vicodec_fops = {
   2003	.owner		= THIS_MODULE,
   2004	.open		= vicodec_open,
   2005	.release	= vicodec_release,
   2006	.poll		= v4l2_m2m_fop_poll,
   2007	.unlocked_ioctl	= video_ioctl2,
   2008	.mmap		= v4l2_m2m_fop_mmap,
   2009};
   2010
   2011static const struct video_device vicodec_videodev = {
   2012	.name		= VICODEC_NAME,
   2013	.vfl_dir	= VFL_DIR_M2M,
   2014	.fops		= &vicodec_fops,
   2015	.ioctl_ops	= &vicodec_ioctl_ops,
   2016	.minor		= -1,
   2017	.release	= video_device_release_empty,
   2018};
   2019
   2020static const struct media_device_ops vicodec_m2m_media_ops = {
   2021	.req_validate	= vicodec_request_validate,
   2022	.req_queue	= v4l2_m2m_request_queue,
   2023};
   2024
   2025static const struct v4l2_m2m_ops m2m_ops = {
   2026	.device_run	= device_run,
   2027	.job_ready	= job_ready,
   2028};
   2029
   2030static int register_instance(struct vicodec_dev *dev,
   2031			     struct vicodec_dev_instance *dev_instance,
   2032			     const char *name, bool is_enc)
   2033{
   2034	struct video_device *vfd;
   2035	int ret;
   2036
   2037	spin_lock_init(&dev_instance->lock);
   2038	mutex_init(&dev_instance->mutex);
   2039	dev_instance->m2m_dev = v4l2_m2m_init(&m2m_ops);
   2040	if (IS_ERR(dev_instance->m2m_dev)) {
   2041		v4l2_err(&dev->v4l2_dev, "Failed to init vicodec enc device\n");
   2042		return PTR_ERR(dev_instance->m2m_dev);
   2043	}
   2044
   2045	dev_instance->vfd = vicodec_videodev;
   2046	vfd = &dev_instance->vfd;
   2047	vfd->lock = &dev_instance->mutex;
   2048	vfd->v4l2_dev = &dev->v4l2_dev;
   2049	strscpy(vfd->name, name, sizeof(vfd->name));
   2050	vfd->device_caps = V4L2_CAP_STREAMING |
   2051		(multiplanar ? V4L2_CAP_VIDEO_M2M_MPLANE : V4L2_CAP_VIDEO_M2M);
   2052	if (is_enc) {
   2053		v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
   2054		v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
   2055	} else {
   2056		v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
   2057		v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
   2058	}
   2059	video_set_drvdata(vfd, dev);
   2060
   2061	ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
   2062	if (ret) {
   2063		v4l2_err(&dev->v4l2_dev, "Failed to register video device '%s'\n", name);
   2064		v4l2_m2m_release(dev_instance->m2m_dev);
   2065		return ret;
   2066	}
   2067	v4l2_info(&dev->v4l2_dev, "Device '%s' registered as /dev/video%d\n",
   2068		  name, vfd->num);
   2069	return 0;
   2070}
   2071
   2072static void vicodec_v4l2_dev_release(struct v4l2_device *v4l2_dev)
   2073{
   2074	struct vicodec_dev *dev = container_of(v4l2_dev, struct vicodec_dev, v4l2_dev);
   2075
   2076	v4l2_device_unregister(&dev->v4l2_dev);
   2077	v4l2_m2m_release(dev->stateful_enc.m2m_dev);
   2078	v4l2_m2m_release(dev->stateful_dec.m2m_dev);
   2079	v4l2_m2m_release(dev->stateless_dec.m2m_dev);
   2080#ifdef CONFIG_MEDIA_CONTROLLER
   2081	media_device_cleanup(&dev->mdev);
   2082#endif
   2083	kfree(dev);
   2084}
   2085
   2086static int vicodec_probe(struct platform_device *pdev)
   2087{
   2088	struct vicodec_dev *dev;
   2089	int ret;
   2090
   2091	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
   2092	if (!dev)
   2093		return -ENOMEM;
   2094
   2095	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
   2096	if (ret)
   2097		goto free_dev;
   2098
   2099	dev->v4l2_dev.release = vicodec_v4l2_dev_release;
   2100
   2101#ifdef CONFIG_MEDIA_CONTROLLER
   2102	dev->mdev.dev = &pdev->dev;
   2103	strscpy(dev->mdev.model, "vicodec", sizeof(dev->mdev.model));
   2104	strscpy(dev->mdev.bus_info, "platform:vicodec",
   2105		sizeof(dev->mdev.bus_info));
   2106	media_device_init(&dev->mdev);
   2107	dev->mdev.ops = &vicodec_m2m_media_ops;
   2108	dev->v4l2_dev.mdev = &dev->mdev;
   2109#endif
   2110
   2111	platform_set_drvdata(pdev, dev);
   2112
   2113	ret = register_instance(dev, &dev->stateful_enc, "stateful-encoder",
   2114				true);
   2115	if (ret)
   2116		goto unreg_dev;
   2117
   2118	ret = register_instance(dev, &dev->stateful_dec, "stateful-decoder",
   2119				false);
   2120	if (ret)
   2121		goto unreg_sf_enc;
   2122
   2123	ret = register_instance(dev, &dev->stateless_dec, "stateless-decoder",
   2124				false);
   2125	if (ret)
   2126		goto unreg_sf_dec;
   2127
   2128#ifdef CONFIG_MEDIA_CONTROLLER
   2129	ret = v4l2_m2m_register_media_controller(dev->stateful_enc.m2m_dev,
   2130						 &dev->stateful_enc.vfd,
   2131						 MEDIA_ENT_F_PROC_VIDEO_ENCODER);
   2132	if (ret) {
   2133		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for enc\n");
   2134		goto unreg_m2m;
   2135	}
   2136
   2137	ret = v4l2_m2m_register_media_controller(dev->stateful_dec.m2m_dev,
   2138						 &dev->stateful_dec.vfd,
   2139						 MEDIA_ENT_F_PROC_VIDEO_DECODER);
   2140	if (ret) {
   2141		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for dec\n");
   2142		goto unreg_m2m_sf_enc_mc;
   2143	}
   2144
   2145	ret = v4l2_m2m_register_media_controller(dev->stateless_dec.m2m_dev,
   2146						 &dev->stateless_dec.vfd,
   2147						 MEDIA_ENT_F_PROC_VIDEO_DECODER);
   2148	if (ret) {
   2149		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for stateless dec\n");
   2150		goto unreg_m2m_sf_dec_mc;
   2151	}
   2152
   2153	ret = media_device_register(&dev->mdev);
   2154	if (ret) {
   2155		v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n");
   2156		goto unreg_m2m_sl_dec_mc;
   2157	}
   2158#endif
   2159	return 0;
   2160
   2161#ifdef CONFIG_MEDIA_CONTROLLER
   2162unreg_m2m_sl_dec_mc:
   2163	v4l2_m2m_unregister_media_controller(dev->stateless_dec.m2m_dev);
   2164unreg_m2m_sf_dec_mc:
   2165	v4l2_m2m_unregister_media_controller(dev->stateful_dec.m2m_dev);
   2166unreg_m2m_sf_enc_mc:
   2167	v4l2_m2m_unregister_media_controller(dev->stateful_enc.m2m_dev);
   2168unreg_m2m:
   2169	video_unregister_device(&dev->stateless_dec.vfd);
   2170	v4l2_m2m_release(dev->stateless_dec.m2m_dev);
   2171#endif
   2172unreg_sf_dec:
   2173	video_unregister_device(&dev->stateful_dec.vfd);
   2174	v4l2_m2m_release(dev->stateful_dec.m2m_dev);
   2175unreg_sf_enc:
   2176	video_unregister_device(&dev->stateful_enc.vfd);
   2177	v4l2_m2m_release(dev->stateful_enc.m2m_dev);
   2178unreg_dev:
   2179	v4l2_device_unregister(&dev->v4l2_dev);
   2180free_dev:
   2181	kfree(dev);
   2182
   2183	return ret;
   2184}
   2185
   2186static int vicodec_remove(struct platform_device *pdev)
   2187{
   2188	struct vicodec_dev *dev = platform_get_drvdata(pdev);
   2189
   2190	v4l2_info(&dev->v4l2_dev, "Removing " VICODEC_NAME);
   2191
   2192#ifdef CONFIG_MEDIA_CONTROLLER
   2193	media_device_unregister(&dev->mdev);
   2194	v4l2_m2m_unregister_media_controller(dev->stateful_enc.m2m_dev);
   2195	v4l2_m2m_unregister_media_controller(dev->stateful_dec.m2m_dev);
   2196	v4l2_m2m_unregister_media_controller(dev->stateless_dec.m2m_dev);
   2197#endif
   2198
   2199	video_unregister_device(&dev->stateful_enc.vfd);
   2200	video_unregister_device(&dev->stateful_dec.vfd);
   2201	video_unregister_device(&dev->stateless_dec.vfd);
   2202	v4l2_device_put(&dev->v4l2_dev);
   2203
   2204	return 0;
   2205}
   2206
   2207static struct platform_driver vicodec_pdrv = {
   2208	.probe		= vicodec_probe,
   2209	.remove		= vicodec_remove,
   2210	.driver		= {
   2211		.name	= VICODEC_NAME,
   2212	},
   2213};
   2214
   2215static void __exit vicodec_exit(void)
   2216{
   2217	platform_driver_unregister(&vicodec_pdrv);
   2218	platform_device_unregister(&vicodec_pdev);
   2219}
   2220
   2221static int __init vicodec_init(void)
   2222{
   2223	int ret;
   2224
   2225	ret = platform_device_register(&vicodec_pdev);
   2226	if (ret)
   2227		return ret;
   2228
   2229	ret = platform_driver_register(&vicodec_pdrv);
   2230	if (ret)
   2231		platform_device_unregister(&vicodec_pdev);
   2232
   2233	return ret;
   2234}
   2235
   2236module_init(vicodec_init);
   2237module_exit(vicodec_exit);