162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Contains the driver implementation for the V4L2 stateless interface. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/debugfs.h> 762306a36Sopenharmony_ci#include <linux/font.h> 862306a36Sopenharmony_ci#include <media/v4l2-event.h> 962306a36Sopenharmony_ci#include <media/v4l2-ioctl.h> 1062306a36Sopenharmony_ci#include <media/videobuf2-vmalloc.h> 1162306a36Sopenharmony_ci#include <media/videobuf2-v4l2.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include "visl-video.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "visl.h" 1662306a36Sopenharmony_ci#include "visl-debugfs.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define MIN_CODED_SZ (1024U * 256U) 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic void visl_set_current_codec(struct visl_ctx *ctx) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci u32 fourcc = ctx->coded_fmt.fmt.pix_mp.pixelformat; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci switch (fourcc) { 2562306a36Sopenharmony_ci case V4L2_PIX_FMT_FWHT_STATELESS: 2662306a36Sopenharmony_ci ctx->current_codec = VISL_CODEC_FWHT; 2762306a36Sopenharmony_ci break; 2862306a36Sopenharmony_ci case V4L2_PIX_FMT_MPEG2_SLICE: 2962306a36Sopenharmony_ci ctx->current_codec = VISL_CODEC_MPEG2; 3062306a36Sopenharmony_ci break; 3162306a36Sopenharmony_ci case V4L2_PIX_FMT_VP8_FRAME: 3262306a36Sopenharmony_ci ctx->current_codec = VISL_CODEC_VP8; 3362306a36Sopenharmony_ci break; 3462306a36Sopenharmony_ci case V4L2_PIX_FMT_VP9_FRAME: 3562306a36Sopenharmony_ci ctx->current_codec = VISL_CODEC_VP9; 3662306a36Sopenharmony_ci break; 3762306a36Sopenharmony_ci case V4L2_PIX_FMT_H264_SLICE: 3862306a36Sopenharmony_ci ctx->current_codec = VISL_CODEC_H264; 3962306a36Sopenharmony_ci break; 4062306a36Sopenharmony_ci case V4L2_PIX_FMT_HEVC_SLICE: 4162306a36Sopenharmony_ci ctx->current_codec = VISL_CODEC_HEVC; 4262306a36Sopenharmony_ci break; 4362306a36Sopenharmony_ci default: 4462306a36Sopenharmony_ci dprintk(ctx->dev, "Warning: unsupported fourcc: %d\n", fourcc); 4562306a36Sopenharmony_ci ctx->current_codec = VISL_CODEC_NONE; 4662306a36Sopenharmony_ci break; 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic void visl_print_fmt(struct visl_ctx *ctx, const struct v4l2_format *f) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci const struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; 5362306a36Sopenharmony_ci u32 i; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci dprintk(ctx->dev, "width: %d\n", pix_mp->width); 5662306a36Sopenharmony_ci dprintk(ctx->dev, "height: %d\n", pix_mp->height); 5762306a36Sopenharmony_ci dprintk(ctx->dev, "pixelformat: %c%c%c%c\n", 5862306a36Sopenharmony_ci pix_mp->pixelformat, 5962306a36Sopenharmony_ci (pix_mp->pixelformat >> 8) & 0xff, 6062306a36Sopenharmony_ci (pix_mp->pixelformat >> 16) & 0xff, 6162306a36Sopenharmony_ci (pix_mp->pixelformat >> 24) & 0xff); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci dprintk(ctx->dev, "field: %d\n", pix_mp->field); 6462306a36Sopenharmony_ci dprintk(ctx->dev, "colorspace: %d\n", pix_mp->colorspace); 6562306a36Sopenharmony_ci dprintk(ctx->dev, "num_planes: %d\n", pix_mp->num_planes); 6662306a36Sopenharmony_ci dprintk(ctx->dev, "flags: %d\n", pix_mp->flags); 6762306a36Sopenharmony_ci dprintk(ctx->dev, "quantization: %d\n", pix_mp->quantization); 6862306a36Sopenharmony_ci dprintk(ctx->dev, "xfer_func: %d\n", pix_mp->xfer_func); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci for (i = 0; i < pix_mp->num_planes; i++) { 7162306a36Sopenharmony_ci dprintk(ctx->dev, 7262306a36Sopenharmony_ci "plane[%d]: sizeimage: %d\n", i, pix_mp->plane_fmt[i].sizeimage); 7362306a36Sopenharmony_ci dprintk(ctx->dev, 7462306a36Sopenharmony_ci "plane[%d]: bytesperline: %d\n", i, pix_mp->plane_fmt[i].bytesperline); 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic int visl_tpg_init(struct visl_ctx *ctx) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci const struct font_desc *font; 8162306a36Sopenharmony_ci const char *font_name = "VGA8x16"; 8262306a36Sopenharmony_ci int ret; 8362306a36Sopenharmony_ci u32 width = ctx->decoded_fmt.fmt.pix_mp.width; 8462306a36Sopenharmony_ci u32 height = ctx->decoded_fmt.fmt.pix_mp.height; 8562306a36Sopenharmony_ci struct v4l2_pix_format_mplane *f = &ctx->decoded_fmt.fmt.pix_mp; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci tpg_free(&ctx->tpg); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci font = find_font(font_name); 9062306a36Sopenharmony_ci if (font) { 9162306a36Sopenharmony_ci tpg_init(&ctx->tpg, width, height); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci ret = tpg_alloc(&ctx->tpg, width); 9462306a36Sopenharmony_ci if (ret) 9562306a36Sopenharmony_ci goto err_alloc; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci tpg_set_font(font->data); 9862306a36Sopenharmony_ci ret = tpg_s_fourcc(&ctx->tpg, 9962306a36Sopenharmony_ci f->pixelformat); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (!ret) 10262306a36Sopenharmony_ci goto err_fourcc; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci tpg_reset_source(&ctx->tpg, width, height, f->field); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci tpg_s_pattern(&ctx->tpg, TPG_PAT_75_COLORBAR); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci tpg_s_field(&ctx->tpg, f->field, false); 10962306a36Sopenharmony_ci tpg_s_colorspace(&ctx->tpg, f->colorspace); 11062306a36Sopenharmony_ci tpg_s_ycbcr_enc(&ctx->tpg, f->ycbcr_enc); 11162306a36Sopenharmony_ci tpg_s_quantization(&ctx->tpg, f->quantization); 11262306a36Sopenharmony_ci tpg_s_xfer_func(&ctx->tpg, f->xfer_func); 11362306a36Sopenharmony_ci } else { 11462306a36Sopenharmony_ci v4l2_err(&ctx->dev->v4l2_dev, 11562306a36Sopenharmony_ci "Font %s not found\n", font_name); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci return -EINVAL; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci dprintk(ctx->dev, "Initialized the V4L2 test pattern generator, w=%d, h=%d, max_w=%d\n", 12162306a36Sopenharmony_ci width, height, width); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci return 0; 12462306a36Sopenharmony_cierr_alloc: 12562306a36Sopenharmony_ci return ret; 12662306a36Sopenharmony_cierr_fourcc: 12762306a36Sopenharmony_ci tpg_free(&ctx->tpg); 12862306a36Sopenharmony_ci return ret; 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic const u32 visl_decoded_fmts[] = { 13262306a36Sopenharmony_ci V4L2_PIX_FMT_NV12, 13362306a36Sopenharmony_ci V4L2_PIX_FMT_YUV420, 13462306a36Sopenharmony_ci}; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ciconst struct visl_coded_format_desc visl_coded_fmts[] = { 13762306a36Sopenharmony_ci { 13862306a36Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_FWHT_STATELESS, 13962306a36Sopenharmony_ci .frmsize = { 14062306a36Sopenharmony_ci .min_width = 640, 14162306a36Sopenharmony_ci .max_width = 4096, 14262306a36Sopenharmony_ci .step_width = 1, 14362306a36Sopenharmony_ci .min_height = 360, 14462306a36Sopenharmony_ci .max_height = 2160, 14562306a36Sopenharmony_ci .step_height = 1, 14662306a36Sopenharmony_ci }, 14762306a36Sopenharmony_ci .ctrls = &visl_fwht_ctrls, 14862306a36Sopenharmony_ci .num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts), 14962306a36Sopenharmony_ci .decoded_fmts = visl_decoded_fmts, 15062306a36Sopenharmony_ci }, 15162306a36Sopenharmony_ci { 15262306a36Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_MPEG2_SLICE, 15362306a36Sopenharmony_ci .frmsize = { 15462306a36Sopenharmony_ci .min_width = 16, 15562306a36Sopenharmony_ci .max_width = 1920, 15662306a36Sopenharmony_ci .step_width = 1, 15762306a36Sopenharmony_ci .min_height = 16, 15862306a36Sopenharmony_ci .max_height = 1152, 15962306a36Sopenharmony_ci .step_height = 1, 16062306a36Sopenharmony_ci }, 16162306a36Sopenharmony_ci .ctrls = &visl_mpeg2_ctrls, 16262306a36Sopenharmony_ci .num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts), 16362306a36Sopenharmony_ci .decoded_fmts = visl_decoded_fmts, 16462306a36Sopenharmony_ci }, 16562306a36Sopenharmony_ci { 16662306a36Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_VP8_FRAME, 16762306a36Sopenharmony_ci .frmsize = { 16862306a36Sopenharmony_ci .min_width = 64, 16962306a36Sopenharmony_ci .max_width = 16383, 17062306a36Sopenharmony_ci .step_width = 1, 17162306a36Sopenharmony_ci .min_height = 64, 17262306a36Sopenharmony_ci .max_height = 16383, 17362306a36Sopenharmony_ci .step_height = 1, 17462306a36Sopenharmony_ci }, 17562306a36Sopenharmony_ci .ctrls = &visl_vp8_ctrls, 17662306a36Sopenharmony_ci .num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts), 17762306a36Sopenharmony_ci .decoded_fmts = visl_decoded_fmts, 17862306a36Sopenharmony_ci }, 17962306a36Sopenharmony_ci { 18062306a36Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_VP9_FRAME, 18162306a36Sopenharmony_ci .frmsize = { 18262306a36Sopenharmony_ci .min_width = 64, 18362306a36Sopenharmony_ci .max_width = 8192, 18462306a36Sopenharmony_ci .step_width = 1, 18562306a36Sopenharmony_ci .min_height = 64, 18662306a36Sopenharmony_ci .max_height = 4352, 18762306a36Sopenharmony_ci .step_height = 1, 18862306a36Sopenharmony_ci }, 18962306a36Sopenharmony_ci .ctrls = &visl_vp9_ctrls, 19062306a36Sopenharmony_ci .num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts), 19162306a36Sopenharmony_ci .decoded_fmts = visl_decoded_fmts, 19262306a36Sopenharmony_ci }, 19362306a36Sopenharmony_ci { 19462306a36Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_H264_SLICE, 19562306a36Sopenharmony_ci .frmsize = { 19662306a36Sopenharmony_ci .min_width = 64, 19762306a36Sopenharmony_ci .max_width = 4096, 19862306a36Sopenharmony_ci .step_width = 1, 19962306a36Sopenharmony_ci .min_height = 64, 20062306a36Sopenharmony_ci .max_height = 2304, 20162306a36Sopenharmony_ci .step_height = 1, 20262306a36Sopenharmony_ci }, 20362306a36Sopenharmony_ci .ctrls = &visl_h264_ctrls, 20462306a36Sopenharmony_ci .num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts), 20562306a36Sopenharmony_ci .decoded_fmts = visl_decoded_fmts, 20662306a36Sopenharmony_ci }, 20762306a36Sopenharmony_ci { 20862306a36Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_HEVC_SLICE, 20962306a36Sopenharmony_ci .frmsize = { 21062306a36Sopenharmony_ci .min_width = 64, 21162306a36Sopenharmony_ci .max_width = 4096, 21262306a36Sopenharmony_ci .step_width = 1, 21362306a36Sopenharmony_ci .min_height = 64, 21462306a36Sopenharmony_ci .max_height = 2304, 21562306a36Sopenharmony_ci .step_height = 1, 21662306a36Sopenharmony_ci }, 21762306a36Sopenharmony_ci .ctrls = &visl_hevc_ctrls, 21862306a36Sopenharmony_ci .num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts), 21962306a36Sopenharmony_ci .decoded_fmts = visl_decoded_fmts, 22062306a36Sopenharmony_ci }, 22162306a36Sopenharmony_ci}; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ciconst size_t num_coded_fmts = ARRAY_SIZE(visl_coded_fmts); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic const struct visl_coded_format_desc* 22662306a36Sopenharmony_civisl_find_coded_fmt_desc(u32 fourcc) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci unsigned int i; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(visl_coded_fmts); i++) { 23162306a36Sopenharmony_ci if (visl_coded_fmts[i].pixelformat == fourcc) 23262306a36Sopenharmony_ci return &visl_coded_fmts[i]; 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci return NULL; 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic void visl_init_fmt(struct v4l2_format *f, u32 fourcc) 23962306a36Sopenharmony_ci{ memset(f, 0, sizeof(*f)); 24062306a36Sopenharmony_ci f->fmt.pix_mp.pixelformat = fourcc; 24162306a36Sopenharmony_ci f->fmt.pix_mp.field = V4L2_FIELD_NONE; 24262306a36Sopenharmony_ci f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709; 24362306a36Sopenharmony_ci f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 24462306a36Sopenharmony_ci f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; 24562306a36Sopenharmony_ci f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic void visl_reset_coded_fmt(struct visl_ctx *ctx) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci struct v4l2_format *f = &ctx->coded_fmt; 25162306a36Sopenharmony_ci struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci ctx->coded_format_desc = &visl_coded_fmts[0]; 25462306a36Sopenharmony_ci visl_init_fmt(f, ctx->coded_format_desc->pixelformat); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 25762306a36Sopenharmony_ci f->fmt.pix_mp.width = ctx->coded_format_desc->frmsize.min_width; 25862306a36Sopenharmony_ci f->fmt.pix_mp.height = ctx->coded_format_desc->frmsize.min_height; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci pix_mp->num_planes = 1; 26162306a36Sopenharmony_ci pix_mp->plane_fmt[0].sizeimage = pix_mp->width * pix_mp->height * 8; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci dprintk(ctx->dev, "OUTPUT format was set to:\n"); 26462306a36Sopenharmony_ci visl_print_fmt(ctx, &ctx->coded_fmt); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci visl_set_current_codec(ctx); 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistatic int visl_reset_decoded_fmt(struct visl_ctx *ctx) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci struct v4l2_format *f = &ctx->decoded_fmt; 27262306a36Sopenharmony_ci u32 decoded_fmt = ctx->coded_format_desc[0].decoded_fmts[0]; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci visl_init_fmt(f, decoded_fmt); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci v4l2_fill_pixfmt_mp(&f->fmt.pix_mp, 27962306a36Sopenharmony_ci ctx->coded_format_desc->decoded_fmts[0], 28062306a36Sopenharmony_ci ctx->coded_fmt.fmt.pix_mp.width, 28162306a36Sopenharmony_ci ctx->coded_fmt.fmt.pix_mp.height); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci dprintk(ctx->dev, "CAPTURE format was set to:\n"); 28462306a36Sopenharmony_ci visl_print_fmt(ctx, &ctx->decoded_fmt); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci return visl_tpg_init(ctx); 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ciint visl_set_default_format(struct visl_ctx *ctx) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci visl_reset_coded_fmt(ctx); 29262306a36Sopenharmony_ci return visl_reset_decoded_fmt(ctx); 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic struct visl_q_data *get_q_data(struct visl_ctx *ctx, 29662306a36Sopenharmony_ci enum v4l2_buf_type type) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci switch (type) { 29962306a36Sopenharmony_ci case V4L2_BUF_TYPE_VIDEO_OUTPUT: 30062306a36Sopenharmony_ci case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 30162306a36Sopenharmony_ci return &ctx->q_data[V4L2_M2M_SRC]; 30262306a36Sopenharmony_ci case V4L2_BUF_TYPE_VIDEO_CAPTURE: 30362306a36Sopenharmony_ci case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 30462306a36Sopenharmony_ci return &ctx->q_data[V4L2_M2M_DST]; 30562306a36Sopenharmony_ci default: 30662306a36Sopenharmony_ci break; 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci return NULL; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cistatic int visl_querycap(struct file *file, void *priv, 31262306a36Sopenharmony_ci struct v4l2_capability *cap) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci strscpy(cap->driver, VISL_NAME, sizeof(cap->driver)); 31562306a36Sopenharmony_ci strscpy(cap->card, VISL_NAME, sizeof(cap->card)); 31662306a36Sopenharmony_ci snprintf(cap->bus_info, sizeof(cap->bus_info), 31762306a36Sopenharmony_ci "platform:%s", VISL_NAME); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci return 0; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic int visl_enum_fmt_vid_cap(struct file *file, void *priv, 32362306a36Sopenharmony_ci struct v4l2_fmtdesc *f) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci struct visl_ctx *ctx = visl_file_to_ctx(file); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci if (f->index >= ctx->coded_format_desc->num_decoded_fmts) 32862306a36Sopenharmony_ci return -EINVAL; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci f->pixelformat = ctx->coded_format_desc->decoded_fmts[f->index]; 33162306a36Sopenharmony_ci return 0; 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic int visl_enum_fmt_vid_out(struct file *file, void *priv, 33562306a36Sopenharmony_ci struct v4l2_fmtdesc *f) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci if (f->index >= ARRAY_SIZE(visl_coded_fmts)) 33862306a36Sopenharmony_ci return -EINVAL; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci f->pixelformat = visl_coded_fmts[f->index].pixelformat; 34162306a36Sopenharmony_ci return 0; 34262306a36Sopenharmony_ci} 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic int visl_g_fmt_vid_cap(struct file *file, void *priv, 34562306a36Sopenharmony_ci struct v4l2_format *f) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci struct visl_ctx *ctx = visl_file_to_ctx(file); 34862306a36Sopenharmony_ci *f = ctx->decoded_fmt; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci return 0; 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_cistatic int visl_g_fmt_vid_out(struct file *file, void *priv, 35462306a36Sopenharmony_ci struct v4l2_format *f) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci struct visl_ctx *ctx = visl_file_to_ctx(file); 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci *f = ctx->coded_fmt; 35962306a36Sopenharmony_ci return 0; 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic int visl_try_fmt_vid_cap(struct file *file, void *priv, 36362306a36Sopenharmony_ci struct v4l2_format *f) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; 36662306a36Sopenharmony_ci struct visl_ctx *ctx = visl_file_to_ctx(file); 36762306a36Sopenharmony_ci const struct visl_coded_format_desc *coded_desc; 36862306a36Sopenharmony_ci unsigned int i; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci coded_desc = ctx->coded_format_desc; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci for (i = 0; i < coded_desc->num_decoded_fmts; i++) { 37362306a36Sopenharmony_ci if (coded_desc->decoded_fmts[i] == pix_mp->pixelformat) 37462306a36Sopenharmony_ci break; 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci if (i == coded_desc->num_decoded_fmts) 37862306a36Sopenharmony_ci pix_mp->pixelformat = coded_desc->decoded_fmts[0]; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci v4l2_apply_frmsize_constraints(&pix_mp->width, 38162306a36Sopenharmony_ci &pix_mp->height, 38262306a36Sopenharmony_ci &coded_desc->frmsize); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, 38562306a36Sopenharmony_ci pix_mp->width, pix_mp->height); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci pix_mp->field = V4L2_FIELD_NONE; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci return 0; 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic int visl_try_fmt_vid_out(struct file *file, void *priv, 39362306a36Sopenharmony_ci struct v4l2_format *f) 39462306a36Sopenharmony_ci{ 39562306a36Sopenharmony_ci struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; 39662306a36Sopenharmony_ci const struct visl_coded_format_desc *coded_desc; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci coded_desc = visl_find_coded_fmt_desc(pix_mp->pixelformat); 39962306a36Sopenharmony_ci if (!coded_desc) { 40062306a36Sopenharmony_ci pix_mp->pixelformat = visl_coded_fmts[0].pixelformat; 40162306a36Sopenharmony_ci coded_desc = &visl_coded_fmts[0]; 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci v4l2_apply_frmsize_constraints(&pix_mp->width, 40562306a36Sopenharmony_ci &pix_mp->height, 40662306a36Sopenharmony_ci &coded_desc->frmsize); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci pix_mp->field = V4L2_FIELD_NONE; 40962306a36Sopenharmony_ci pix_mp->num_planes = 1; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci if (pix_mp->plane_fmt[0].sizeimage == 0) 41262306a36Sopenharmony_ci pix_mp->plane_fmt[0].sizeimage = max(MIN_CODED_SZ, 41362306a36Sopenharmony_ci pix_mp->width * pix_mp->height * 3); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci return 0; 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cistatic int visl_s_fmt_vid_out(struct file *file, void *priv, 41962306a36Sopenharmony_ci struct v4l2_format *f) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci struct visl_ctx *ctx = visl_file_to_ctx(file); 42262306a36Sopenharmony_ci struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; 42362306a36Sopenharmony_ci const struct visl_coded_format_desc *desc; 42462306a36Sopenharmony_ci struct vb2_queue *peer_vq; 42562306a36Sopenharmony_ci int ret; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci peer_vq = v4l2_m2m_get_vq(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 42862306a36Sopenharmony_ci if (vb2_is_busy(peer_vq)) 42962306a36Sopenharmony_ci return -EBUSY; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci dprintk(ctx->dev, "Trying to set the OUTPUT format to:\n"); 43262306a36Sopenharmony_ci visl_print_fmt(ctx, f); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci ret = visl_try_fmt_vid_out(file, priv, f); 43562306a36Sopenharmony_ci if (ret) 43662306a36Sopenharmony_ci return ret; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci desc = visl_find_coded_fmt_desc(f->fmt.pix_mp.pixelformat); 43962306a36Sopenharmony_ci ctx->coded_format_desc = desc; 44062306a36Sopenharmony_ci ctx->coded_fmt = *f; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci ret = visl_reset_decoded_fmt(ctx); 44362306a36Sopenharmony_ci if (ret) 44462306a36Sopenharmony_ci return ret; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci ctx->decoded_fmt.fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; 44762306a36Sopenharmony_ci ctx->decoded_fmt.fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; 44862306a36Sopenharmony_ci ctx->decoded_fmt.fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; 44962306a36Sopenharmony_ci ctx->decoded_fmt.fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci dprintk(ctx->dev, "OUTPUT format was set to:\n"); 45262306a36Sopenharmony_ci visl_print_fmt(ctx, &ctx->coded_fmt); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci visl_set_current_codec(ctx); 45562306a36Sopenharmony_ci return 0; 45662306a36Sopenharmony_ci} 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistatic int visl_s_fmt_vid_cap(struct file *file, void *priv, 45962306a36Sopenharmony_ci struct v4l2_format *f) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci struct visl_ctx *ctx = visl_file_to_ctx(file); 46262306a36Sopenharmony_ci int ret; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci dprintk(ctx->dev, "Trying to set the CAPTURE format to:\n"); 46562306a36Sopenharmony_ci visl_print_fmt(ctx, f); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci ret = visl_try_fmt_vid_cap(file, priv, f); 46862306a36Sopenharmony_ci if (ret) 46962306a36Sopenharmony_ci return ret; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci ctx->decoded_fmt = *f; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci dprintk(ctx->dev, "CAPTURE format was set to:\n"); 47462306a36Sopenharmony_ci visl_print_fmt(ctx, &ctx->decoded_fmt); 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci visl_tpg_init(ctx); 47762306a36Sopenharmony_ci return 0; 47862306a36Sopenharmony_ci} 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_cistatic int visl_enum_framesizes(struct file *file, void *priv, 48162306a36Sopenharmony_ci struct v4l2_frmsizeenum *fsize) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci const struct visl_coded_format_desc *fmt; 48462306a36Sopenharmony_ci struct visl_ctx *ctx = visl_file_to_ctx(file); 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci if (fsize->index != 0) 48762306a36Sopenharmony_ci return -EINVAL; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci fmt = visl_find_coded_fmt_desc(fsize->pixel_format); 49062306a36Sopenharmony_ci if (!fmt) { 49162306a36Sopenharmony_ci dprintk(ctx->dev, 49262306a36Sopenharmony_ci "Unsupported format for the OUTPUT queue: %d\n", 49362306a36Sopenharmony_ci fsize->pixel_format); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci return -EINVAL; 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; 49962306a36Sopenharmony_ci fsize->stepwise = fmt->frmsize; 50062306a36Sopenharmony_ci return 0; 50162306a36Sopenharmony_ci} 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ciconst struct v4l2_ioctl_ops visl_ioctl_ops = { 50462306a36Sopenharmony_ci .vidioc_querycap = visl_querycap, 50562306a36Sopenharmony_ci .vidioc_enum_framesizes = visl_enum_framesizes, 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci .vidioc_enum_fmt_vid_cap = visl_enum_fmt_vid_cap, 50862306a36Sopenharmony_ci .vidioc_g_fmt_vid_cap_mplane = visl_g_fmt_vid_cap, 50962306a36Sopenharmony_ci .vidioc_try_fmt_vid_cap_mplane = visl_try_fmt_vid_cap, 51062306a36Sopenharmony_ci .vidioc_s_fmt_vid_cap_mplane = visl_s_fmt_vid_cap, 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci .vidioc_enum_fmt_vid_out = visl_enum_fmt_vid_out, 51362306a36Sopenharmony_ci .vidioc_g_fmt_vid_out_mplane = visl_g_fmt_vid_out, 51462306a36Sopenharmony_ci .vidioc_try_fmt_vid_out_mplane = visl_try_fmt_vid_out, 51562306a36Sopenharmony_ci .vidioc_s_fmt_vid_out_mplane = visl_s_fmt_vid_out, 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 51862306a36Sopenharmony_ci .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 51962306a36Sopenharmony_ci .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 52062306a36Sopenharmony_ci .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 52162306a36Sopenharmony_ci .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, 52262306a36Sopenharmony_ci .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 52362306a36Sopenharmony_ci .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci .vidioc_streamon = v4l2_m2m_ioctl_streamon, 52662306a36Sopenharmony_ci .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci .vidioc_decoder_cmd = v4l2_m2m_ioctl_stateless_decoder_cmd, 52962306a36Sopenharmony_ci .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_stateless_try_decoder_cmd, 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 53262306a36Sopenharmony_ci .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 53362306a36Sopenharmony_ci}; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_cistatic int visl_queue_setup(struct vb2_queue *vq, 53662306a36Sopenharmony_ci unsigned int *nbuffers, 53762306a36Sopenharmony_ci unsigned int *num_planes, 53862306a36Sopenharmony_ci unsigned int sizes[], 53962306a36Sopenharmony_ci struct device *alloc_devs[]) 54062306a36Sopenharmony_ci{ 54162306a36Sopenharmony_ci struct visl_ctx *ctx = vb2_get_drv_priv(vq); 54262306a36Sopenharmony_ci struct v4l2_format *f; 54362306a36Sopenharmony_ci u32 i; 54462306a36Sopenharmony_ci char *qname; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci if (V4L2_TYPE_IS_OUTPUT(vq->type)) { 54762306a36Sopenharmony_ci f = &ctx->coded_fmt; 54862306a36Sopenharmony_ci qname = "Output"; 54962306a36Sopenharmony_ci } else { 55062306a36Sopenharmony_ci f = &ctx->decoded_fmt; 55162306a36Sopenharmony_ci qname = "Capture"; 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci if (*num_planes) { 55562306a36Sopenharmony_ci if (*num_planes != f->fmt.pix_mp.num_planes) 55662306a36Sopenharmony_ci return -EINVAL; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci for (i = 0; i < f->fmt.pix_mp.num_planes; i++) { 55962306a36Sopenharmony_ci if (sizes[i] < f->fmt.pix_mp.plane_fmt[i].sizeimage) 56062306a36Sopenharmony_ci return -EINVAL; 56162306a36Sopenharmony_ci } 56262306a36Sopenharmony_ci } else { 56362306a36Sopenharmony_ci *num_planes = f->fmt.pix_mp.num_planes; 56462306a36Sopenharmony_ci for (i = 0; i < f->fmt.pix_mp.num_planes; i++) 56562306a36Sopenharmony_ci sizes[i] = f->fmt.pix_mp.plane_fmt[i].sizeimage; 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci dprintk(ctx->dev, "%s: %d buffer(s) requested, num_planes=%d.\n", 56962306a36Sopenharmony_ci qname, *nbuffers, *num_planes); 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci for (i = 0; i < f->fmt.pix_mp.num_planes; i++) 57262306a36Sopenharmony_ci dprintk(ctx->dev, "plane[%d].sizeimage=%d\n", 57362306a36Sopenharmony_ci i, f->fmt.pix_mp.plane_fmt[i].sizeimage); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci return 0; 57662306a36Sopenharmony_ci} 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_cistatic void visl_queue_cleanup(struct vb2_queue *vq, u32 state) 57962306a36Sopenharmony_ci{ 58062306a36Sopenharmony_ci struct visl_ctx *ctx = vb2_get_drv_priv(vq); 58162306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci dprintk(ctx->dev, "Cleaning up queues\n"); 58462306a36Sopenharmony_ci for (;;) { 58562306a36Sopenharmony_ci if (V4L2_TYPE_IS_OUTPUT(vq->type)) 58662306a36Sopenharmony_ci vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); 58762306a36Sopenharmony_ci else 58862306a36Sopenharmony_ci vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci if (!vbuf) 59162306a36Sopenharmony_ci break; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, 59462306a36Sopenharmony_ci &ctx->hdl); 59562306a36Sopenharmony_ci dprintk(ctx->dev, "Marked request %p as complete\n", 59662306a36Sopenharmony_ci vbuf->vb2_buf.req_obj.req); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci v4l2_m2m_buf_done(vbuf, state); 59962306a36Sopenharmony_ci dprintk(ctx->dev, 60062306a36Sopenharmony_ci "Marked buffer %llu as done, state is %d\n", 60162306a36Sopenharmony_ci vbuf->vb2_buf.timestamp, 60262306a36Sopenharmony_ci state); 60362306a36Sopenharmony_ci } 60462306a36Sopenharmony_ci} 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_cistatic int visl_buf_out_validate(struct vb2_buffer *vb) 60762306a36Sopenharmony_ci{ 60862306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci vbuf->field = V4L2_FIELD_NONE; 61162306a36Sopenharmony_ci return 0; 61262306a36Sopenharmony_ci} 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_cistatic int visl_buf_prepare(struct vb2_buffer *vb) 61562306a36Sopenharmony_ci{ 61662306a36Sopenharmony_ci struct vb2_queue *vq = vb->vb2_queue; 61762306a36Sopenharmony_ci struct visl_ctx *ctx = vb2_get_drv_priv(vq); 61862306a36Sopenharmony_ci u32 plane_sz = vb2_plane_size(vb, 0); 61962306a36Sopenharmony_ci struct v4l2_pix_format *pix_fmt; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci if (V4L2_TYPE_IS_OUTPUT(vq->type)) { 62262306a36Sopenharmony_ci pix_fmt = &ctx->coded_fmt.fmt.pix; 62362306a36Sopenharmony_ci } else { 62462306a36Sopenharmony_ci pix_fmt = &ctx->decoded_fmt.fmt.pix; 62562306a36Sopenharmony_ci vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage); 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci if (plane_sz < pix_fmt->sizeimage) { 62962306a36Sopenharmony_ci v4l2_err(&ctx->dev->v4l2_dev, "plane[0] size is %d, sizeimage is %d\n", 63062306a36Sopenharmony_ci plane_sz, pix_fmt->sizeimage); 63162306a36Sopenharmony_ci return -EINVAL; 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci return 0; 63562306a36Sopenharmony_ci} 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_cistatic int visl_start_streaming(struct vb2_queue *vq, unsigned int count) 63862306a36Sopenharmony_ci{ 63962306a36Sopenharmony_ci struct visl_ctx *ctx = vb2_get_drv_priv(vq); 64062306a36Sopenharmony_ci struct visl_q_data *q_data = get_q_data(ctx, vq->type); 64162306a36Sopenharmony_ci int rc = 0; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci if (!q_data) { 64462306a36Sopenharmony_ci rc = -EINVAL; 64562306a36Sopenharmony_ci goto err; 64662306a36Sopenharmony_ci } 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci q_data->sequence = 0; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci if (V4L2_TYPE_IS_CAPTURE(vq->type)) { 65162306a36Sopenharmony_ci ctx->capture_streamon_jiffies = get_jiffies_64(); 65262306a36Sopenharmony_ci return 0; 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci if (WARN_ON(!ctx->coded_format_desc)) { 65662306a36Sopenharmony_ci rc = -EINVAL; 65762306a36Sopenharmony_ci goto err; 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci return 0; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_cierr: 66362306a36Sopenharmony_ci visl_queue_cleanup(vq, VB2_BUF_STATE_QUEUED); 66462306a36Sopenharmony_ci return rc; 66562306a36Sopenharmony_ci} 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_cistatic void visl_stop_streaming(struct vb2_queue *vq) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci struct visl_ctx *ctx = vb2_get_drv_priv(vq); 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci dprintk(ctx->dev, "Stop streaming\n"); 67262306a36Sopenharmony_ci visl_queue_cleanup(vq, VB2_BUF_STATE_ERROR); 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci if (!keep_bitstream_buffers) 67562306a36Sopenharmony_ci visl_debugfs_clear_bitstream(ctx->dev); 67662306a36Sopenharmony_ci} 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_cistatic void visl_buf_queue(struct vb2_buffer *vb) 67962306a36Sopenharmony_ci{ 68062306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 68162306a36Sopenharmony_ci struct visl_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_cistatic void visl_buf_request_complete(struct vb2_buffer *vb) 68762306a36Sopenharmony_ci{ 68862306a36Sopenharmony_ci struct visl_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl); 69162306a36Sopenharmony_ci} 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_cistatic const struct vb2_ops visl_qops = { 69462306a36Sopenharmony_ci .queue_setup = visl_queue_setup, 69562306a36Sopenharmony_ci .buf_out_validate = visl_buf_out_validate, 69662306a36Sopenharmony_ci .buf_prepare = visl_buf_prepare, 69762306a36Sopenharmony_ci .buf_queue = visl_buf_queue, 69862306a36Sopenharmony_ci .start_streaming = visl_start_streaming, 69962306a36Sopenharmony_ci .stop_streaming = visl_stop_streaming, 70062306a36Sopenharmony_ci .wait_prepare = vb2_ops_wait_prepare, 70162306a36Sopenharmony_ci .wait_finish = vb2_ops_wait_finish, 70262306a36Sopenharmony_ci .buf_request_complete = visl_buf_request_complete, 70362306a36Sopenharmony_ci}; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ciint visl_queue_init(void *priv, struct vb2_queue *src_vq, 70662306a36Sopenharmony_ci struct vb2_queue *dst_vq) 70762306a36Sopenharmony_ci{ 70862306a36Sopenharmony_ci struct visl_ctx *ctx = priv; 70962306a36Sopenharmony_ci int ret; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 71262306a36Sopenharmony_ci src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 71362306a36Sopenharmony_ci src_vq->drv_priv = ctx; 71462306a36Sopenharmony_ci src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 71562306a36Sopenharmony_ci src_vq->ops = &visl_qops; 71662306a36Sopenharmony_ci src_vq->mem_ops = &vb2_vmalloc_memops; 71762306a36Sopenharmony_ci src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 71862306a36Sopenharmony_ci src_vq->lock = &ctx->vb_mutex; 71962306a36Sopenharmony_ci src_vq->supports_requests = true; 72062306a36Sopenharmony_ci src_vq->subsystem_flags |= VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci ret = vb2_queue_init(src_vq); 72362306a36Sopenharmony_ci if (ret) 72462306a36Sopenharmony_ci return ret; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 72762306a36Sopenharmony_ci dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 72862306a36Sopenharmony_ci dst_vq->drv_priv = ctx; 72962306a36Sopenharmony_ci dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 73062306a36Sopenharmony_ci dst_vq->ops = &visl_qops; 73162306a36Sopenharmony_ci dst_vq->mem_ops = &vb2_vmalloc_memops; 73262306a36Sopenharmony_ci dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 73362306a36Sopenharmony_ci dst_vq->lock = &ctx->vb_mutex; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci return vb2_queue_init(dst_vq); 73662306a36Sopenharmony_ci} 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ciint visl_request_validate(struct media_request *req) 73962306a36Sopenharmony_ci{ 74062306a36Sopenharmony_ci struct media_request_object *obj; 74162306a36Sopenharmony_ci struct visl_ctx *ctx = NULL; 74262306a36Sopenharmony_ci unsigned int count; 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci list_for_each_entry(obj, &req->objects, list) { 74562306a36Sopenharmony_ci struct vb2_buffer *vb; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci if (vb2_request_object_is_buffer(obj)) { 74862306a36Sopenharmony_ci vb = container_of(obj, struct vb2_buffer, req_obj); 74962306a36Sopenharmony_ci ctx = vb2_get_drv_priv(vb->vb2_queue); 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci break; 75262306a36Sopenharmony_ci } 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci if (!ctx) 75662306a36Sopenharmony_ci return -ENOENT; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci count = vb2_request_buffer_cnt(req); 75962306a36Sopenharmony_ci if (!count) { 76062306a36Sopenharmony_ci v4l2_err(&ctx->dev->v4l2_dev, 76162306a36Sopenharmony_ci "No buffer was provided with the request\n"); 76262306a36Sopenharmony_ci return -ENOENT; 76362306a36Sopenharmony_ci } else if (count > 1) { 76462306a36Sopenharmony_ci v4l2_err(&ctx->dev->v4l2_dev, 76562306a36Sopenharmony_ci "More than one buffer was provided with the request\n"); 76662306a36Sopenharmony_ci return -EINVAL; 76762306a36Sopenharmony_ci } 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci return vb2_request_validate(req); 77062306a36Sopenharmony_ci} 771