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