brintos

brintos / linux-shallow public Read only

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