1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Contains the driver implementation for the V4L2 stateless interface.
4 */
5
6#include <linux/debugfs.h>
7#include <linux/font.h>
8#include <media/v4l2-event.h>
9#include <media/v4l2-ioctl.h>
10#include <media/videobuf2-vmalloc.h>
11#include <media/videobuf2-v4l2.h>
12
13#include "visl-video.h"
14
15#include "visl.h"
16#include "visl-debugfs.h"
17
18#define MIN_CODED_SZ (1024U * 256U)
19
20static void visl_set_current_codec(struct visl_ctx *ctx)
21{
22	u32 fourcc = ctx->coded_fmt.fmt.pix_mp.pixelformat;
23
24	switch (fourcc) {
25	case V4L2_PIX_FMT_FWHT_STATELESS:
26		ctx->current_codec = VISL_CODEC_FWHT;
27		break;
28	case V4L2_PIX_FMT_MPEG2_SLICE:
29		ctx->current_codec = VISL_CODEC_MPEG2;
30		break;
31	case V4L2_PIX_FMT_VP8_FRAME:
32		ctx->current_codec = VISL_CODEC_VP8;
33		break;
34	case V4L2_PIX_FMT_VP9_FRAME:
35		ctx->current_codec = VISL_CODEC_VP9;
36		break;
37	case V4L2_PIX_FMT_H264_SLICE:
38		ctx->current_codec = VISL_CODEC_H264;
39		break;
40	case V4L2_PIX_FMT_HEVC_SLICE:
41		ctx->current_codec = VISL_CODEC_HEVC;
42		break;
43	default:
44		dprintk(ctx->dev, "Warning: unsupported fourcc: %d\n", fourcc);
45		ctx->current_codec = VISL_CODEC_NONE;
46		break;
47	}
48}
49
50static void visl_print_fmt(struct visl_ctx *ctx, const struct v4l2_format *f)
51{
52	const struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
53	u32 i;
54
55	dprintk(ctx->dev, "width: %d\n", pix_mp->width);
56	dprintk(ctx->dev, "height: %d\n", pix_mp->height);
57	dprintk(ctx->dev, "pixelformat: %c%c%c%c\n",
58		pix_mp->pixelformat,
59		(pix_mp->pixelformat >> 8) & 0xff,
60		(pix_mp->pixelformat >> 16) & 0xff,
61		(pix_mp->pixelformat >> 24) & 0xff);
62
63	dprintk(ctx->dev, "field: %d\n", pix_mp->field);
64	dprintk(ctx->dev, "colorspace: %d\n", pix_mp->colorspace);
65	dprintk(ctx->dev, "num_planes: %d\n", pix_mp->num_planes);
66	dprintk(ctx->dev, "flags: %d\n", pix_mp->flags);
67	dprintk(ctx->dev, "quantization: %d\n", pix_mp->quantization);
68	dprintk(ctx->dev, "xfer_func: %d\n", pix_mp->xfer_func);
69
70	for (i = 0; i < pix_mp->num_planes; i++) {
71		dprintk(ctx->dev,
72			"plane[%d]: sizeimage: %d\n", i, pix_mp->plane_fmt[i].sizeimage);
73		dprintk(ctx->dev,
74			"plane[%d]: bytesperline: %d\n", i, pix_mp->plane_fmt[i].bytesperline);
75	}
76}
77
78static int visl_tpg_init(struct visl_ctx *ctx)
79{
80	const struct font_desc *font;
81	const char *font_name = "VGA8x16";
82	int ret;
83	u32 width = ctx->decoded_fmt.fmt.pix_mp.width;
84	u32 height = ctx->decoded_fmt.fmt.pix_mp.height;
85	struct v4l2_pix_format_mplane *f = &ctx->decoded_fmt.fmt.pix_mp;
86
87	tpg_free(&ctx->tpg);
88
89	font = find_font(font_name);
90	if (font) {
91		tpg_init(&ctx->tpg, width, height);
92
93		ret = tpg_alloc(&ctx->tpg, width);
94		if (ret)
95			goto err_alloc;
96
97		tpg_set_font(font->data);
98		ret = tpg_s_fourcc(&ctx->tpg,
99				   f->pixelformat);
100
101		if (!ret)
102			goto err_fourcc;
103
104		tpg_reset_source(&ctx->tpg, width, height, f->field);
105
106		tpg_s_pattern(&ctx->tpg, TPG_PAT_75_COLORBAR);
107
108		tpg_s_field(&ctx->tpg, f->field, false);
109		tpg_s_colorspace(&ctx->tpg, f->colorspace);
110		tpg_s_ycbcr_enc(&ctx->tpg, f->ycbcr_enc);
111		tpg_s_quantization(&ctx->tpg, f->quantization);
112		tpg_s_xfer_func(&ctx->tpg, f->xfer_func);
113	} else {
114		v4l2_err(&ctx->dev->v4l2_dev,
115			 "Font %s not found\n", font_name);
116
117		return -EINVAL;
118	}
119
120	dprintk(ctx->dev, "Initialized the V4L2 test pattern generator, w=%d, h=%d, max_w=%d\n",
121		width, height, width);
122
123	return 0;
124err_alloc:
125	return ret;
126err_fourcc:
127	tpg_free(&ctx->tpg);
128	return ret;
129}
130
131static const u32 visl_decoded_fmts[] = {
132	V4L2_PIX_FMT_NV12,
133	V4L2_PIX_FMT_YUV420,
134};
135
136const struct visl_coded_format_desc visl_coded_fmts[] = {
137	{
138		.pixelformat = V4L2_PIX_FMT_FWHT_STATELESS,
139		.frmsize = {
140			.min_width = 640,
141			.max_width = 4096,
142			.step_width = 1,
143			.min_height = 360,
144			.max_height = 2160,
145			.step_height = 1,
146		},
147		.ctrls = &visl_fwht_ctrls,
148		.num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts),
149		.decoded_fmts = visl_decoded_fmts,
150	},
151	{
152		.pixelformat = V4L2_PIX_FMT_MPEG2_SLICE,
153		.frmsize = {
154			.min_width = 16,
155			.max_width = 1920,
156			.step_width = 1,
157			.min_height = 16,
158			.max_height = 1152,
159			.step_height = 1,
160		},
161		.ctrls = &visl_mpeg2_ctrls,
162		.num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts),
163		.decoded_fmts = visl_decoded_fmts,
164	},
165	{
166		.pixelformat = V4L2_PIX_FMT_VP8_FRAME,
167		.frmsize = {
168			.min_width = 64,
169			.max_width = 16383,
170			.step_width = 1,
171			.min_height = 64,
172			.max_height = 16383,
173			.step_height = 1,
174		},
175		.ctrls = &visl_vp8_ctrls,
176		.num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts),
177		.decoded_fmts = visl_decoded_fmts,
178	},
179	{
180		.pixelformat = V4L2_PIX_FMT_VP9_FRAME,
181		.frmsize = {
182			.min_width = 64,
183			.max_width = 8192,
184			.step_width = 1,
185			.min_height = 64,
186			.max_height = 4352,
187			.step_height = 1,
188		},
189		.ctrls = &visl_vp9_ctrls,
190		.num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts),
191		.decoded_fmts = visl_decoded_fmts,
192	},
193	{
194		.pixelformat = V4L2_PIX_FMT_H264_SLICE,
195		.frmsize = {
196			.min_width = 64,
197			.max_width = 4096,
198			.step_width = 1,
199			.min_height = 64,
200			.max_height = 2304,
201			.step_height = 1,
202		},
203		.ctrls = &visl_h264_ctrls,
204		.num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts),
205		.decoded_fmts = visl_decoded_fmts,
206	},
207	{
208		.pixelformat = V4L2_PIX_FMT_HEVC_SLICE,
209		.frmsize = {
210			.min_width = 64,
211			.max_width = 4096,
212			.step_width = 1,
213			.min_height = 64,
214			.max_height = 2304,
215			.step_height = 1,
216		},
217		.ctrls = &visl_hevc_ctrls,
218		.num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts),
219		.decoded_fmts = visl_decoded_fmts,
220	},
221};
222
223const size_t num_coded_fmts = ARRAY_SIZE(visl_coded_fmts);
224
225static const struct visl_coded_format_desc*
226visl_find_coded_fmt_desc(u32 fourcc)
227{
228	unsigned int i;
229
230	for (i = 0; i < ARRAY_SIZE(visl_coded_fmts); i++) {
231		if (visl_coded_fmts[i].pixelformat == fourcc)
232			return &visl_coded_fmts[i];
233	}
234
235	return NULL;
236}
237
238static void visl_init_fmt(struct v4l2_format *f, u32 fourcc)
239{	memset(f, 0, sizeof(*f));
240	f->fmt.pix_mp.pixelformat = fourcc;
241	f->fmt.pix_mp.field = V4L2_FIELD_NONE;
242	f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709;
243	f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
244	f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
245	f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
246}
247
248static void visl_reset_coded_fmt(struct visl_ctx *ctx)
249{
250	struct v4l2_format *f = &ctx->coded_fmt;
251	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
252
253	ctx->coded_format_desc = &visl_coded_fmts[0];
254	visl_init_fmt(f, ctx->coded_format_desc->pixelformat);
255
256	f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
257	f->fmt.pix_mp.width = ctx->coded_format_desc->frmsize.min_width;
258	f->fmt.pix_mp.height = ctx->coded_format_desc->frmsize.min_height;
259
260	pix_mp->num_planes = 1;
261	pix_mp->plane_fmt[0].sizeimage = pix_mp->width * pix_mp->height * 8;
262
263	dprintk(ctx->dev, "OUTPUT format was set to:\n");
264	visl_print_fmt(ctx, &ctx->coded_fmt);
265
266	visl_set_current_codec(ctx);
267}
268
269static int visl_reset_decoded_fmt(struct visl_ctx *ctx)
270{
271	struct v4l2_format *f = &ctx->decoded_fmt;
272	u32 decoded_fmt = ctx->coded_format_desc[0].decoded_fmts[0];
273
274	visl_init_fmt(f, decoded_fmt);
275
276	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
277
278	v4l2_fill_pixfmt_mp(&f->fmt.pix_mp,
279			    ctx->coded_format_desc->decoded_fmts[0],
280			    ctx->coded_fmt.fmt.pix_mp.width,
281			    ctx->coded_fmt.fmt.pix_mp.height);
282
283	dprintk(ctx->dev, "CAPTURE format was set to:\n");
284	visl_print_fmt(ctx, &ctx->decoded_fmt);
285
286	return visl_tpg_init(ctx);
287}
288
289int visl_set_default_format(struct visl_ctx *ctx)
290{
291	visl_reset_coded_fmt(ctx);
292	return visl_reset_decoded_fmt(ctx);
293}
294
295static struct visl_q_data *get_q_data(struct visl_ctx *ctx,
296				      enum v4l2_buf_type type)
297{
298	switch (type) {
299	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
300	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
301		return &ctx->q_data[V4L2_M2M_SRC];
302	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
303	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
304		return &ctx->q_data[V4L2_M2M_DST];
305	default:
306		break;
307	}
308	return NULL;
309}
310
311static int visl_querycap(struct file *file, void *priv,
312			 struct v4l2_capability *cap)
313{
314	strscpy(cap->driver, VISL_NAME, sizeof(cap->driver));
315	strscpy(cap->card, VISL_NAME, sizeof(cap->card));
316	snprintf(cap->bus_info, sizeof(cap->bus_info),
317		 "platform:%s", VISL_NAME);
318
319	return 0;
320}
321
322static int visl_enum_fmt_vid_cap(struct file *file, void *priv,
323				 struct v4l2_fmtdesc *f)
324{
325	struct visl_ctx *ctx = visl_file_to_ctx(file);
326
327	if (f->index >= ctx->coded_format_desc->num_decoded_fmts)
328		return -EINVAL;
329
330	f->pixelformat = ctx->coded_format_desc->decoded_fmts[f->index];
331	return 0;
332}
333
334static int visl_enum_fmt_vid_out(struct file *file, void *priv,
335				 struct v4l2_fmtdesc *f)
336{
337	if (f->index >= ARRAY_SIZE(visl_coded_fmts))
338		return -EINVAL;
339
340	f->pixelformat = visl_coded_fmts[f->index].pixelformat;
341	return 0;
342}
343
344static int visl_g_fmt_vid_cap(struct file *file, void *priv,
345			      struct v4l2_format *f)
346{
347	struct visl_ctx *ctx = visl_file_to_ctx(file);
348	*f = ctx->decoded_fmt;
349
350	return 0;
351}
352
353static int visl_g_fmt_vid_out(struct file *file, void *priv,
354			      struct v4l2_format *f)
355{
356	struct visl_ctx *ctx = visl_file_to_ctx(file);
357
358	*f = ctx->coded_fmt;
359	return 0;
360}
361
362static int visl_try_fmt_vid_cap(struct file *file, void *priv,
363				struct v4l2_format *f)
364{
365	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
366	struct visl_ctx *ctx = visl_file_to_ctx(file);
367	const struct visl_coded_format_desc *coded_desc;
368	unsigned int i;
369
370	coded_desc = ctx->coded_format_desc;
371
372	for (i = 0; i < coded_desc->num_decoded_fmts; i++) {
373		if (coded_desc->decoded_fmts[i] == pix_mp->pixelformat)
374			break;
375	}
376
377	if (i == coded_desc->num_decoded_fmts)
378		pix_mp->pixelformat = coded_desc->decoded_fmts[0];
379
380	v4l2_apply_frmsize_constraints(&pix_mp->width,
381				       &pix_mp->height,
382				       &coded_desc->frmsize);
383
384	v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat,
385			    pix_mp->width, pix_mp->height);
386
387	pix_mp->field = V4L2_FIELD_NONE;
388
389	return 0;
390}
391
392static int visl_try_fmt_vid_out(struct file *file, void *priv,
393				struct v4l2_format *f)
394{
395	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
396	const struct visl_coded_format_desc *coded_desc;
397
398	coded_desc = visl_find_coded_fmt_desc(pix_mp->pixelformat);
399	if (!coded_desc) {
400		pix_mp->pixelformat = visl_coded_fmts[0].pixelformat;
401		coded_desc = &visl_coded_fmts[0];
402	}
403
404	v4l2_apply_frmsize_constraints(&pix_mp->width,
405				       &pix_mp->height,
406				       &coded_desc->frmsize);
407
408	pix_mp->field = V4L2_FIELD_NONE;
409	pix_mp->num_planes = 1;
410
411	if (pix_mp->plane_fmt[0].sizeimage == 0)
412		pix_mp->plane_fmt[0].sizeimage = max(MIN_CODED_SZ,
413						     pix_mp->width * pix_mp->height * 3);
414
415	return 0;
416}
417
418static int visl_s_fmt_vid_out(struct file *file, void *priv,
419			      struct v4l2_format *f)
420{
421	struct visl_ctx *ctx = visl_file_to_ctx(file);
422	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
423	const struct visl_coded_format_desc *desc;
424	struct vb2_queue *peer_vq;
425	int ret;
426
427	peer_vq = v4l2_m2m_get_vq(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
428	if (vb2_is_busy(peer_vq))
429		return -EBUSY;
430
431	dprintk(ctx->dev, "Trying to set the OUTPUT format to:\n");
432	visl_print_fmt(ctx, f);
433
434	ret = visl_try_fmt_vid_out(file, priv, f);
435	if (ret)
436		return ret;
437
438	desc = visl_find_coded_fmt_desc(f->fmt.pix_mp.pixelformat);
439	ctx->coded_format_desc = desc;
440	ctx->coded_fmt = *f;
441
442	ret = visl_reset_decoded_fmt(ctx);
443	if (ret)
444		return ret;
445
446	ctx->decoded_fmt.fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace;
447	ctx->decoded_fmt.fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func;
448	ctx->decoded_fmt.fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
449	ctx->decoded_fmt.fmt.pix_mp.quantization = f->fmt.pix_mp.quantization;
450
451	dprintk(ctx->dev, "OUTPUT format was set to:\n");
452	visl_print_fmt(ctx, &ctx->coded_fmt);
453
454	visl_set_current_codec(ctx);
455	return 0;
456}
457
458static int visl_s_fmt_vid_cap(struct file *file, void *priv,
459			      struct v4l2_format *f)
460{
461	struct visl_ctx *ctx = visl_file_to_ctx(file);
462	int ret;
463
464	dprintk(ctx->dev, "Trying to set the CAPTURE format to:\n");
465	visl_print_fmt(ctx, f);
466
467	ret = visl_try_fmt_vid_cap(file, priv, f);
468	if (ret)
469		return ret;
470
471	ctx->decoded_fmt = *f;
472
473	dprintk(ctx->dev, "CAPTURE format was set to:\n");
474	visl_print_fmt(ctx, &ctx->decoded_fmt);
475
476	visl_tpg_init(ctx);
477	return 0;
478}
479
480static int visl_enum_framesizes(struct file *file, void *priv,
481				struct v4l2_frmsizeenum *fsize)
482{
483	const struct visl_coded_format_desc *fmt;
484	struct visl_ctx *ctx = visl_file_to_ctx(file);
485
486	if (fsize->index != 0)
487		return -EINVAL;
488
489	fmt = visl_find_coded_fmt_desc(fsize->pixel_format);
490	if (!fmt) {
491		dprintk(ctx->dev,
492			"Unsupported format for the OUTPUT queue: %d\n",
493			fsize->pixel_format);
494
495		return -EINVAL;
496	}
497
498	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
499	fsize->stepwise = fmt->frmsize;
500	return 0;
501}
502
503const struct v4l2_ioctl_ops visl_ioctl_ops = {
504	.vidioc_querycap		= visl_querycap,
505	.vidioc_enum_framesizes		= visl_enum_framesizes,
506
507	.vidioc_enum_fmt_vid_cap	= visl_enum_fmt_vid_cap,
508	.vidioc_g_fmt_vid_cap_mplane	= visl_g_fmt_vid_cap,
509	.vidioc_try_fmt_vid_cap_mplane	= visl_try_fmt_vid_cap,
510	.vidioc_s_fmt_vid_cap_mplane	= visl_s_fmt_vid_cap,
511
512	.vidioc_enum_fmt_vid_out	= visl_enum_fmt_vid_out,
513	.vidioc_g_fmt_vid_out_mplane	= visl_g_fmt_vid_out,
514	.vidioc_try_fmt_vid_out_mplane	= visl_try_fmt_vid_out,
515	.vidioc_s_fmt_vid_out_mplane	= visl_s_fmt_vid_out,
516
517	.vidioc_reqbufs			= v4l2_m2m_ioctl_reqbufs,
518	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
519	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,
520	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,
521	.vidioc_prepare_buf		= v4l2_m2m_ioctl_prepare_buf,
522	.vidioc_create_bufs		= v4l2_m2m_ioctl_create_bufs,
523	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,
524
525	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
526	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
527
528	.vidioc_decoder_cmd		= v4l2_m2m_ioctl_stateless_decoder_cmd,
529	.vidioc_try_decoder_cmd		= v4l2_m2m_ioctl_stateless_try_decoder_cmd,
530
531	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
532	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
533};
534
535static int visl_queue_setup(struct vb2_queue *vq,
536			    unsigned int *nbuffers,
537			    unsigned int *num_planes,
538			    unsigned int sizes[],
539			    struct device *alloc_devs[])
540{
541	struct visl_ctx *ctx = vb2_get_drv_priv(vq);
542	struct v4l2_format *f;
543	u32 i;
544	char *qname;
545
546	if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
547		f = &ctx->coded_fmt;
548		qname = "Output";
549	} else {
550		f = &ctx->decoded_fmt;
551		qname = "Capture";
552	}
553
554	if (*num_planes) {
555		if (*num_planes != f->fmt.pix_mp.num_planes)
556			return -EINVAL;
557
558		for (i = 0; i < f->fmt.pix_mp.num_planes; i++) {
559			if (sizes[i] < f->fmt.pix_mp.plane_fmt[i].sizeimage)
560				return -EINVAL;
561		}
562	} else {
563		*num_planes = f->fmt.pix_mp.num_planes;
564		for (i = 0; i < f->fmt.pix_mp.num_planes; i++)
565			sizes[i] = f->fmt.pix_mp.plane_fmt[i].sizeimage;
566	}
567
568	dprintk(ctx->dev, "%s: %d buffer(s) requested, num_planes=%d.\n",
569		qname, *nbuffers, *num_planes);
570
571	for (i = 0; i < f->fmt.pix_mp.num_planes; i++)
572		dprintk(ctx->dev, "plane[%d].sizeimage=%d\n",
573			i, f->fmt.pix_mp.plane_fmt[i].sizeimage);
574
575	return 0;
576}
577
578static void visl_queue_cleanup(struct vb2_queue *vq, u32 state)
579{
580	struct visl_ctx *ctx = vb2_get_drv_priv(vq);
581	struct vb2_v4l2_buffer *vbuf;
582
583	dprintk(ctx->dev, "Cleaning up queues\n");
584	for (;;) {
585		if (V4L2_TYPE_IS_OUTPUT(vq->type))
586			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
587		else
588			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
589
590		if (!vbuf)
591			break;
592
593		v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
594					   &ctx->hdl);
595		dprintk(ctx->dev, "Marked request %p as complete\n",
596			vbuf->vb2_buf.req_obj.req);
597
598		v4l2_m2m_buf_done(vbuf, state);
599		dprintk(ctx->dev,
600			"Marked buffer %llu as done, state is %d\n",
601			vbuf->vb2_buf.timestamp,
602			state);
603	}
604}
605
606static int visl_buf_out_validate(struct vb2_buffer *vb)
607{
608	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
609
610	vbuf->field = V4L2_FIELD_NONE;
611	return 0;
612}
613
614static int visl_buf_prepare(struct vb2_buffer *vb)
615{
616	struct vb2_queue *vq = vb->vb2_queue;
617	struct visl_ctx *ctx = vb2_get_drv_priv(vq);
618	u32 plane_sz = vb2_plane_size(vb, 0);
619	struct v4l2_pix_format *pix_fmt;
620
621	if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
622		pix_fmt = &ctx->coded_fmt.fmt.pix;
623	} else {
624		pix_fmt = &ctx->decoded_fmt.fmt.pix;
625		vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage);
626	}
627
628	if (plane_sz < pix_fmt->sizeimage) {
629		v4l2_err(&ctx->dev->v4l2_dev, "plane[0] size is %d, sizeimage is %d\n",
630			 plane_sz, pix_fmt->sizeimage);
631		return -EINVAL;
632	}
633
634	return 0;
635}
636
637static int visl_start_streaming(struct vb2_queue *vq, unsigned int count)
638{
639	struct visl_ctx *ctx = vb2_get_drv_priv(vq);
640	struct visl_q_data *q_data = get_q_data(ctx, vq->type);
641	int rc = 0;
642
643	if (!q_data) {
644		rc = -EINVAL;
645		goto err;
646	}
647
648	q_data->sequence = 0;
649
650	if (V4L2_TYPE_IS_CAPTURE(vq->type)) {
651		ctx->capture_streamon_jiffies = get_jiffies_64();
652		return 0;
653	}
654
655	if (WARN_ON(!ctx->coded_format_desc)) {
656		rc =  -EINVAL;
657		goto err;
658	}
659
660	return 0;
661
662err:
663	visl_queue_cleanup(vq, VB2_BUF_STATE_QUEUED);
664	return rc;
665}
666
667static void visl_stop_streaming(struct vb2_queue *vq)
668{
669	struct visl_ctx *ctx = vb2_get_drv_priv(vq);
670
671	dprintk(ctx->dev, "Stop streaming\n");
672	visl_queue_cleanup(vq, VB2_BUF_STATE_ERROR);
673
674	if (!keep_bitstream_buffers)
675		visl_debugfs_clear_bitstream(ctx->dev);
676}
677
678static void visl_buf_queue(struct vb2_buffer *vb)
679{
680	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
681	struct visl_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
682
683	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
684}
685
686static void visl_buf_request_complete(struct vb2_buffer *vb)
687{
688	struct visl_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
689
690	v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
691}
692
693static const struct vb2_ops visl_qops = {
694	.queue_setup          = visl_queue_setup,
695	.buf_out_validate     = visl_buf_out_validate,
696	.buf_prepare          = visl_buf_prepare,
697	.buf_queue            = visl_buf_queue,
698	.start_streaming      = visl_start_streaming,
699	.stop_streaming       = visl_stop_streaming,
700	.wait_prepare         = vb2_ops_wait_prepare,
701	.wait_finish          = vb2_ops_wait_finish,
702	.buf_request_complete = visl_buf_request_complete,
703};
704
705int visl_queue_init(void *priv, struct vb2_queue *src_vq,
706		    struct vb2_queue *dst_vq)
707{
708	struct visl_ctx *ctx = priv;
709	int ret;
710
711	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
712	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
713	src_vq->drv_priv = ctx;
714	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
715	src_vq->ops = &visl_qops;
716	src_vq->mem_ops = &vb2_vmalloc_memops;
717	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
718	src_vq->lock = &ctx->vb_mutex;
719	src_vq->supports_requests = true;
720	src_vq->subsystem_flags |= VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
721
722	ret = vb2_queue_init(src_vq);
723	if (ret)
724		return ret;
725
726	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
727	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
728	dst_vq->drv_priv = ctx;
729	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
730	dst_vq->ops = &visl_qops;
731	dst_vq->mem_ops = &vb2_vmalloc_memops;
732	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
733	dst_vq->lock = &ctx->vb_mutex;
734
735	return vb2_queue_init(dst_vq);
736}
737
738int visl_request_validate(struct media_request *req)
739{
740	struct media_request_object *obj;
741	struct visl_ctx *ctx = NULL;
742	unsigned int count;
743
744	list_for_each_entry(obj, &req->objects, list) {
745		struct vb2_buffer *vb;
746
747		if (vb2_request_object_is_buffer(obj)) {
748			vb = container_of(obj, struct vb2_buffer, req_obj);
749			ctx = vb2_get_drv_priv(vb->vb2_queue);
750
751			break;
752		}
753	}
754
755	if (!ctx)
756		return -ENOENT;
757
758	count = vb2_request_buffer_cnt(req);
759	if (!count) {
760		v4l2_err(&ctx->dev->v4l2_dev,
761			 "No buffer was provided with the request\n");
762		return -ENOENT;
763	} else if (count > 1) {
764		v4l2_err(&ctx->dev->v4l2_dev,
765			 "More than one buffer was provided with the request\n");
766		return -EINVAL;
767	}
768
769	return vb2_request_validate(req);
770}
771