brintos

brintos / linux-shallow public Read only

0
0
Text · 26.0 KiB · 62d3962 Raw
1002 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Hantro VPU codec driver4 *5 * Copyright (C) 2018 Collabora, Ltd.6 * Copyright (C) 2018 Rockchip Electronics Co., Ltd.7 *	Alpha Lin <Alpha.Lin@rock-chips.com>8 *	Jeffy Chen <jeffy.chen@rock-chips.com>9 *10 * Copyright 2018 Google LLC.11 *	Tomasz Figa <tfiga@chromium.org>12 *13 * Based on s5p-mfc driver by Samsung Electronics Co., Ltd.14 * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.15 */16 17#include <linux/interrupt.h>18#include <linux/io.h>19#include <linux/module.h>20#include <linux/pm_runtime.h>21#include <linux/videodev2.h>22#include <linux/workqueue.h>23#include <media/v4l2-ctrls.h>24#include <media/v4l2-event.h>25#include <media/v4l2-mem2mem.h>26 27#include "hantro.h"28#include "hantro_hw.h"29#include "hantro_v4l2.h"30 31#define  HANTRO_DEFAULT_BIT_DEPTH 832 33static int hantro_set_fmt_out(struct hantro_ctx *ctx,34			      struct v4l2_pix_format_mplane *pix_mp,35			      bool need_postproc);36static int hantro_set_fmt_cap(struct hantro_ctx *ctx,37			      struct v4l2_pix_format_mplane *pix_mp);38 39static const struct hantro_fmt *40hantro_get_formats(const struct hantro_ctx *ctx, unsigned int *num_fmts, bool need_postproc)41{42	const struct hantro_fmt *formats;43 44	if (need_postproc) {45		*num_fmts = 0;46		return NULL;47	}48 49	if (ctx->is_encoder) {50		formats = ctx->dev->variant->enc_fmts;51		*num_fmts = ctx->dev->variant->num_enc_fmts;52	} else {53		formats = ctx->dev->variant->dec_fmts;54		*num_fmts = ctx->dev->variant->num_dec_fmts;55	}56 57	return formats;58}59 60static const struct hantro_fmt *61hantro_get_postproc_formats(const struct hantro_ctx *ctx,62			    unsigned int *num_fmts)63{64	struct hantro_dev *vpu = ctx->dev;65 66	if (ctx->is_encoder || !vpu->variant->postproc_fmts) {67		*num_fmts = 0;68		return NULL;69	}70 71	*num_fmts = ctx->dev->variant->num_postproc_fmts;72	return ctx->dev->variant->postproc_fmts;73}74 75int hantro_get_format_depth(u32 fourcc)76{77	switch (fourcc) {78	case V4L2_PIX_FMT_P010:79	case V4L2_PIX_FMT_P010_4L4:80	case V4L2_PIX_FMT_NV15_4L4:81		return 10;82	default:83		return 8;84	}85}86 87static bool88hantro_check_depth_match(const struct hantro_fmt *fmt, int bit_depth)89{90	int fmt_depth;91 92	if (!fmt->match_depth && !fmt->postprocessed)93		return true;94 95	/* 0 means default depth, which is 8 */96	if (!bit_depth)97		bit_depth = HANTRO_DEFAULT_BIT_DEPTH;98 99	fmt_depth = hantro_get_format_depth(fmt->fourcc);100 101	/*102	 * Allow only downconversion for postproc formats for now.103	 * It may be possible to relax that on some HW.104	 */105	if (!fmt->match_depth)106		return fmt_depth <= bit_depth;107 108	return fmt_depth == bit_depth;109}110 111static const struct hantro_fmt *112hantro_find_format(const struct hantro_ctx *ctx, u32 fourcc)113{114	const struct hantro_fmt *formats;115	unsigned int i, num_fmts;116 117	formats = hantro_get_formats(ctx, &num_fmts, HANTRO_AUTO_POSTPROC);118	for (i = 0; i < num_fmts; i++)119		if (formats[i].fourcc == fourcc)120			return &formats[i];121 122	formats = hantro_get_postproc_formats(ctx, &num_fmts);123	for (i = 0; i < num_fmts; i++)124		if (formats[i].fourcc == fourcc)125			return &formats[i];126	return NULL;127}128 129const struct hantro_fmt *130hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream,131		       int bit_depth, bool need_postproc)132{133	const struct hantro_fmt *formats;134	unsigned int i, num_fmts;135 136	formats = hantro_get_formats(ctx, &num_fmts, need_postproc);137	for (i = 0; i < num_fmts; i++) {138		if (bitstream == (formats[i].codec_mode !=139				  HANTRO_MODE_NONE) &&140		    hantro_check_depth_match(&formats[i], bit_depth))141			return &formats[i];142	}143 144	formats = hantro_get_postproc_formats(ctx, &num_fmts);145	for (i = 0; i < num_fmts; i++) {146		if (bitstream == (formats[i].codec_mode !=147				  HANTRO_MODE_NONE) &&148		    hantro_check_depth_match(&formats[i], bit_depth))149			return &formats[i];150	}151 152	return NULL;153}154 155static int vidioc_querycap(struct file *file, void *priv,156			   struct v4l2_capability *cap)157{158	struct hantro_dev *vpu = video_drvdata(file);159	struct video_device *vdev = video_devdata(file);160 161	strscpy(cap->driver, vpu->dev->driver->name, sizeof(cap->driver));162	strscpy(cap->card, vdev->name, sizeof(cap->card));163	return 0;164}165 166static int vidioc_enum_framesizes(struct file *file, void *priv,167				  struct v4l2_frmsizeenum *fsize)168{169	struct hantro_ctx *ctx = fh_to_ctx(priv);170	const struct hantro_fmt *fmt;171 172	fmt = hantro_find_format(ctx, fsize->pixel_format);173	if (!fmt) {174		vpu_debug(0, "unsupported bitstream format (%08x)\n",175			  fsize->pixel_format);176		return -EINVAL;177	}178 179	/* For non-coded formats check if postprocessing scaling is possible */180	if (fmt->codec_mode == HANTRO_MODE_NONE) {181		if (hantro_needs_postproc(ctx, fmt))182			return hanto_postproc_enum_framesizes(ctx, fsize);183		else184			return -ENOTTY;185	} else if (fsize->index != 0) {186		vpu_debug(0, "invalid frame size index (expected 0, got %d)\n",187			  fsize->index);188		return -EINVAL;189	}190 191	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;192	fsize->stepwise = fmt->frmsize;193 194	return 0;195}196 197static int vidioc_enum_fmt(struct file *file, void *priv,198			   struct v4l2_fmtdesc *f, bool capture)199 200{201	struct hantro_ctx *ctx = fh_to_ctx(priv);202	const struct hantro_fmt *fmt, *formats;203	unsigned int num_fmts, i, j = 0;204	bool skip_mode_none;205 206	/*207	 * When dealing with an encoder:208	 *  - on the capture side we want to filter out all MODE_NONE formats.209	 *  - on the output side we want to filter out all formats that are210	 *    not MODE_NONE.211	 * When dealing with a decoder:212	 *  - on the capture side we want to filter out all formats that are213	 *    not MODE_NONE.214	 *  - on the output side we want to filter out all MODE_NONE formats.215	 */216	skip_mode_none = capture == ctx->is_encoder;217 218	formats = hantro_get_formats(ctx, &num_fmts, HANTRO_AUTO_POSTPROC);219	for (i = 0; i < num_fmts; i++) {220		bool mode_none = formats[i].codec_mode == HANTRO_MODE_NONE;221		fmt = &formats[i];222 223		if (skip_mode_none == mode_none)224			continue;225		if (!hantro_check_depth_match(fmt, ctx->bit_depth))226			continue;227		if (j == f->index) {228			f->pixelformat = fmt->fourcc;229			return 0;230		}231		++j;232	}233 234	/*235	 * Enumerate post-processed formats. As per the specification,236	 * we enumerated these formats after natively decoded formats237	 * as a hint for applications on what's the preferred fomat.238	 */239	if (!capture)240		return -EINVAL;241	formats = hantro_get_postproc_formats(ctx, &num_fmts);242	for (i = 0; i < num_fmts; i++) {243		fmt = &formats[i];244 245		if (!hantro_check_depth_match(fmt, ctx->bit_depth))246			continue;247		if (j == f->index) {248			f->pixelformat = fmt->fourcc;249			return 0;250		}251		++j;252	}253 254	return -EINVAL;255}256 257static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,258				   struct v4l2_fmtdesc *f)259{260	return vidioc_enum_fmt(file, priv, f, true);261}262 263static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,264				   struct v4l2_fmtdesc *f)265{266	return vidioc_enum_fmt(file, priv, f, false);267}268 269static int vidioc_g_fmt_out_mplane(struct file *file, void *priv,270				   struct v4l2_format *f)271{272	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;273	struct hantro_ctx *ctx = fh_to_ctx(priv);274 275	vpu_debug(4, "f->type = %d\n", f->type);276 277	*pix_mp = ctx->src_fmt;278 279	return 0;280}281 282static int vidioc_g_fmt_cap_mplane(struct file *file, void *priv,283				   struct v4l2_format *f)284{285	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;286	struct hantro_ctx *ctx = fh_to_ctx(priv);287 288	vpu_debug(4, "f->type = %d\n", f->type);289 290	*pix_mp = ctx->dst_fmt;291 292	return 0;293}294 295static int hantro_try_fmt(const struct hantro_ctx *ctx,296			  struct v4l2_pix_format_mplane *pix_mp,297			  enum v4l2_buf_type type)298{299	const struct hantro_fmt *fmt;300	const struct hantro_fmt *vpu_fmt;301	bool capture = V4L2_TYPE_IS_CAPTURE(type);302	bool coded;303 304	coded = capture == ctx->is_encoder;305 306	vpu_debug(4, "trying format %p4cc\n", &pix_mp->pixelformat);307 308	fmt = hantro_find_format(ctx, pix_mp->pixelformat);309	if (!fmt) {310		fmt = hantro_get_default_fmt(ctx, coded, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC);311		pix_mp->pixelformat = fmt->fourcc;312	}313 314	if (coded) {315		pix_mp->num_planes = 1;316		vpu_fmt = fmt;317	} else if (ctx->is_encoder) {318		vpu_fmt = hantro_find_format(ctx, ctx->dst_fmt.pixelformat);319	} else {320		/*321		 * Width/height on the CAPTURE end of a decoder are ignored and322		 * replaced by the OUTPUT ones.323		 */324		pix_mp->width = ctx->src_fmt.width;325		pix_mp->height = ctx->src_fmt.height;326		vpu_fmt = fmt;327	}328 329	pix_mp->field = V4L2_FIELD_NONE;330 331	v4l2_apply_frmsize_constraints(&pix_mp->width, &pix_mp->height,332				       &vpu_fmt->frmsize);333 334	if (!coded) {335		/* Fill remaining fields */336		v4l2_fill_pixfmt_mp(pix_mp, fmt->fourcc, pix_mp->width,337				    pix_mp->height);338		if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_H264_SLICE &&339		    !hantro_needs_postproc(ctx, fmt))340			pix_mp->plane_fmt[0].sizeimage +=341				hantro_h264_mv_size(pix_mp->width,342						    pix_mp->height);343		else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_VP9_FRAME &&344			 !hantro_needs_postproc(ctx, fmt))345			pix_mp->plane_fmt[0].sizeimage +=346				hantro_vp9_mv_size(pix_mp->width,347						   pix_mp->height);348		else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_HEVC_SLICE &&349			 !hantro_needs_postproc(ctx, fmt))350			pix_mp->plane_fmt[0].sizeimage +=351				hantro_hevc_mv_size(pix_mp->width,352						    pix_mp->height);353		else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_AV1_FRAME &&354			 !hantro_needs_postproc(ctx, fmt))355			pix_mp->plane_fmt[0].sizeimage +=356				hantro_av1_mv_size(pix_mp->width,357						   pix_mp->height);358	} else if (!pix_mp->plane_fmt[0].sizeimage) {359		/*360		 * For coded formats the application can specify361		 * sizeimage. If the application passes a zero sizeimage,362		 * let's default to the maximum frame size.363		 */364		pix_mp->plane_fmt[0].sizeimage = fmt->header_size +365			pix_mp->width * pix_mp->height * fmt->max_depth;366	}367 368	return 0;369}370 371static int vidioc_try_fmt_cap_mplane(struct file *file, void *priv,372				     struct v4l2_format *f)373{374	return hantro_try_fmt(fh_to_ctx(priv), &f->fmt.pix_mp, f->type);375}376 377static int vidioc_try_fmt_out_mplane(struct file *file, void *priv,378				     struct v4l2_format *f)379{380	return hantro_try_fmt(fh_to_ctx(priv), &f->fmt.pix_mp, f->type);381}382 383static void384hantro_reset_fmt(struct v4l2_pix_format_mplane *fmt,385		 const struct hantro_fmt *vpu_fmt)386{387	memset(fmt, 0, sizeof(*fmt));388 389	fmt->pixelformat = vpu_fmt->fourcc;390	fmt->field = V4L2_FIELD_NONE;391	fmt->colorspace = V4L2_COLORSPACE_JPEG;392	fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;393	fmt->quantization = V4L2_QUANTIZATION_DEFAULT;394	fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT;395}396 397static void398hantro_reset_encoded_fmt(struct hantro_ctx *ctx)399{400	const struct hantro_fmt *vpu_fmt;401	struct v4l2_pix_format_mplane fmt;402 403	vpu_fmt = hantro_get_default_fmt(ctx, true, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC);404	if (!vpu_fmt)405		return;406 407	hantro_reset_fmt(&fmt, vpu_fmt);408	fmt.width = vpu_fmt->frmsize.min_width;409	fmt.height = vpu_fmt->frmsize.min_height;410	if (ctx->is_encoder)411		hantro_set_fmt_cap(ctx, &fmt);412	else413		hantro_set_fmt_out(ctx, &fmt, HANTRO_AUTO_POSTPROC);414}415 416int417hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth, bool need_postproc)418{419	const struct hantro_fmt *raw_vpu_fmt;420	struct v4l2_pix_format_mplane raw_fmt, *encoded_fmt;421	int ret;422 423	raw_vpu_fmt = hantro_get_default_fmt(ctx, false, bit_depth, need_postproc);424	if (!raw_vpu_fmt)425		return -EINVAL;426 427	if (ctx->is_encoder) {428		encoded_fmt = &ctx->dst_fmt;429		ctx->vpu_src_fmt = raw_vpu_fmt;430	} else {431		encoded_fmt = &ctx->src_fmt;432	}433 434	hantro_reset_fmt(&raw_fmt, raw_vpu_fmt);435	raw_fmt.width = encoded_fmt->width;436	raw_fmt.height = encoded_fmt->height;437	if (ctx->is_encoder)438		ret = hantro_set_fmt_out(ctx, &raw_fmt, need_postproc);439	else440		ret = hantro_set_fmt_cap(ctx, &raw_fmt);441 442	if (!ret) {443		ctx->bit_depth = bit_depth;444		ctx->need_postproc = need_postproc;445	}446 447	return ret;448}449 450void hantro_reset_fmts(struct hantro_ctx *ctx)451{452	hantro_reset_encoded_fmt(ctx);453	hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC);454}455 456static void457hantro_update_requires_request(struct hantro_ctx *ctx, u32 fourcc)458{459	switch (fourcc) {460	case V4L2_PIX_FMT_JPEG:461		ctx->fh.m2m_ctx->out_q_ctx.q.requires_requests = false;462		break;463	case V4L2_PIX_FMT_MPEG2_SLICE:464	case V4L2_PIX_FMT_VP8_FRAME:465	case V4L2_PIX_FMT_H264_SLICE:466	case V4L2_PIX_FMT_HEVC_SLICE:467	case V4L2_PIX_FMT_VP9_FRAME:468		ctx->fh.m2m_ctx->out_q_ctx.q.requires_requests = true;469		break;470	default:471		break;472	}473}474 475static void476hantro_update_requires_hold_capture_buf(struct hantro_ctx *ctx, u32 fourcc)477{478	struct vb2_queue *vq;479 480	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,481			     V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);482 483	switch (fourcc) {484	case V4L2_PIX_FMT_JPEG:485	case V4L2_PIX_FMT_MPEG2_SLICE:486	case V4L2_PIX_FMT_VP8_FRAME:487	case V4L2_PIX_FMT_HEVC_SLICE:488	case V4L2_PIX_FMT_VP9_FRAME:489		vq->subsystem_flags &= ~(VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF);490		break;491	case V4L2_PIX_FMT_H264_SLICE:492		vq->subsystem_flags |= VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;493		break;494	default:495		break;496	}497}498 499static int hantro_set_fmt_out(struct hantro_ctx *ctx,500			      struct v4l2_pix_format_mplane *pix_mp,501			      bool need_postproc)502{503	struct vb2_queue *vq;504	int ret;505 506	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,507			     V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);508	ret = hantro_try_fmt(ctx, pix_mp, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);509	if (ret)510		return ret;511 512	if (!ctx->is_encoder) {513		/*514		 * In order to support dynamic resolution change,515		 * the decoder admits a resolution change, as long516		 * as the pixelformat remains.517		 */518		if (vb2_is_streaming(vq) && pix_mp->pixelformat != ctx->src_fmt.pixelformat) {519			return -EBUSY;520		}521	} else {522		/*523		 * The encoder doesn't admit a format change if524		 * there are OUTPUT buffers allocated.525		 */526		if (vb2_is_busy(vq))527			return -EBUSY;528	}529 530	ctx->vpu_src_fmt = hantro_find_format(ctx, pix_mp->pixelformat);531	ctx->src_fmt = *pix_mp;532 533	/*534	 * Current raw format might have become invalid with newly535	 * selected codec, so reset it to default just to be safe and536	 * keep internal driver state sane. User is mandated to set537	 * the raw format again after we return, so we don't need538	 * anything smarter.539	 * Note that hantro_reset_raw_fmt() also propagates size540	 * changes to the raw format.541	 */542	if (!ctx->is_encoder)543		hantro_reset_raw_fmt(ctx,544				     hantro_get_format_depth(pix_mp->pixelformat),545				     need_postproc);546 547	/* Colorimetry information are always propagated. */548	ctx->dst_fmt.colorspace = pix_mp->colorspace;549	ctx->dst_fmt.ycbcr_enc = pix_mp->ycbcr_enc;550	ctx->dst_fmt.xfer_func = pix_mp->xfer_func;551	ctx->dst_fmt.quantization = pix_mp->quantization;552 553	hantro_update_requires_request(ctx, pix_mp->pixelformat);554	hantro_update_requires_hold_capture_buf(ctx, pix_mp->pixelformat);555 556	vpu_debug(0, "OUTPUT codec mode: %d\n", ctx->vpu_src_fmt->codec_mode);557	vpu_debug(0, "fmt - w: %d, h: %d\n",558		  pix_mp->width, pix_mp->height);559	return 0;560}561 562static int hantro_set_fmt_cap(struct hantro_ctx *ctx,563			      struct v4l2_pix_format_mplane *pix_mp)564{565	int ret;566 567	if (ctx->is_encoder) {568		struct vb2_queue *peer_vq;569 570		/*571		 * Since format change on the CAPTURE queue will reset572		 * the OUTPUT queue, we can't allow doing so573		 * when the OUTPUT queue has buffers allocated.574		 */575		peer_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,576					  V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);577		if (vb2_is_busy(peer_vq) &&578		    (pix_mp->pixelformat != ctx->dst_fmt.pixelformat ||579		     pix_mp->height != ctx->dst_fmt.height ||580		     pix_mp->width != ctx->dst_fmt.width))581			return -EBUSY;582	}583 584	ret = hantro_try_fmt(ctx, pix_mp, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);585	if (ret)586		return ret;587 588	ctx->vpu_dst_fmt = hantro_find_format(ctx, pix_mp->pixelformat);589	ctx->dst_fmt = *pix_mp;590 591	/*592	 * Current raw format might have become invalid with newly593	 * selected codec, so reset it to default just to be safe and594	 * keep internal driver state sane. User is mandated to set595	 * the raw format again after we return, so we don't need596	 * anything smarter.597	 * Note that hantro_reset_raw_fmt() also propagates size598	 * changes to the raw format.599	 */600	if (ctx->is_encoder)601		hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC);602 603	/* Colorimetry information are always propagated. */604	ctx->src_fmt.colorspace = pix_mp->colorspace;605	ctx->src_fmt.ycbcr_enc = pix_mp->ycbcr_enc;606	ctx->src_fmt.xfer_func = pix_mp->xfer_func;607	ctx->src_fmt.quantization = pix_mp->quantization;608 609	vpu_debug(0, "CAPTURE codec mode: %d\n", ctx->vpu_dst_fmt->codec_mode);610	vpu_debug(0, "fmt - w: %d, h: %d\n",611		  pix_mp->width, pix_mp->height);612 613	hantro_update_requires_request(ctx, pix_mp->pixelformat);614 615	return 0;616}617 618static int619vidioc_s_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f)620{621	return hantro_set_fmt_out(fh_to_ctx(priv), &f->fmt.pix_mp, HANTRO_AUTO_POSTPROC);622}623 624static int625vidioc_s_fmt_cap_mplane(struct file *file, void *priv, struct v4l2_format *f)626{627	return hantro_set_fmt_cap(fh_to_ctx(priv), &f->fmt.pix_mp);628}629 630static int vidioc_g_selection(struct file *file, void *priv,631			      struct v4l2_selection *sel)632{633	struct hantro_ctx *ctx = fh_to_ctx(priv);634 635	/* Crop only supported on source. */636	if (!ctx->is_encoder ||637	    sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)638		return -EINVAL;639 640	switch (sel->target) {641	case V4L2_SEL_TGT_CROP_DEFAULT:642	case V4L2_SEL_TGT_CROP_BOUNDS:643		sel->r.top = 0;644		sel->r.left = 0;645		sel->r.width = ctx->src_fmt.width;646		sel->r.height = ctx->src_fmt.height;647		break;648	case V4L2_SEL_TGT_CROP:649		sel->r.top = 0;650		sel->r.left = 0;651		sel->r.width = ctx->dst_fmt.width;652		sel->r.height = ctx->dst_fmt.height;653		break;654	default:655		return -EINVAL;656	}657 658	return 0;659}660 661static int vidioc_s_selection(struct file *file, void *priv,662			      struct v4l2_selection *sel)663{664	struct hantro_ctx *ctx = fh_to_ctx(priv);665	struct v4l2_rect *rect = &sel->r;666	struct vb2_queue *vq;667 668	/* Crop only supported on source. */669	if (!ctx->is_encoder ||670	    sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)671		return -EINVAL;672 673	/* Change not allowed if the queue is streaming. */674	vq = v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx);675	if (vb2_is_streaming(vq))676		return -EBUSY;677 678	if (sel->target != V4L2_SEL_TGT_CROP)679		return -EINVAL;680 681	/*682	 * We do not support offsets, and we can crop only inside683	 * right-most or bottom-most macroblocks.684	 */685	if (rect->left != 0 || rect->top != 0 ||686	    round_up(rect->width, MB_DIM) != ctx->src_fmt.width ||687	    round_up(rect->height, MB_DIM) != ctx->src_fmt.height) {688		/* Default to full frame for incorrect settings. */689		rect->left = 0;690		rect->top = 0;691		rect->width = ctx->src_fmt.width;692		rect->height = ctx->src_fmt.height;693	} else {694		/* We support widths aligned to 4 pixels and arbitrary heights. */695		rect->width = round_up(rect->width, 4);696	}697 698	ctx->dst_fmt.width = rect->width;699	ctx->dst_fmt.height = rect->height;700 701	return 0;702}703 704static const struct v4l2_event hantro_eos_event = {705	.type = V4L2_EVENT_EOS706};707 708static int vidioc_encoder_cmd(struct file *file, void *priv,709			      struct v4l2_encoder_cmd *ec)710{711	struct hantro_ctx *ctx = fh_to_ctx(priv);712	int ret;713 714	ret = v4l2_m2m_ioctl_try_encoder_cmd(file, priv, ec);715	if (ret < 0)716		return ret;717 718	if (!vb2_is_streaming(v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx)) ||719	    !vb2_is_streaming(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx)))720		return 0;721 722	ret = v4l2_m2m_ioctl_encoder_cmd(file, priv, ec);723	if (ret < 0)724		return ret;725 726	if (ec->cmd == V4L2_ENC_CMD_STOP &&727	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))728		v4l2_event_queue_fh(&ctx->fh, &hantro_eos_event);729 730	if (ec->cmd == V4L2_ENC_CMD_START)731		vb2_clear_last_buffer_dequeued(&ctx->fh.m2m_ctx->cap_q_ctx.q);732 733	return 0;734}735 736const struct v4l2_ioctl_ops hantro_ioctl_ops = {737	.vidioc_querycap = vidioc_querycap,738	.vidioc_enum_framesizes = vidioc_enum_framesizes,739 740	.vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_cap_mplane,741	.vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_out_mplane,742	.vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_out_mplane,743	.vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_cap_mplane,744	.vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_out_mplane,745	.vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_cap_mplane,746	.vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,747	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,748 749	.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,750	.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,751	.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,752	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,753	.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,754	.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,755	.vidioc_remove_bufs = v4l2_m2m_ioctl_remove_bufs,756	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,757 758	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,759	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,760 761	.vidioc_streamon = v4l2_m2m_ioctl_streamon,762	.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,763 764	.vidioc_g_selection = vidioc_g_selection,765	.vidioc_s_selection = vidioc_s_selection,766 767	.vidioc_decoder_cmd = v4l2_m2m_ioctl_stateless_decoder_cmd,768	.vidioc_try_decoder_cmd = v4l2_m2m_ioctl_stateless_try_decoder_cmd,769 770	.vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,771	.vidioc_encoder_cmd = vidioc_encoder_cmd,772};773 774static int775hantro_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,776		   unsigned int *num_planes, unsigned int sizes[],777		   struct device *alloc_devs[])778{779	struct hantro_ctx *ctx = vb2_get_drv_priv(vq);780	struct v4l2_pix_format_mplane *pixfmt;781	int i;782 783	switch (vq->type) {784	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:785		pixfmt = &ctx->dst_fmt;786		break;787	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:788		pixfmt = &ctx->src_fmt;789		break;790	default:791		vpu_err("invalid queue type: %d\n", vq->type);792		return -EINVAL;793	}794 795	if (*num_planes) {796		if (*num_planes != pixfmt->num_planes)797			return -EINVAL;798		for (i = 0; i < pixfmt->num_planes; ++i)799			if (sizes[i] < pixfmt->plane_fmt[i].sizeimage)800				return -EINVAL;801		return 0;802	}803 804	*num_planes = pixfmt->num_planes;805	for (i = 0; i < pixfmt->num_planes; ++i)806		sizes[i] = pixfmt->plane_fmt[i].sizeimage;807	return 0;808}809 810static int811hantro_buf_plane_check(struct vb2_buffer *vb,812		       struct v4l2_pix_format_mplane *pixfmt)813{814	unsigned int sz;815	int i;816 817	for (i = 0; i < pixfmt->num_planes; ++i) {818		sz = pixfmt->plane_fmt[i].sizeimage;819		vpu_debug(4, "plane %d size: %ld, sizeimage: %u\n",820			  i, vb2_plane_size(vb, i), sz);821		if (vb2_plane_size(vb, i) < sz) {822			vpu_err("plane %d is too small for output\n", i);823			return -EINVAL;824		}825	}826	return 0;827}828 829static int hantro_buf_prepare(struct vb2_buffer *vb)830{831	struct vb2_queue *vq = vb->vb2_queue;832	struct hantro_ctx *ctx = vb2_get_drv_priv(vq);833	struct v4l2_pix_format_mplane *pix_fmt;834	int ret;835 836	if (V4L2_TYPE_IS_OUTPUT(vq->type))837		pix_fmt = &ctx->src_fmt;838	else839		pix_fmt = &ctx->dst_fmt;840	ret = hantro_buf_plane_check(vb, pix_fmt);841	if (ret)842		return ret;843	/*844	 * Buffer's bytesused must be written by driver for CAPTURE buffers.845	 * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets846	 * it to buffer length).847	 */848	if (V4L2_TYPE_IS_CAPTURE(vq->type)) {849		if (ctx->is_encoder)850			vb2_set_plane_payload(vb, 0, 0);851		else852			vb2_set_plane_payload(vb, 0, pix_fmt->plane_fmt[0].sizeimage);853	}854 855	return 0;856}857 858static void hantro_buf_queue(struct vb2_buffer *vb)859{860	struct hantro_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);861	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);862 863	if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) &&864	    vb2_is_streaming(vb->vb2_queue) &&865	    v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) {866		unsigned int i;867 868		for (i = 0; i < vb->num_planes; i++)869			vb2_set_plane_payload(vb, i, 0);870 871		vbuf->field = V4L2_FIELD_NONE;872		vbuf->sequence = ctx->sequence_cap++;873 874		v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf);875		v4l2_event_queue_fh(&ctx->fh, &hantro_eos_event);876		return;877	}878 879	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);880}881 882static bool hantro_vq_is_coded(struct vb2_queue *q)883{884	struct hantro_ctx *ctx = vb2_get_drv_priv(q);885 886	return ctx->is_encoder != V4L2_TYPE_IS_OUTPUT(q->type);887}888 889static int hantro_start_streaming(struct vb2_queue *q, unsigned int count)890{891	struct hantro_ctx *ctx = vb2_get_drv_priv(q);892	int ret = 0;893 894	v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q);895 896	if (V4L2_TYPE_IS_OUTPUT(q->type))897		ctx->sequence_out = 0;898	else899		ctx->sequence_cap = 0;900 901	if (hantro_vq_is_coded(q)) {902		enum hantro_codec_mode codec_mode;903 904		if (V4L2_TYPE_IS_OUTPUT(q->type))905			codec_mode = ctx->vpu_src_fmt->codec_mode;906		else907			codec_mode = ctx->vpu_dst_fmt->codec_mode;908 909		vpu_debug(4, "Codec mode = %d\n", codec_mode);910		ctx->codec_ops = &ctx->dev->variant->codec_ops[codec_mode];911		if (ctx->codec_ops->init) {912			ret = ctx->codec_ops->init(ctx);913			if (ret)914				return ret;915		}916 917		if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) {918			ret = hantro_postproc_init(ctx);919			if (ret)920				goto err_codec_exit;921		}922	}923	return ret;924 925err_codec_exit:926	if (ctx->codec_ops->exit)927		ctx->codec_ops->exit(ctx);928	return ret;929}930 931static void932hantro_return_bufs(struct vb2_queue *q,933		   struct vb2_v4l2_buffer *(*buf_remove)(struct v4l2_m2m_ctx *))934{935	struct hantro_ctx *ctx = vb2_get_drv_priv(q);936 937	for (;;) {938		struct vb2_v4l2_buffer *vbuf;939 940		vbuf = buf_remove(ctx->fh.m2m_ctx);941		if (!vbuf)942			break;943		v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,944					   &ctx->ctrl_handler);945		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);946	}947}948 949static void hantro_stop_streaming(struct vb2_queue *q)950{951	struct hantro_ctx *ctx = vb2_get_drv_priv(q);952 953	if (hantro_vq_is_coded(q)) {954		hantro_postproc_free(ctx);955		if (ctx->codec_ops && ctx->codec_ops->exit)956			ctx->codec_ops->exit(ctx);957	}958 959	/*960	 * The mem2mem framework calls v4l2_m2m_cancel_job before961	 * .stop_streaming, so there isn't any job running and962	 * it is safe to return all the buffers.963	 */964	if (V4L2_TYPE_IS_OUTPUT(q->type))965		hantro_return_bufs(q, v4l2_m2m_src_buf_remove);966	else967		hantro_return_bufs(q, v4l2_m2m_dst_buf_remove);968 969	v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q);970 971	if (V4L2_TYPE_IS_OUTPUT(q->type) &&972	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))973		v4l2_event_queue_fh(&ctx->fh, &hantro_eos_event);974}975 976static void hantro_buf_request_complete(struct vb2_buffer *vb)977{978	struct hantro_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);979 980	v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->ctrl_handler);981}982 983static int hantro_buf_out_validate(struct vb2_buffer *vb)984{985	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);986 987	vbuf->field = V4L2_FIELD_NONE;988	return 0;989}990 991const struct vb2_ops hantro_queue_ops = {992	.queue_setup = hantro_queue_setup,993	.buf_prepare = hantro_buf_prepare,994	.buf_queue = hantro_buf_queue,995	.buf_out_validate = hantro_buf_out_validate,996	.buf_request_complete = hantro_buf_request_complete,997	.start_streaming = hantro_start_streaming,998	.stop_streaming = hantro_stop_streaming,999	.wait_prepare = vb2_ops_wait_prepare,1000	.wait_finish = vb2_ops_wait_finish,1001};1002