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