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
visl_set_current_codec(struct visl_ctx * ctx)20 static 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
visl_print_fmt(struct visl_ctx * ctx,const struct v4l2_format * f)50 static 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
visl_tpg_init(struct visl_ctx * ctx)78 static 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;
124 err_alloc:
125 return ret;
126 err_fourcc:
127 tpg_free(&ctx->tpg);
128 return ret;
129 }
130
131 static const u32 visl_decoded_fmts[] = {
132 V4L2_PIX_FMT_NV12,
133 V4L2_PIX_FMT_YUV420,
134 };
135
136 const 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
223 const size_t num_coded_fmts = ARRAY_SIZE(visl_coded_fmts);
224
225 static const struct visl_coded_format_desc*
visl_find_coded_fmt_desc(u32 fourcc)226 visl_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
visl_init_fmt(struct v4l2_format * f,u32 fourcc)238 static 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
visl_reset_coded_fmt(struct visl_ctx * ctx)248 static 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
visl_reset_decoded_fmt(struct visl_ctx * ctx)269 static 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
visl_set_default_format(struct visl_ctx * ctx)289 int visl_set_default_format(struct visl_ctx *ctx)
290 {
291 visl_reset_coded_fmt(ctx);
292 return visl_reset_decoded_fmt(ctx);
293 }
294
get_q_data(struct visl_ctx * ctx,enum v4l2_buf_type type)295 static 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
visl_querycap(struct file * file,void * priv,struct v4l2_capability * cap)311 static 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
visl_enum_fmt_vid_cap(struct file * file,void * priv,struct v4l2_fmtdesc * f)322 static 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
visl_enum_fmt_vid_out(struct file * file,void * priv,struct v4l2_fmtdesc * f)334 static 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
visl_g_fmt_vid_cap(struct file * file,void * priv,struct v4l2_format * f)344 static 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
visl_g_fmt_vid_out(struct file * file,void * priv,struct v4l2_format * f)353 static 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
visl_try_fmt_vid_cap(struct file * file,void * priv,struct v4l2_format * f)362 static 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
visl_try_fmt_vid_out(struct file * file,void * priv,struct v4l2_format * f)392 static 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
visl_s_fmt_vid_out(struct file * file,void * priv,struct v4l2_format * f)418 static 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
visl_s_fmt_vid_cap(struct file * file,void * priv,struct v4l2_format * f)458 static 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
visl_enum_framesizes(struct file * file,void * priv,struct v4l2_frmsizeenum * fsize)480 static 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
503 const 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_subscribe_event = v4l2_ctrl_subscribe_event,
529 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
530 };
531
visl_queue_setup(struct vb2_queue * vq,unsigned int * nbuffers,unsigned int * num_planes,unsigned int sizes[],struct device * alloc_devs[])532 static int visl_queue_setup(struct vb2_queue *vq,
533 unsigned int *nbuffers,
534 unsigned int *num_planes,
535 unsigned int sizes[],
536 struct device *alloc_devs[])
537 {
538 struct visl_ctx *ctx = vb2_get_drv_priv(vq);
539 struct v4l2_format *f;
540 u32 i;
541 char *qname;
542
543 if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
544 f = &ctx->coded_fmt;
545 qname = "Output";
546 } else {
547 f = &ctx->decoded_fmt;
548 qname = "Capture";
549 }
550
551 if (*num_planes) {
552 if (*num_planes != f->fmt.pix_mp.num_planes)
553 return -EINVAL;
554
555 for (i = 0; i < f->fmt.pix_mp.num_planes; i++) {
556 if (sizes[i] < f->fmt.pix_mp.plane_fmt[i].sizeimage)
557 return -EINVAL;
558 }
559 } else {
560 *num_planes = f->fmt.pix_mp.num_planes;
561 for (i = 0; i < f->fmt.pix_mp.num_planes; i++)
562 sizes[i] = f->fmt.pix_mp.plane_fmt[i].sizeimage;
563 }
564
565 dprintk(ctx->dev, "%s: %d buffer(s) requested, num_planes=%d.\n",
566 qname, *nbuffers, *num_planes);
567
568 for (i = 0; i < f->fmt.pix_mp.num_planes; i++)
569 dprintk(ctx->dev, "plane[%d].sizeimage=%d\n",
570 i, f->fmt.pix_mp.plane_fmt[i].sizeimage);
571
572 return 0;
573 }
574
visl_queue_cleanup(struct vb2_queue * vq,u32 state)575 static void visl_queue_cleanup(struct vb2_queue *vq, u32 state)
576 {
577 struct visl_ctx *ctx = vb2_get_drv_priv(vq);
578 struct vb2_v4l2_buffer *vbuf;
579
580 dprintk(ctx->dev, "Cleaning up queues\n");
581 for (;;) {
582 if (V4L2_TYPE_IS_OUTPUT(vq->type))
583 vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
584 else
585 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
586
587 if (!vbuf)
588 break;
589
590 v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
591 &ctx->hdl);
592 dprintk(ctx->dev, "Marked request %p as complete\n",
593 vbuf->vb2_buf.req_obj.req);
594
595 v4l2_m2m_buf_done(vbuf, state);
596 dprintk(ctx->dev,
597 "Marked buffer %llu as done, state is %d\n",
598 vbuf->vb2_buf.timestamp,
599 state);
600 }
601 }
602
visl_buf_out_validate(struct vb2_buffer * vb)603 static int visl_buf_out_validate(struct vb2_buffer *vb)
604 {
605 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
606
607 vbuf->field = V4L2_FIELD_NONE;
608 return 0;
609 }
610
visl_buf_prepare(struct vb2_buffer * vb)611 static int visl_buf_prepare(struct vb2_buffer *vb)
612 {
613 struct vb2_queue *vq = vb->vb2_queue;
614 struct visl_ctx *ctx = vb2_get_drv_priv(vq);
615 u32 plane_sz = vb2_plane_size(vb, 0);
616 struct v4l2_pix_format *pix_fmt;
617
618 if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
619 pix_fmt = &ctx->coded_fmt.fmt.pix;
620 } else {
621 pix_fmt = &ctx->decoded_fmt.fmt.pix;
622 vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage);
623 }
624
625 if (plane_sz < pix_fmt->sizeimage) {
626 v4l2_err(&ctx->dev->v4l2_dev, "plane[0] size is %d, sizeimage is %d\n",
627 plane_sz, pix_fmt->sizeimage);
628 return -EINVAL;
629 }
630
631 return 0;
632 }
633
visl_start_streaming(struct vb2_queue * vq,unsigned int count)634 static int visl_start_streaming(struct vb2_queue *vq, unsigned int count)
635 {
636 struct visl_ctx *ctx = vb2_get_drv_priv(vq);
637 struct visl_q_data *q_data = get_q_data(ctx, vq->type);
638 int rc = 0;
639
640 if (!q_data) {
641 rc = -EINVAL;
642 goto err;
643 }
644
645 q_data->sequence = 0;
646
647 if (V4L2_TYPE_IS_CAPTURE(vq->type)) {
648 ctx->capture_streamon_jiffies = get_jiffies_64();
649 return 0;
650 }
651
652 if (WARN_ON(!ctx->coded_format_desc)) {
653 rc = -EINVAL;
654 goto err;
655 }
656
657 return 0;
658
659 err:
660 visl_queue_cleanup(vq, VB2_BUF_STATE_QUEUED);
661 return rc;
662 }
663
visl_stop_streaming(struct vb2_queue * vq)664 static void visl_stop_streaming(struct vb2_queue *vq)
665 {
666 struct visl_ctx *ctx = vb2_get_drv_priv(vq);
667
668 dprintk(ctx->dev, "Stop streaming\n");
669 visl_queue_cleanup(vq, VB2_BUF_STATE_ERROR);
670
671 if (!keep_bitstream_buffers)
672 visl_debugfs_clear_bitstream(ctx->dev);
673 }
674
visl_buf_queue(struct vb2_buffer * vb)675 static void visl_buf_queue(struct vb2_buffer *vb)
676 {
677 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
678 struct visl_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
679
680 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
681 }
682
visl_buf_request_complete(struct vb2_buffer * vb)683 static void visl_buf_request_complete(struct vb2_buffer *vb)
684 {
685 struct visl_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
686
687 v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
688 }
689
690 static const struct vb2_ops visl_qops = {
691 .queue_setup = visl_queue_setup,
692 .buf_out_validate = visl_buf_out_validate,
693 .buf_prepare = visl_buf_prepare,
694 .buf_queue = visl_buf_queue,
695 .start_streaming = visl_start_streaming,
696 .stop_streaming = visl_stop_streaming,
697 .wait_prepare = vb2_ops_wait_prepare,
698 .wait_finish = vb2_ops_wait_finish,
699 .buf_request_complete = visl_buf_request_complete,
700 };
701
visl_queue_init(void * priv,struct vb2_queue * src_vq,struct vb2_queue * dst_vq)702 int visl_queue_init(void *priv, struct vb2_queue *src_vq,
703 struct vb2_queue *dst_vq)
704 {
705 struct visl_ctx *ctx = priv;
706 int ret;
707
708 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
709 src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
710 src_vq->drv_priv = ctx;
711 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
712 src_vq->ops = &visl_qops;
713 src_vq->mem_ops = &vb2_vmalloc_memops;
714 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
715 src_vq->lock = &ctx->vb_mutex;
716 src_vq->supports_requests = true;
717 src_vq->subsystem_flags |= VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
718
719 ret = vb2_queue_init(src_vq);
720 if (ret)
721 return ret;
722
723 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
724 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
725 dst_vq->drv_priv = ctx;
726 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
727 dst_vq->ops = &visl_qops;
728 dst_vq->mem_ops = &vb2_vmalloc_memops;
729 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
730 dst_vq->lock = &ctx->vb_mutex;
731
732 return vb2_queue_init(dst_vq);
733 }
734
visl_request_validate(struct media_request * req)735 int visl_request_validate(struct media_request *req)
736 {
737 struct media_request_object *obj;
738 struct visl_ctx *ctx = NULL;
739 unsigned int count;
740
741 list_for_each_entry(obj, &req->objects, list) {
742 struct vb2_buffer *vb;
743
744 if (vb2_request_object_is_buffer(obj)) {
745 vb = container_of(obj, struct vb2_buffer, req_obj);
746 ctx = vb2_get_drv_priv(vb->vb2_queue);
747
748 break;
749 }
750 }
751
752 if (!ctx)
753 return -ENOENT;
754
755 count = vb2_request_buffer_cnt(req);
756 if (!count) {
757 v4l2_err(&ctx->dev->v4l2_dev,
758 "No buffer was provided with the request\n");
759 return -ENOENT;
760 } else if (count > 1) {
761 v4l2_err(&ctx->dev->v4l2_dev,
762 "More than one buffer was provided with the request\n");
763 return -EINVAL;
764 }
765
766 return vb2_request_validate(req);
767 }
768