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