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