10c078e31SDaniel Almeida // SPDX-License-Identifier: GPL-2.0 20c078e31SDaniel Almeida /* 30c078e31SDaniel Almeida * Contains the driver implementation for the V4L2 stateless interface. 40c078e31SDaniel Almeida */ 50c078e31SDaniel Almeida 60c078e31SDaniel Almeida #include <linux/debugfs.h> 70c078e31SDaniel Almeida #include <linux/font.h> 80c078e31SDaniel Almeida #include <media/v4l2-event.h> 90c078e31SDaniel Almeida #include <media/v4l2-ioctl.h> 100c078e31SDaniel Almeida #include <media/videobuf2-vmalloc.h> 110c078e31SDaniel Almeida #include <media/videobuf2-v4l2.h> 120c078e31SDaniel Almeida 130c078e31SDaniel Almeida #include "visl-video.h" 140c078e31SDaniel Almeida 150c078e31SDaniel Almeida #include "visl.h" 160c078e31SDaniel Almeida #include "visl-debugfs.h" 170c078e31SDaniel Almeida 180c078e31SDaniel Almeida #define MIN_CODED_SZ (1024U * 256U) 190c078e31SDaniel Almeida 200c078e31SDaniel Almeida static void visl_set_current_codec(struct visl_ctx *ctx) 210c078e31SDaniel Almeida { 220c078e31SDaniel Almeida u32 fourcc = ctx->coded_fmt.fmt.pix_mp.pixelformat; 230c078e31SDaniel Almeida 240c078e31SDaniel Almeida switch (fourcc) { 250c078e31SDaniel Almeida case V4L2_PIX_FMT_FWHT_STATELESS: 260c078e31SDaniel Almeida ctx->current_codec = VISL_CODEC_FWHT; 270c078e31SDaniel Almeida break; 280c078e31SDaniel Almeida case V4L2_PIX_FMT_MPEG2_SLICE: 290c078e31SDaniel Almeida ctx->current_codec = VISL_CODEC_MPEG2; 300c078e31SDaniel Almeida break; 310c078e31SDaniel Almeida case V4L2_PIX_FMT_VP8_FRAME: 320c078e31SDaniel Almeida ctx->current_codec = VISL_CODEC_VP8; 330c078e31SDaniel Almeida break; 340c078e31SDaniel Almeida case V4L2_PIX_FMT_VP9_FRAME: 350c078e31SDaniel Almeida ctx->current_codec = VISL_CODEC_VP9; 360c078e31SDaniel Almeida break; 370c078e31SDaniel Almeida case V4L2_PIX_FMT_H264_SLICE: 380c078e31SDaniel Almeida ctx->current_codec = VISL_CODEC_H264; 390c078e31SDaniel Almeida break; 400c078e31SDaniel Almeida case V4L2_PIX_FMT_HEVC_SLICE: 410c078e31SDaniel Almeida ctx->current_codec = VISL_CODEC_HEVC; 420c078e31SDaniel Almeida break; 430c078e31SDaniel Almeida default: 440c078e31SDaniel Almeida dprintk(ctx->dev, "Warning: unsupported fourcc: %d\n", fourcc); 450c078e31SDaniel Almeida ctx->current_codec = VISL_CODEC_NONE; 460c078e31SDaniel Almeida break; 470c078e31SDaniel Almeida } 480c078e31SDaniel Almeida } 490c078e31SDaniel Almeida 500c078e31SDaniel Almeida static void visl_print_fmt(struct visl_ctx *ctx, const struct v4l2_format *f) 510c078e31SDaniel Almeida { 520c078e31SDaniel Almeida const struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; 530c078e31SDaniel Almeida u32 i; 540c078e31SDaniel Almeida 550c078e31SDaniel Almeida dprintk(ctx->dev, "width: %d\n", pix_mp->width); 560c078e31SDaniel Almeida dprintk(ctx->dev, "height: %d\n", pix_mp->height); 570c078e31SDaniel Almeida dprintk(ctx->dev, "pixelformat: %c%c%c%c\n", 580c078e31SDaniel Almeida pix_mp->pixelformat, 590c078e31SDaniel Almeida (pix_mp->pixelformat >> 8) & 0xff, 600c078e31SDaniel Almeida (pix_mp->pixelformat >> 16) & 0xff, 610c078e31SDaniel Almeida (pix_mp->pixelformat >> 24) & 0xff); 620c078e31SDaniel Almeida 630c078e31SDaniel Almeida dprintk(ctx->dev, "field: %d\n", pix_mp->field); 640c078e31SDaniel Almeida dprintk(ctx->dev, "colorspace: %d\n", pix_mp->colorspace); 650c078e31SDaniel Almeida dprintk(ctx->dev, "num_planes: %d\n", pix_mp->num_planes); 660c078e31SDaniel Almeida dprintk(ctx->dev, "flags: %d\n", pix_mp->flags); 670c078e31SDaniel Almeida dprintk(ctx->dev, "quantization: %d\n", pix_mp->quantization); 680c078e31SDaniel Almeida dprintk(ctx->dev, "xfer_func: %d\n", pix_mp->xfer_func); 690c078e31SDaniel Almeida 700c078e31SDaniel Almeida for (i = 0; i < pix_mp->num_planes; i++) { 710c078e31SDaniel Almeida dprintk(ctx->dev, 720c078e31SDaniel Almeida "plane[%d]: sizeimage: %d\n", i, pix_mp->plane_fmt[i].sizeimage); 730c078e31SDaniel Almeida dprintk(ctx->dev, 740c078e31SDaniel Almeida "plane[%d]: bytesperline: %d\n", i, pix_mp->plane_fmt[i].bytesperline); 750c078e31SDaniel Almeida } 760c078e31SDaniel Almeida } 770c078e31SDaniel Almeida 780c078e31SDaniel Almeida static int visl_tpg_init(struct visl_ctx *ctx) 790c078e31SDaniel Almeida { 800c078e31SDaniel Almeida const struct font_desc *font; 810c078e31SDaniel Almeida const char *font_name = "VGA8x16"; 820c078e31SDaniel Almeida int ret; 830c078e31SDaniel Almeida u32 width = ctx->decoded_fmt.fmt.pix_mp.width; 840c078e31SDaniel Almeida u32 height = ctx->decoded_fmt.fmt.pix_mp.height; 850c078e31SDaniel Almeida struct v4l2_pix_format_mplane *f = &ctx->decoded_fmt.fmt.pix_mp; 860c078e31SDaniel Almeida 870c078e31SDaniel Almeida tpg_free(&ctx->tpg); 880c078e31SDaniel Almeida 890c078e31SDaniel Almeida font = find_font(font_name); 900c078e31SDaniel Almeida if (font) { 910c078e31SDaniel Almeida tpg_init(&ctx->tpg, width, height); 920c078e31SDaniel Almeida 930c078e31SDaniel Almeida ret = tpg_alloc(&ctx->tpg, width); 940c078e31SDaniel Almeida if (ret) 950c078e31SDaniel Almeida goto err_alloc; 960c078e31SDaniel Almeida 970c078e31SDaniel Almeida tpg_set_font(font->data); 980c078e31SDaniel Almeida ret = tpg_s_fourcc(&ctx->tpg, 990c078e31SDaniel Almeida f->pixelformat); 1000c078e31SDaniel Almeida 1010c078e31SDaniel Almeida if (!ret) 1020c078e31SDaniel Almeida goto err_fourcc; 1030c078e31SDaniel Almeida 1040c078e31SDaniel Almeida tpg_reset_source(&ctx->tpg, width, height, f->field); 1050c078e31SDaniel Almeida 1060c078e31SDaniel Almeida tpg_s_pattern(&ctx->tpg, TPG_PAT_75_COLORBAR); 1070c078e31SDaniel Almeida 1080c078e31SDaniel Almeida tpg_s_field(&ctx->tpg, f->field, false); 1090c078e31SDaniel Almeida tpg_s_colorspace(&ctx->tpg, f->colorspace); 1100c078e31SDaniel Almeida tpg_s_ycbcr_enc(&ctx->tpg, f->ycbcr_enc); 1110c078e31SDaniel Almeida tpg_s_quantization(&ctx->tpg, f->quantization); 1120c078e31SDaniel Almeida tpg_s_xfer_func(&ctx->tpg, f->xfer_func); 1130c078e31SDaniel Almeida } else { 1140c078e31SDaniel Almeida v4l2_err(&ctx->dev->v4l2_dev, 1150c078e31SDaniel Almeida "Font %s not found\n", font_name); 1160c078e31SDaniel Almeida 1170c078e31SDaniel Almeida return -EINVAL; 1180c078e31SDaniel Almeida } 1190c078e31SDaniel Almeida 1200c078e31SDaniel Almeida dprintk(ctx->dev, "Initialized the V4L2 test pattern generator, w=%d, h=%d, max_w=%d\n", 1210c078e31SDaniel Almeida width, height, width); 1220c078e31SDaniel Almeida 1230c078e31SDaniel Almeida return 0; 1240c078e31SDaniel Almeida err_alloc: 1250c078e31SDaniel Almeida return ret; 1260c078e31SDaniel Almeida err_fourcc: 1270c078e31SDaniel Almeida tpg_free(&ctx->tpg); 1280c078e31SDaniel Almeida return ret; 1290c078e31SDaniel Almeida } 1300c078e31SDaniel Almeida 1310c078e31SDaniel Almeida static const u32 visl_decoded_fmts[] = { 1320c078e31SDaniel Almeida V4L2_PIX_FMT_NV12, 1330c078e31SDaniel Almeida V4L2_PIX_FMT_YUV420, 1340c078e31SDaniel Almeida }; 1350c078e31SDaniel Almeida 1360c078e31SDaniel Almeida const struct visl_coded_format_desc visl_coded_fmts[] = { 1370c078e31SDaniel Almeida { 1380c078e31SDaniel Almeida .pixelformat = V4L2_PIX_FMT_FWHT_STATELESS, 1390c078e31SDaniel Almeida .frmsize = { 1400c078e31SDaniel Almeida .min_width = 640, 1410c078e31SDaniel Almeida .max_width = 4096, 1420c078e31SDaniel Almeida .step_width = 1, 1430c078e31SDaniel Almeida .min_height = 360, 1440c078e31SDaniel Almeida .max_height = 2160, 1450c078e31SDaniel Almeida .step_height = 1, 1460c078e31SDaniel Almeida }, 1470c078e31SDaniel Almeida .ctrls = &visl_fwht_ctrls, 1480c078e31SDaniel Almeida .num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts), 1490c078e31SDaniel Almeida .decoded_fmts = visl_decoded_fmts, 1500c078e31SDaniel Almeida }, 1510c078e31SDaniel Almeida { 1520c078e31SDaniel Almeida .pixelformat = V4L2_PIX_FMT_MPEG2_SLICE, 1530c078e31SDaniel Almeida .frmsize = { 1540c078e31SDaniel Almeida .min_width = 16, 1550c078e31SDaniel Almeida .max_width = 1920, 1560c078e31SDaniel Almeida .step_width = 1, 1570c078e31SDaniel Almeida .min_height = 16, 1580c078e31SDaniel Almeida .max_height = 1152, 1590c078e31SDaniel Almeida .step_height = 1, 1600c078e31SDaniel Almeida }, 1610c078e31SDaniel Almeida .ctrls = &visl_mpeg2_ctrls, 1620c078e31SDaniel Almeida .num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts), 1630c078e31SDaniel Almeida .decoded_fmts = visl_decoded_fmts, 1640c078e31SDaniel Almeida }, 1650c078e31SDaniel Almeida { 1660c078e31SDaniel Almeida .pixelformat = V4L2_PIX_FMT_VP8_FRAME, 1670c078e31SDaniel Almeida .frmsize = { 1680c078e31SDaniel Almeida .min_width = 64, 1690c078e31SDaniel Almeida .max_width = 16383, 1700c078e31SDaniel Almeida .step_width = 1, 1710c078e31SDaniel Almeida .min_height = 64, 1720c078e31SDaniel Almeida .max_height = 16383, 1730c078e31SDaniel Almeida .step_height = 1, 1740c078e31SDaniel Almeida }, 1750c078e31SDaniel Almeida .ctrls = &visl_vp8_ctrls, 1760c078e31SDaniel Almeida .num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts), 1770c078e31SDaniel Almeida .decoded_fmts = visl_decoded_fmts, 1780c078e31SDaniel Almeida }, 1790c078e31SDaniel Almeida { 1800c078e31SDaniel Almeida .pixelformat = V4L2_PIX_FMT_VP9_FRAME, 1810c078e31SDaniel Almeida .frmsize = { 1820c078e31SDaniel Almeida .min_width = 64, 1830c078e31SDaniel Almeida .max_width = 8192, 1840c078e31SDaniel Almeida .step_width = 1, 1850c078e31SDaniel Almeida .min_height = 64, 1860c078e31SDaniel Almeida .max_height = 4352, 1870c078e31SDaniel Almeida .step_height = 1, 1880c078e31SDaniel Almeida }, 1890c078e31SDaniel Almeida .ctrls = &visl_vp9_ctrls, 1900c078e31SDaniel Almeida .num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts), 1910c078e31SDaniel Almeida .decoded_fmts = visl_decoded_fmts, 1920c078e31SDaniel Almeida }, 1930c078e31SDaniel Almeida { 1940c078e31SDaniel Almeida .pixelformat = V4L2_PIX_FMT_H264_SLICE, 1950c078e31SDaniel Almeida .frmsize = { 1960c078e31SDaniel Almeida .min_width = 64, 1970c078e31SDaniel Almeida .max_width = 4096, 1980c078e31SDaniel Almeida .step_width = 1, 1990c078e31SDaniel Almeida .min_height = 64, 2000c078e31SDaniel Almeida .max_height = 2304, 2010c078e31SDaniel Almeida .step_height = 1, 2020c078e31SDaniel Almeida }, 2030c078e31SDaniel Almeida .ctrls = &visl_h264_ctrls, 2040c078e31SDaniel Almeida .num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts), 2050c078e31SDaniel Almeida .decoded_fmts = visl_decoded_fmts, 2060c078e31SDaniel Almeida }, 2070c078e31SDaniel Almeida { 2080c078e31SDaniel Almeida .pixelformat = V4L2_PIX_FMT_HEVC_SLICE, 2090c078e31SDaniel Almeida .frmsize = { 2100c078e31SDaniel Almeida .min_width = 64, 2110c078e31SDaniel Almeida .max_width = 4096, 2120c078e31SDaniel Almeida .step_width = 1, 2130c078e31SDaniel Almeida .min_height = 64, 2140c078e31SDaniel Almeida .max_height = 2304, 2150c078e31SDaniel Almeida .step_height = 1, 2160c078e31SDaniel Almeida }, 2170c078e31SDaniel Almeida .ctrls = &visl_hevc_ctrls, 2180c078e31SDaniel Almeida .num_decoded_fmts = ARRAY_SIZE(visl_decoded_fmts), 2190c078e31SDaniel Almeida .decoded_fmts = visl_decoded_fmts, 2200c078e31SDaniel Almeida }, 2210c078e31SDaniel Almeida }; 2220c078e31SDaniel Almeida 2230c078e31SDaniel Almeida const size_t num_coded_fmts = ARRAY_SIZE(visl_coded_fmts); 2240c078e31SDaniel Almeida 2250c078e31SDaniel Almeida static const struct visl_coded_format_desc* 2260c078e31SDaniel Almeida visl_find_coded_fmt_desc(u32 fourcc) 2270c078e31SDaniel Almeida { 2280c078e31SDaniel Almeida unsigned int i; 2290c078e31SDaniel Almeida 2300c078e31SDaniel Almeida for (i = 0; i < ARRAY_SIZE(visl_coded_fmts); i++) { 2310c078e31SDaniel Almeida if (visl_coded_fmts[i].pixelformat == fourcc) 2320c078e31SDaniel Almeida return &visl_coded_fmts[i]; 2330c078e31SDaniel Almeida } 2340c078e31SDaniel Almeida 2350c078e31SDaniel Almeida return NULL; 2360c078e31SDaniel Almeida } 2370c078e31SDaniel Almeida 2380c078e31SDaniel Almeida static void visl_init_fmt(struct v4l2_format *f, u32 fourcc) 2390c078e31SDaniel Almeida { memset(f, 0, sizeof(*f)); 2400c078e31SDaniel Almeida f->fmt.pix_mp.pixelformat = fourcc; 2410c078e31SDaniel Almeida f->fmt.pix_mp.field = V4L2_FIELD_NONE; 2420c078e31SDaniel Almeida f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709; 2430c078e31SDaniel Almeida f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 2440c078e31SDaniel Almeida f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; 2450c078e31SDaniel Almeida f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; 2460c078e31SDaniel Almeida } 2470c078e31SDaniel Almeida 2480c078e31SDaniel Almeida static void visl_reset_coded_fmt(struct visl_ctx *ctx) 2490c078e31SDaniel Almeida { 2500c078e31SDaniel Almeida struct v4l2_format *f = &ctx->coded_fmt; 2510c078e31SDaniel Almeida struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; 2520c078e31SDaniel Almeida 2530c078e31SDaniel Almeida ctx->coded_format_desc = &visl_coded_fmts[0]; 2540c078e31SDaniel Almeida visl_init_fmt(f, ctx->coded_format_desc->pixelformat); 2550c078e31SDaniel Almeida 2560c078e31SDaniel Almeida f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 2570c078e31SDaniel Almeida f->fmt.pix_mp.width = ctx->coded_format_desc->frmsize.min_width; 2580c078e31SDaniel Almeida f->fmt.pix_mp.height = ctx->coded_format_desc->frmsize.min_height; 2590c078e31SDaniel Almeida 2600c078e31SDaniel Almeida pix_mp->num_planes = 1; 2610c078e31SDaniel Almeida pix_mp->plane_fmt[0].sizeimage = pix_mp->width * pix_mp->height * 8; 2620c078e31SDaniel Almeida 2630c078e31SDaniel Almeida dprintk(ctx->dev, "OUTPUT format was set to:\n"); 2640c078e31SDaniel Almeida visl_print_fmt(ctx, &ctx->coded_fmt); 2650c078e31SDaniel Almeida 2660c078e31SDaniel Almeida visl_set_current_codec(ctx); 2670c078e31SDaniel Almeida } 2680c078e31SDaniel Almeida 2690c078e31SDaniel Almeida static int visl_reset_decoded_fmt(struct visl_ctx *ctx) 2700c078e31SDaniel Almeida { 2710c078e31SDaniel Almeida struct v4l2_format *f = &ctx->decoded_fmt; 2720c078e31SDaniel Almeida u32 decoded_fmt = ctx->coded_format_desc[0].decoded_fmts[0]; 2730c078e31SDaniel Almeida 2740c078e31SDaniel Almeida visl_init_fmt(f, decoded_fmt); 2750c078e31SDaniel Almeida 2760c078e31SDaniel Almeida f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 2770c078e31SDaniel Almeida 2780c078e31SDaniel Almeida v4l2_fill_pixfmt_mp(&f->fmt.pix_mp, 2790c078e31SDaniel Almeida ctx->coded_format_desc->decoded_fmts[0], 2800c078e31SDaniel Almeida ctx->coded_fmt.fmt.pix_mp.width, 2810c078e31SDaniel Almeida ctx->coded_fmt.fmt.pix_mp.height); 2820c078e31SDaniel Almeida 2830c078e31SDaniel Almeida dprintk(ctx->dev, "CAPTURE format was set to:\n"); 2840c078e31SDaniel Almeida visl_print_fmt(ctx, &ctx->decoded_fmt); 2850c078e31SDaniel Almeida 2860c078e31SDaniel Almeida return visl_tpg_init(ctx); 2870c078e31SDaniel Almeida } 2880c078e31SDaniel Almeida 2890c078e31SDaniel Almeida int visl_set_default_format(struct visl_ctx *ctx) 2900c078e31SDaniel Almeida { 2910c078e31SDaniel Almeida visl_reset_coded_fmt(ctx); 2920c078e31SDaniel Almeida return visl_reset_decoded_fmt(ctx); 2930c078e31SDaniel Almeida } 2940c078e31SDaniel Almeida 2950c078e31SDaniel Almeida static struct visl_q_data *get_q_data(struct visl_ctx *ctx, 2960c078e31SDaniel Almeida enum v4l2_buf_type type) 2970c078e31SDaniel Almeida { 2980c078e31SDaniel Almeida switch (type) { 2990c078e31SDaniel Almeida case V4L2_BUF_TYPE_VIDEO_OUTPUT: 3000c078e31SDaniel Almeida case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 3010c078e31SDaniel Almeida return &ctx->q_data[V4L2_M2M_SRC]; 3020c078e31SDaniel Almeida case V4L2_BUF_TYPE_VIDEO_CAPTURE: 3030c078e31SDaniel Almeida case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 3040c078e31SDaniel Almeida return &ctx->q_data[V4L2_M2M_DST]; 3050c078e31SDaniel Almeida default: 3060c078e31SDaniel Almeida break; 3070c078e31SDaniel Almeida } 3080c078e31SDaniel Almeida return NULL; 3090c078e31SDaniel Almeida } 3100c078e31SDaniel Almeida 3110c078e31SDaniel Almeida static int visl_querycap(struct file *file, void *priv, 3120c078e31SDaniel Almeida struct v4l2_capability *cap) 3130c078e31SDaniel Almeida { 3140c078e31SDaniel Almeida strscpy(cap->driver, VISL_NAME, sizeof(cap->driver)); 3150c078e31SDaniel Almeida strscpy(cap->card, VISL_NAME, sizeof(cap->card)); 3160c078e31SDaniel Almeida snprintf(cap->bus_info, sizeof(cap->bus_info), 3170c078e31SDaniel Almeida "platform:%s", VISL_NAME); 3180c078e31SDaniel Almeida 3190c078e31SDaniel Almeida return 0; 3200c078e31SDaniel Almeida } 3210c078e31SDaniel Almeida 3220c078e31SDaniel Almeida static int visl_enum_fmt_vid_cap(struct file *file, void *priv, 3230c078e31SDaniel Almeida struct v4l2_fmtdesc *f) 3240c078e31SDaniel Almeida { 3250c078e31SDaniel Almeida struct visl_ctx *ctx = visl_file_to_ctx(file); 3260c078e31SDaniel Almeida 3270c078e31SDaniel Almeida if (f->index >= ctx->coded_format_desc->num_decoded_fmts) 3280c078e31SDaniel Almeida return -EINVAL; 3290c078e31SDaniel Almeida 3300c078e31SDaniel Almeida f->pixelformat = ctx->coded_format_desc->decoded_fmts[f->index]; 3310c078e31SDaniel Almeida return 0; 3320c078e31SDaniel Almeida } 3330c078e31SDaniel Almeida 3340c078e31SDaniel Almeida static int visl_enum_fmt_vid_out(struct file *file, void *priv, 3350c078e31SDaniel Almeida struct v4l2_fmtdesc *f) 3360c078e31SDaniel Almeida { 3370c078e31SDaniel Almeida if (f->index >= ARRAY_SIZE(visl_coded_fmts)) 3380c078e31SDaniel Almeida return -EINVAL; 3390c078e31SDaniel Almeida 3400c078e31SDaniel Almeida f->pixelformat = visl_coded_fmts[f->index].pixelformat; 3410c078e31SDaniel Almeida return 0; 3420c078e31SDaniel Almeida } 3430c078e31SDaniel Almeida 3440c078e31SDaniel Almeida static int visl_g_fmt_vid_cap(struct file *file, void *priv, 3450c078e31SDaniel Almeida struct v4l2_format *f) 3460c078e31SDaniel Almeida { 3470c078e31SDaniel Almeida struct visl_ctx *ctx = visl_file_to_ctx(file); 3480c078e31SDaniel Almeida *f = ctx->decoded_fmt; 3490c078e31SDaniel Almeida 3500c078e31SDaniel Almeida return 0; 3510c078e31SDaniel Almeida } 3520c078e31SDaniel Almeida 3530c078e31SDaniel Almeida static int visl_g_fmt_vid_out(struct file *file, void *priv, 3540c078e31SDaniel Almeida struct v4l2_format *f) 3550c078e31SDaniel Almeida { 3560c078e31SDaniel Almeida struct visl_ctx *ctx = visl_file_to_ctx(file); 3570c078e31SDaniel Almeida 3580c078e31SDaniel Almeida *f = ctx->coded_fmt; 3590c078e31SDaniel Almeida return 0; 3600c078e31SDaniel Almeida } 3610c078e31SDaniel Almeida 3620c078e31SDaniel Almeida static int visl_try_fmt_vid_cap(struct file *file, void *priv, 3630c078e31SDaniel Almeida struct v4l2_format *f) 3640c078e31SDaniel Almeida { 3650c078e31SDaniel Almeida struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; 3660c078e31SDaniel Almeida struct visl_ctx *ctx = visl_file_to_ctx(file); 3670c078e31SDaniel Almeida const struct visl_coded_format_desc *coded_desc; 3680c078e31SDaniel Almeida unsigned int i; 3690c078e31SDaniel Almeida 3700c078e31SDaniel Almeida coded_desc = ctx->coded_format_desc; 3710c078e31SDaniel Almeida 3720c078e31SDaniel Almeida for (i = 0; i < coded_desc->num_decoded_fmts; i++) { 3730c078e31SDaniel Almeida if (coded_desc->decoded_fmts[i] == pix_mp->pixelformat) 3740c078e31SDaniel Almeida break; 3750c078e31SDaniel Almeida } 3760c078e31SDaniel Almeida 3770c078e31SDaniel Almeida if (i == coded_desc->num_decoded_fmts) 3780c078e31SDaniel Almeida pix_mp->pixelformat = coded_desc->decoded_fmts[0]; 3790c078e31SDaniel Almeida 3800c078e31SDaniel Almeida v4l2_apply_frmsize_constraints(&pix_mp->width, 3810c078e31SDaniel Almeida &pix_mp->height, 3820c078e31SDaniel Almeida &coded_desc->frmsize); 3830c078e31SDaniel Almeida 3840c078e31SDaniel Almeida v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, 3850c078e31SDaniel Almeida pix_mp->width, pix_mp->height); 3860c078e31SDaniel Almeida 3870c078e31SDaniel Almeida pix_mp->field = V4L2_FIELD_NONE; 3880c078e31SDaniel Almeida 3890c078e31SDaniel Almeida return 0; 3900c078e31SDaniel Almeida } 3910c078e31SDaniel Almeida 3920c078e31SDaniel Almeida static int visl_try_fmt_vid_out(struct file *file, void *priv, 3930c078e31SDaniel Almeida struct v4l2_format *f) 3940c078e31SDaniel Almeida { 3950c078e31SDaniel Almeida struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; 3960c078e31SDaniel Almeida const struct visl_coded_format_desc *coded_desc; 3970c078e31SDaniel Almeida 3980c078e31SDaniel Almeida coded_desc = visl_find_coded_fmt_desc(pix_mp->pixelformat); 3990c078e31SDaniel Almeida if (!coded_desc) { 4000c078e31SDaniel Almeida pix_mp->pixelformat = visl_coded_fmts[0].pixelformat; 4010c078e31SDaniel Almeida coded_desc = &visl_coded_fmts[0]; 4020c078e31SDaniel Almeida } 4030c078e31SDaniel Almeida 4040c078e31SDaniel Almeida v4l2_apply_frmsize_constraints(&pix_mp->width, 4050c078e31SDaniel Almeida &pix_mp->height, 4060c078e31SDaniel Almeida &coded_desc->frmsize); 4070c078e31SDaniel Almeida 4080c078e31SDaniel Almeida pix_mp->field = V4L2_FIELD_NONE; 4090c078e31SDaniel Almeida pix_mp->num_planes = 1; 4100c078e31SDaniel Almeida 4110c078e31SDaniel Almeida if (pix_mp->plane_fmt[0].sizeimage == 0) 4120c078e31SDaniel Almeida pix_mp->plane_fmt[0].sizeimage = max(MIN_CODED_SZ, 4130c078e31SDaniel Almeida pix_mp->width * pix_mp->height * 3); 4140c078e31SDaniel Almeida 4150c078e31SDaniel Almeida return 0; 4160c078e31SDaniel Almeida } 4170c078e31SDaniel Almeida 4180c078e31SDaniel Almeida static int visl_s_fmt_vid_out(struct file *file, void *priv, 4190c078e31SDaniel Almeida struct v4l2_format *f) 4200c078e31SDaniel Almeida { 4210c078e31SDaniel Almeida struct visl_ctx *ctx = visl_file_to_ctx(file); 4220c078e31SDaniel Almeida struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; 4230c078e31SDaniel Almeida const struct visl_coded_format_desc *desc; 4240c078e31SDaniel Almeida struct vb2_queue *peer_vq; 4250c078e31SDaniel Almeida int ret; 4260c078e31SDaniel Almeida 4270c078e31SDaniel Almeida peer_vq = v4l2_m2m_get_vq(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 4280c078e31SDaniel Almeida if (vb2_is_busy(peer_vq)) 4290c078e31SDaniel Almeida return -EBUSY; 4300c078e31SDaniel Almeida 4310c078e31SDaniel Almeida dprintk(ctx->dev, "Trying to set the OUTPUT format to:\n"); 4320c078e31SDaniel Almeida visl_print_fmt(ctx, f); 4330c078e31SDaniel Almeida 4340c078e31SDaniel Almeida ret = visl_try_fmt_vid_out(file, priv, f); 4350c078e31SDaniel Almeida if (ret) 4360c078e31SDaniel Almeida return ret; 4370c078e31SDaniel Almeida 4380c078e31SDaniel Almeida desc = visl_find_coded_fmt_desc(f->fmt.pix_mp.pixelformat); 4390c078e31SDaniel Almeida ctx->coded_format_desc = desc; 4400c078e31SDaniel Almeida ctx->coded_fmt = *f; 4410c078e31SDaniel Almeida 4420c078e31SDaniel Almeida ret = visl_reset_decoded_fmt(ctx); 4430c078e31SDaniel Almeida if (ret) 4440c078e31SDaniel Almeida return ret; 4450c078e31SDaniel Almeida 4460c078e31SDaniel Almeida ctx->decoded_fmt.fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; 4470c078e31SDaniel Almeida ctx->decoded_fmt.fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; 4480c078e31SDaniel Almeida ctx->decoded_fmt.fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; 4490c078e31SDaniel Almeida ctx->decoded_fmt.fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; 4500c078e31SDaniel Almeida 4510c078e31SDaniel Almeida dprintk(ctx->dev, "OUTPUT format was set to:\n"); 4520c078e31SDaniel Almeida visl_print_fmt(ctx, &ctx->coded_fmt); 4530c078e31SDaniel Almeida 4540c078e31SDaniel Almeida visl_set_current_codec(ctx); 4550c078e31SDaniel Almeida return 0; 4560c078e31SDaniel Almeida } 4570c078e31SDaniel Almeida 4580c078e31SDaniel Almeida static int visl_s_fmt_vid_cap(struct file *file, void *priv, 4590c078e31SDaniel Almeida struct v4l2_format *f) 4600c078e31SDaniel Almeida { 4610c078e31SDaniel Almeida struct visl_ctx *ctx = visl_file_to_ctx(file); 4620c078e31SDaniel Almeida int ret; 4630c078e31SDaniel Almeida 4640c078e31SDaniel Almeida dprintk(ctx->dev, "Trying to set the CAPTURE format to:\n"); 4650c078e31SDaniel Almeida visl_print_fmt(ctx, f); 4660c078e31SDaniel Almeida 4670c078e31SDaniel Almeida ret = visl_try_fmt_vid_cap(file, priv, f); 4680c078e31SDaniel Almeida if (ret) 4690c078e31SDaniel Almeida return ret; 4700c078e31SDaniel Almeida 4710c078e31SDaniel Almeida ctx->decoded_fmt = *f; 4720c078e31SDaniel Almeida 4730c078e31SDaniel Almeida dprintk(ctx->dev, "CAPTURE format was set to:\n"); 4740c078e31SDaniel Almeida visl_print_fmt(ctx, &ctx->decoded_fmt); 4750c078e31SDaniel Almeida 4760c078e31SDaniel Almeida visl_tpg_init(ctx); 4770c078e31SDaniel Almeida return 0; 4780c078e31SDaniel Almeida } 4790c078e31SDaniel Almeida 4800c078e31SDaniel Almeida static int visl_enum_framesizes(struct file *file, void *priv, 4810c078e31SDaniel Almeida struct v4l2_frmsizeenum *fsize) 4820c078e31SDaniel Almeida { 4830c078e31SDaniel Almeida const struct visl_coded_format_desc *fmt; 4840c078e31SDaniel Almeida struct visl_ctx *ctx = visl_file_to_ctx(file); 4850c078e31SDaniel Almeida 4860c078e31SDaniel Almeida if (fsize->index != 0) 4870c078e31SDaniel Almeida return -EINVAL; 4880c078e31SDaniel Almeida 4890c078e31SDaniel Almeida fmt = visl_find_coded_fmt_desc(fsize->pixel_format); 4900c078e31SDaniel Almeida if (!fmt) { 4910c078e31SDaniel Almeida dprintk(ctx->dev, 4920c078e31SDaniel Almeida "Unsupported format for the OUTPUT queue: %d\n", 4930c078e31SDaniel Almeida fsize->pixel_format); 4940c078e31SDaniel Almeida 4950c078e31SDaniel Almeida return -EINVAL; 4960c078e31SDaniel Almeida } 4970c078e31SDaniel Almeida 4980c078e31SDaniel Almeida fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; 4990c078e31SDaniel Almeida fsize->stepwise = fmt->frmsize; 5000c078e31SDaniel Almeida return 0; 5010c078e31SDaniel Almeida } 5020c078e31SDaniel Almeida 5030c078e31SDaniel Almeida const struct v4l2_ioctl_ops visl_ioctl_ops = { 5040c078e31SDaniel Almeida .vidioc_querycap = visl_querycap, 5050c078e31SDaniel Almeida .vidioc_enum_framesizes = visl_enum_framesizes, 5060c078e31SDaniel Almeida 5070c078e31SDaniel Almeida .vidioc_enum_fmt_vid_cap = visl_enum_fmt_vid_cap, 5080c078e31SDaniel Almeida .vidioc_g_fmt_vid_cap_mplane = visl_g_fmt_vid_cap, 5090c078e31SDaniel Almeida .vidioc_try_fmt_vid_cap_mplane = visl_try_fmt_vid_cap, 5100c078e31SDaniel Almeida .vidioc_s_fmt_vid_cap_mplane = visl_s_fmt_vid_cap, 5110c078e31SDaniel Almeida 5120c078e31SDaniel Almeida .vidioc_enum_fmt_vid_out = visl_enum_fmt_vid_out, 5130c078e31SDaniel Almeida .vidioc_g_fmt_vid_out_mplane = visl_g_fmt_vid_out, 5140c078e31SDaniel Almeida .vidioc_try_fmt_vid_out_mplane = visl_try_fmt_vid_out, 5150c078e31SDaniel Almeida .vidioc_s_fmt_vid_out_mplane = visl_s_fmt_vid_out, 5160c078e31SDaniel Almeida 5170c078e31SDaniel Almeida .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 5180c078e31SDaniel Almeida .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 5190c078e31SDaniel Almeida .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 5200c078e31SDaniel Almeida .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 5210c078e31SDaniel Almeida .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, 5220c078e31SDaniel Almeida .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 5230c078e31SDaniel Almeida .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 5240c078e31SDaniel Almeida 5250c078e31SDaniel Almeida .vidioc_streamon = v4l2_m2m_ioctl_streamon, 5260c078e31SDaniel Almeida .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 5270c078e31SDaniel Almeida 5280c078e31SDaniel Almeida .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 5290c078e31SDaniel Almeida .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 5300c078e31SDaniel Almeida }; 5310c078e31SDaniel Almeida 5320c078e31SDaniel Almeida static int visl_queue_setup(struct vb2_queue *vq, 5330c078e31SDaniel Almeida unsigned int *nbuffers, 5340c078e31SDaniel Almeida unsigned int *num_planes, 5350c078e31SDaniel Almeida unsigned int sizes[], 5360c078e31SDaniel Almeida struct device *alloc_devs[]) 5370c078e31SDaniel Almeida { 5380c078e31SDaniel Almeida struct visl_ctx *ctx = vb2_get_drv_priv(vq); 5390c078e31SDaniel Almeida struct v4l2_format *f; 5400c078e31SDaniel Almeida u32 i; 5410c078e31SDaniel Almeida char *qname; 5420c078e31SDaniel Almeida 5430c078e31SDaniel Almeida if (V4L2_TYPE_IS_OUTPUT(vq->type)) { 5440c078e31SDaniel Almeida f = &ctx->coded_fmt; 5450c078e31SDaniel Almeida qname = "Output"; 5460c078e31SDaniel Almeida } else { 5470c078e31SDaniel Almeida f = &ctx->decoded_fmt; 5480c078e31SDaniel Almeida qname = "Capture"; 5490c078e31SDaniel Almeida } 5500c078e31SDaniel Almeida 5510c078e31SDaniel Almeida if (*num_planes) { 5520c078e31SDaniel Almeida if (*num_planes != f->fmt.pix_mp.num_planes) 5530c078e31SDaniel Almeida return -EINVAL; 5540c078e31SDaniel Almeida 5550c078e31SDaniel Almeida for (i = 0; i < f->fmt.pix_mp.num_planes; i++) { 5560c078e31SDaniel Almeida if (sizes[i] < f->fmt.pix_mp.plane_fmt[i].sizeimage) 5570c078e31SDaniel Almeida return -EINVAL; 5580c078e31SDaniel Almeida } 5590c078e31SDaniel Almeida } else { 5600c078e31SDaniel Almeida *num_planes = f->fmt.pix_mp.num_planes; 5610c078e31SDaniel Almeida for (i = 0; i < f->fmt.pix_mp.num_planes; i++) 5620c078e31SDaniel Almeida sizes[i] = f->fmt.pix_mp.plane_fmt[i].sizeimage; 5630c078e31SDaniel Almeida } 5640c078e31SDaniel Almeida 5650c078e31SDaniel Almeida dprintk(ctx->dev, "%s: %d buffer(s) requested, num_planes=%d.\n", 5660c078e31SDaniel Almeida qname, *nbuffers, *num_planes); 5670c078e31SDaniel Almeida 5680c078e31SDaniel Almeida for (i = 0; i < f->fmt.pix_mp.num_planes; i++) 5690c078e31SDaniel Almeida dprintk(ctx->dev, "plane[%d].sizeimage=%d\n", 5700c078e31SDaniel Almeida i, f->fmt.pix_mp.plane_fmt[i].sizeimage); 5710c078e31SDaniel Almeida 5720c078e31SDaniel Almeida return 0; 5730c078e31SDaniel Almeida } 5740c078e31SDaniel Almeida 5750c078e31SDaniel Almeida static void visl_queue_cleanup(struct vb2_queue *vq, u32 state) 5760c078e31SDaniel Almeida { 5770c078e31SDaniel Almeida struct visl_ctx *ctx = vb2_get_drv_priv(vq); 5780c078e31SDaniel Almeida struct vb2_v4l2_buffer *vbuf; 5790c078e31SDaniel Almeida 5800c078e31SDaniel Almeida dprintk(ctx->dev, "Cleaning up queues\n"); 5810c078e31SDaniel Almeida for (;;) { 5820c078e31SDaniel Almeida if (V4L2_TYPE_IS_OUTPUT(vq->type)) 5830c078e31SDaniel Almeida vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); 5840c078e31SDaniel Almeida else 5850c078e31SDaniel Almeida vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 5860c078e31SDaniel Almeida 5870c078e31SDaniel Almeida if (!vbuf) 5880c078e31SDaniel Almeida break; 5890c078e31SDaniel Almeida 5900c078e31SDaniel Almeida v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, 5910c078e31SDaniel Almeida &ctx->hdl); 5920c078e31SDaniel Almeida dprintk(ctx->dev, "Marked request %p as complete\n", 5930c078e31SDaniel Almeida vbuf->vb2_buf.req_obj.req); 5940c078e31SDaniel Almeida 5950c078e31SDaniel Almeida v4l2_m2m_buf_done(vbuf, state); 5960c078e31SDaniel Almeida dprintk(ctx->dev, 5970c078e31SDaniel Almeida "Marked buffer %llu as done, state is %d\n", 5980c078e31SDaniel Almeida vbuf->vb2_buf.timestamp, 5990c078e31SDaniel Almeida state); 6000c078e31SDaniel Almeida } 6010c078e31SDaniel Almeida } 6020c078e31SDaniel Almeida 6030c078e31SDaniel Almeida static int visl_buf_out_validate(struct vb2_buffer *vb) 6040c078e31SDaniel Almeida { 6050c078e31SDaniel Almeida struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 6060c078e31SDaniel Almeida 6070c078e31SDaniel Almeida vbuf->field = V4L2_FIELD_NONE; 6080c078e31SDaniel Almeida return 0; 6090c078e31SDaniel Almeida } 6100c078e31SDaniel Almeida 6110c078e31SDaniel Almeida static int visl_buf_prepare(struct vb2_buffer *vb) 6120c078e31SDaniel Almeida { 6130c078e31SDaniel Almeida struct vb2_queue *vq = vb->vb2_queue; 6140c078e31SDaniel Almeida struct visl_ctx *ctx = vb2_get_drv_priv(vq); 6150c078e31SDaniel Almeida u32 plane_sz = vb2_plane_size(vb, 0); 6160c078e31SDaniel Almeida struct v4l2_pix_format *pix_fmt; 6170c078e31SDaniel Almeida 6180c078e31SDaniel Almeida if (V4L2_TYPE_IS_OUTPUT(vq->type)) { 6190c078e31SDaniel Almeida pix_fmt = &ctx->coded_fmt.fmt.pix; 6200c078e31SDaniel Almeida } else { 6210c078e31SDaniel Almeida pix_fmt = &ctx->decoded_fmt.fmt.pix; 6220c078e31SDaniel Almeida vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage); 6230c078e31SDaniel Almeida } 6240c078e31SDaniel Almeida 6250c078e31SDaniel Almeida if (plane_sz < pix_fmt->sizeimage) { 6260c078e31SDaniel Almeida v4l2_err(&ctx->dev->v4l2_dev, "plane[0] size is %d, sizeimage is %d\n", 6270c078e31SDaniel Almeida plane_sz, pix_fmt->sizeimage); 6280c078e31SDaniel Almeida return -EINVAL; 6290c078e31SDaniel Almeida } 6300c078e31SDaniel Almeida 6310c078e31SDaniel Almeida return 0; 6320c078e31SDaniel Almeida } 6330c078e31SDaniel Almeida 6340c078e31SDaniel Almeida static int visl_start_streaming(struct vb2_queue *vq, unsigned int count) 6350c078e31SDaniel Almeida { 6360c078e31SDaniel Almeida struct visl_ctx *ctx = vb2_get_drv_priv(vq); 6370c078e31SDaniel Almeida struct visl_q_data *q_data = get_q_data(ctx, vq->type); 6380c078e31SDaniel Almeida int rc = 0; 6390c078e31SDaniel Almeida 6400c078e31SDaniel Almeida if (!q_data) { 6410c078e31SDaniel Almeida rc = -EINVAL; 6420c078e31SDaniel Almeida goto err; 6430c078e31SDaniel Almeida } 6440c078e31SDaniel Almeida 6450c078e31SDaniel Almeida q_data->sequence = 0; 6460c078e31SDaniel Almeida 6470c078e31SDaniel Almeida if (V4L2_TYPE_IS_CAPTURE(vq->type)) { 6480c078e31SDaniel Almeida ctx->capture_streamon_jiffies = get_jiffies_64(); 6490c078e31SDaniel Almeida return 0; 6500c078e31SDaniel Almeida } 6510c078e31SDaniel Almeida 6520c078e31SDaniel Almeida if (WARN_ON(!ctx->coded_format_desc)) { 6530c078e31SDaniel Almeida rc = -EINVAL; 6540c078e31SDaniel Almeida goto err; 6550c078e31SDaniel Almeida } 6560c078e31SDaniel Almeida 6570c078e31SDaniel Almeida return 0; 6580c078e31SDaniel Almeida 6590c078e31SDaniel Almeida err: 6600c078e31SDaniel Almeida visl_queue_cleanup(vq, VB2_BUF_STATE_QUEUED); 6610c078e31SDaniel Almeida return rc; 6620c078e31SDaniel Almeida } 6630c078e31SDaniel Almeida 6640c078e31SDaniel Almeida static void visl_stop_streaming(struct vb2_queue *vq) 6650c078e31SDaniel Almeida { 6660c078e31SDaniel Almeida struct visl_ctx *ctx = vb2_get_drv_priv(vq); 6670c078e31SDaniel Almeida 6680c078e31SDaniel Almeida dprintk(ctx->dev, "Stop streaming\n"); 6690c078e31SDaniel Almeida visl_queue_cleanup(vq, VB2_BUF_STATE_ERROR); 6700c078e31SDaniel Almeida 6710c078e31SDaniel Almeida if (!keep_bitstream_buffers) 6720c078e31SDaniel Almeida visl_debugfs_clear_bitstream(ctx->dev); 6730c078e31SDaniel Almeida } 6740c078e31SDaniel Almeida 6750c078e31SDaniel Almeida static void visl_buf_queue(struct vb2_buffer *vb) 6760c078e31SDaniel Almeida { 6770c078e31SDaniel Almeida struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 6780c078e31SDaniel Almeida struct visl_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 6790c078e31SDaniel Almeida 6800c078e31SDaniel Almeida v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); 6810c078e31SDaniel Almeida } 6820c078e31SDaniel Almeida 6830c078e31SDaniel Almeida static void visl_buf_request_complete(struct vb2_buffer *vb) 6840c078e31SDaniel Almeida { 6850c078e31SDaniel Almeida struct visl_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 6860c078e31SDaniel Almeida 6870c078e31SDaniel Almeida v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl); 6880c078e31SDaniel Almeida } 6890c078e31SDaniel Almeida 690*b6a1af03SHans Verkuil static const struct vb2_ops visl_qops = { 6910c078e31SDaniel Almeida .queue_setup = visl_queue_setup, 6920c078e31SDaniel Almeida .buf_out_validate = visl_buf_out_validate, 6930c078e31SDaniel Almeida .buf_prepare = visl_buf_prepare, 6940c078e31SDaniel Almeida .buf_queue = visl_buf_queue, 6950c078e31SDaniel Almeida .start_streaming = visl_start_streaming, 6960c078e31SDaniel Almeida .stop_streaming = visl_stop_streaming, 6970c078e31SDaniel Almeida .wait_prepare = vb2_ops_wait_prepare, 6980c078e31SDaniel Almeida .wait_finish = vb2_ops_wait_finish, 6990c078e31SDaniel Almeida .buf_request_complete = visl_buf_request_complete, 7000c078e31SDaniel Almeida }; 7010c078e31SDaniel Almeida 7020c078e31SDaniel Almeida int visl_queue_init(void *priv, struct vb2_queue *src_vq, 7030c078e31SDaniel Almeida struct vb2_queue *dst_vq) 7040c078e31SDaniel Almeida { 7050c078e31SDaniel Almeida struct visl_ctx *ctx = priv; 7060c078e31SDaniel Almeida int ret; 7070c078e31SDaniel Almeida 7080c078e31SDaniel Almeida src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 7090c078e31SDaniel Almeida src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 7100c078e31SDaniel Almeida src_vq->drv_priv = ctx; 7110c078e31SDaniel Almeida src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 7120c078e31SDaniel Almeida src_vq->ops = &visl_qops; 7130c078e31SDaniel Almeida src_vq->mem_ops = &vb2_vmalloc_memops; 7140c078e31SDaniel Almeida src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 7150c078e31SDaniel Almeida src_vq->lock = &ctx->vb_mutex; 7160c078e31SDaniel Almeida src_vq->supports_requests = true; 7170c078e31SDaniel Almeida src_vq->subsystem_flags |= VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; 7180c078e31SDaniel Almeida 7190c078e31SDaniel Almeida ret = vb2_queue_init(src_vq); 7200c078e31SDaniel Almeida if (ret) 7210c078e31SDaniel Almeida return ret; 7220c078e31SDaniel Almeida 7230c078e31SDaniel Almeida dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 7240c078e31SDaniel Almeida dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 7250c078e31SDaniel Almeida dst_vq->drv_priv = ctx; 7260c078e31SDaniel Almeida dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 7270c078e31SDaniel Almeida dst_vq->ops = &visl_qops; 7280c078e31SDaniel Almeida dst_vq->mem_ops = &vb2_vmalloc_memops; 7290c078e31SDaniel Almeida dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 7300c078e31SDaniel Almeida dst_vq->lock = &ctx->vb_mutex; 7310c078e31SDaniel Almeida 7320c078e31SDaniel Almeida return vb2_queue_init(dst_vq); 7330c078e31SDaniel Almeida } 7340c078e31SDaniel Almeida 7350c078e31SDaniel Almeida int visl_request_validate(struct media_request *req) 7360c078e31SDaniel Almeida { 7370c078e31SDaniel Almeida struct media_request_object *obj; 7380c078e31SDaniel Almeida struct visl_ctx *ctx = NULL; 7390c078e31SDaniel Almeida unsigned int count; 7400c078e31SDaniel Almeida 7410c078e31SDaniel Almeida list_for_each_entry(obj, &req->objects, list) { 7420c078e31SDaniel Almeida struct vb2_buffer *vb; 7430c078e31SDaniel Almeida 7440c078e31SDaniel Almeida if (vb2_request_object_is_buffer(obj)) { 7450c078e31SDaniel Almeida vb = container_of(obj, struct vb2_buffer, req_obj); 7460c078e31SDaniel Almeida ctx = vb2_get_drv_priv(vb->vb2_queue); 7470c078e31SDaniel Almeida 7480c078e31SDaniel Almeida break; 7490c078e31SDaniel Almeida } 7500c078e31SDaniel Almeida } 7510c078e31SDaniel Almeida 7520c078e31SDaniel Almeida if (!ctx) 7530c078e31SDaniel Almeida return -ENOENT; 7540c078e31SDaniel Almeida 7550c078e31SDaniel Almeida count = vb2_request_buffer_cnt(req); 7560c078e31SDaniel Almeida if (!count) { 7570c078e31SDaniel Almeida v4l2_err(&ctx->dev->v4l2_dev, 7580c078e31SDaniel Almeida "No buffer was provided with the request\n"); 7590c078e31SDaniel Almeida return -ENOENT; 7600c078e31SDaniel Almeida } else if (count > 1) { 7610c078e31SDaniel Almeida v4l2_err(&ctx->dev->v4l2_dev, 7620c078e31SDaniel Almeida "More than one buffer was provided with the request\n"); 7630c078e31SDaniel Almeida return -EINVAL; 7640c078e31SDaniel Almeida } 7650c078e31SDaniel Almeida 7660c078e31SDaniel Almeida return vb2_request_validate(req); 7670c078e31SDaniel Almeida } 768