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