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