linux/drivers/staging/media/hantro/hantro_v4l2.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Hantro VPU codec driver
   4 *
   5 * Copyright (C) 2018 Collabora, Ltd.
   6 * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
   7 *      Alpha Lin <Alpha.Lin@rock-chips.com>
   8 *      Jeffy Chen <jeffy.chen@rock-chips.com>
   9 *
  10 * Copyright 2018 Google LLC.
  11 *      Tomasz Figa <tfiga@chromium.org>
  12 *
  13 * Based on s5p-mfc driver by Samsung Electronics Co., Ltd.
  14 * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
  15 */
  16
  17#include <linux/interrupt.h>
  18#include <linux/io.h>
  19#include <linux/module.h>
  20#include <linux/pm_runtime.h>
  21#include <linux/videodev2.h>
  22#include <linux/workqueue.h>
  23#include <media/v4l2-ctrls.h>
  24#include <media/v4l2-event.h>
  25#include <media/v4l2-mem2mem.h>
  26#include <media/videobuf2-core.h>
  27#include <media/videobuf2-dma-sg.h>
  28
  29#include "hantro.h"
  30#include "hantro_hw.h"
  31#include "hantro_v4l2.h"
  32
  33static int hantro_set_fmt_out(struct hantro_ctx *ctx,
  34                              struct v4l2_pix_format_mplane *pix_mp);
  35static int hantro_set_fmt_cap(struct hantro_ctx *ctx,
  36                              struct v4l2_pix_format_mplane *pix_mp);
  37
  38static const struct hantro_fmt *
  39hantro_get_formats(const struct hantro_ctx *ctx, unsigned int *num_fmts)
  40{
  41        const struct hantro_fmt *formats;
  42
  43        if (ctx->is_encoder) {
  44                formats = ctx->dev->variant->enc_fmts;
  45                *num_fmts = ctx->dev->variant->num_enc_fmts;
  46        } else {
  47                formats = ctx->dev->variant->dec_fmts;
  48                *num_fmts = ctx->dev->variant->num_dec_fmts;
  49        }
  50
  51        return formats;
  52}
  53
  54static const struct hantro_fmt *
  55hantro_get_postproc_formats(const struct hantro_ctx *ctx,
  56                            unsigned int *num_fmts)
  57{
  58        if (ctx->is_encoder) {
  59                *num_fmts = 0;
  60                return NULL;
  61        }
  62
  63        *num_fmts = ctx->dev->variant->num_postproc_fmts;
  64        return ctx->dev->variant->postproc_fmts;
  65}
  66
  67static const struct hantro_fmt *
  68hantro_find_format(const struct hantro_ctx *ctx, u32 fourcc)
  69{
  70        const struct hantro_fmt *formats;
  71        unsigned int i, num_fmts;
  72
  73        formats = hantro_get_formats(ctx, &num_fmts);
  74        for (i = 0; i < num_fmts; i++)
  75                if (formats[i].fourcc == fourcc)
  76                        return &formats[i];
  77
  78        formats = hantro_get_postproc_formats(ctx, &num_fmts);
  79        for (i = 0; i < num_fmts; i++)
  80                if (formats[i].fourcc == fourcc)
  81                        return &formats[i];
  82        return NULL;
  83}
  84
  85static const struct hantro_fmt *
  86hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream)
  87{
  88        const struct hantro_fmt *formats;
  89        unsigned int i, num_fmts;
  90
  91        formats = hantro_get_formats(ctx, &num_fmts);
  92        for (i = 0; i < num_fmts; i++) {
  93                if (bitstream == (formats[i].codec_mode !=
  94                                  HANTRO_MODE_NONE))
  95                        return &formats[i];
  96        }
  97        return NULL;
  98}
  99
 100static int vidioc_querycap(struct file *file, void *priv,
 101                           struct v4l2_capability *cap)
 102{
 103        struct hantro_dev *vpu = video_drvdata(file);
 104        struct video_device *vdev = video_devdata(file);
 105
 106        strscpy(cap->driver, vpu->dev->driver->name, sizeof(cap->driver));
 107        strscpy(cap->card, vdev->name, sizeof(cap->card));
 108        snprintf(cap->bus_info, sizeof(cap->bus_info), "platform: %s",
 109                 vpu->dev->driver->name);
 110        return 0;
 111}
 112
 113static int vidioc_enum_framesizes(struct file *file, void *priv,
 114                                  struct v4l2_frmsizeenum *fsize)
 115{
 116        struct hantro_ctx *ctx = fh_to_ctx(priv);
 117        const struct hantro_fmt *fmt;
 118
 119        if (fsize->index != 0) {
 120                vpu_debug(0, "invalid frame size index (expected 0, got %d)\n",
 121                          fsize->index);
 122                return -EINVAL;
 123        }
 124
 125        fmt = hantro_find_format(ctx, fsize->pixel_format);
 126        if (!fmt) {
 127                vpu_debug(0, "unsupported bitstream format (%08x)\n",
 128                          fsize->pixel_format);
 129                return -EINVAL;
 130        }
 131
 132        /* This only makes sense for coded formats */
 133        if (fmt->codec_mode == HANTRO_MODE_NONE)
 134                return -EINVAL;
 135
 136        fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
 137        fsize->stepwise = fmt->frmsize;
 138
 139        return 0;
 140}
 141
 142static int vidioc_enum_fmt(struct file *file, void *priv,
 143                           struct v4l2_fmtdesc *f, bool capture)
 144
 145{
 146        struct hantro_ctx *ctx = fh_to_ctx(priv);
 147        const struct hantro_fmt *fmt, *formats;
 148        unsigned int num_fmts, i, j = 0;
 149        bool skip_mode_none;
 150
 151        /*
 152         * When dealing with an encoder:
 153         *  - on the capture side we want to filter out all MODE_NONE formats.
 154         *  - on the output side we want to filter out all formats that are
 155         *    not MODE_NONE.
 156         * When dealing with a decoder:
 157         *  - on the capture side we want to filter out all formats that are
 158         *    not MODE_NONE.
 159         *  - on the output side we want to filter out all MODE_NONE formats.
 160         */
 161        skip_mode_none = capture == ctx->is_encoder;
 162
 163        formats = hantro_get_formats(ctx, &num_fmts);
 164        for (i = 0; i < num_fmts; i++) {
 165                bool mode_none = formats[i].codec_mode == HANTRO_MODE_NONE;
 166
 167                if (skip_mode_none == mode_none)
 168                        continue;
 169                if (j == f->index) {
 170                        fmt = &formats[i];
 171                        f->pixelformat = fmt->fourcc;
 172                        return 0;
 173                }
 174                ++j;
 175        }
 176
 177        /*
 178         * Enumerate post-processed formats. As per the specification,
 179         * we enumerated these formats after natively decoded formats
 180         * as a hint for applications on what's the preferred fomat.
 181         */
 182        if (!capture)
 183                return -EINVAL;
 184        formats = hantro_get_postproc_formats(ctx, &num_fmts);
 185        for (i = 0; i < num_fmts; i++) {
 186                if (j == f->index) {
 187                        fmt = &formats[i];
 188                        f->pixelformat = fmt->fourcc;
 189                        return 0;
 190                }
 191                ++j;
 192        }
 193
 194        return -EINVAL;
 195}
 196
 197static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
 198                                   struct v4l2_fmtdesc *f)
 199{
 200        return vidioc_enum_fmt(file, priv, f, true);
 201}
 202
 203static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
 204                                   struct v4l2_fmtdesc *f)
 205{
 206        return vidioc_enum_fmt(file, priv, f, false);
 207}
 208
 209static int vidioc_g_fmt_out_mplane(struct file *file, void *priv,
 210                                   struct v4l2_format *f)
 211{
 212        struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
 213        struct hantro_ctx *ctx = fh_to_ctx(priv);
 214
 215        vpu_debug(4, "f->type = %d\n", f->type);
 216
 217        *pix_mp = ctx->src_fmt;
 218
 219        return 0;
 220}
 221
 222static int vidioc_g_fmt_cap_mplane(struct file *file, void *priv,
 223                                   struct v4l2_format *f)
 224{
 225        struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
 226        struct hantro_ctx *ctx = fh_to_ctx(priv);
 227
 228        vpu_debug(4, "f->type = %d\n", f->type);
 229
 230        *pix_mp = ctx->dst_fmt;
 231
 232        return 0;
 233}
 234
 235static int hantro_try_fmt(const struct hantro_ctx *ctx,
 236                          struct v4l2_pix_format_mplane *pix_mp,
 237                          enum v4l2_buf_type type)
 238{
 239        const struct hantro_fmt *fmt, *vpu_fmt;
 240        bool capture = V4L2_TYPE_IS_CAPTURE(type);
 241        bool coded;
 242
 243        coded = capture == ctx->is_encoder;
 244
 245        vpu_debug(4, "trying format %c%c%c%c\n",
 246                  (pix_mp->pixelformat & 0x7f),
 247                  (pix_mp->pixelformat >> 8) & 0x7f,
 248                  (pix_mp->pixelformat >> 16) & 0x7f,
 249                  (pix_mp->pixelformat >> 24) & 0x7f);
 250
 251        fmt = hantro_find_format(ctx, pix_mp->pixelformat);
 252        if (!fmt) {
 253                fmt = hantro_get_default_fmt(ctx, coded);
 254                pix_mp->pixelformat = fmt->fourcc;
 255        }
 256
 257        if (coded) {
 258                pix_mp->num_planes = 1;
 259                vpu_fmt = fmt;
 260        } else if (ctx->is_encoder) {
 261                vpu_fmt = ctx->vpu_dst_fmt;
 262        } else {
 263                vpu_fmt = ctx->vpu_src_fmt;
 264                /*
 265                 * Width/height on the CAPTURE end of a decoder are ignored and
 266                 * replaced by the OUTPUT ones.
 267                 */
 268                pix_mp->width = ctx->src_fmt.width;
 269                pix_mp->height = ctx->src_fmt.height;
 270        }
 271
 272        pix_mp->field = V4L2_FIELD_NONE;
 273
 274        v4l2_apply_frmsize_constraints(&pix_mp->width, &pix_mp->height,
 275                                       &vpu_fmt->frmsize);
 276
 277        if (!coded) {
 278                /* Fill remaining fields */
 279                v4l2_fill_pixfmt_mp(pix_mp, fmt->fourcc, pix_mp->width,
 280                                    pix_mp->height);
 281                if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_H264_SLICE &&
 282                    !hantro_needs_postproc(ctx, fmt))
 283                        pix_mp->plane_fmt[0].sizeimage +=
 284                                hantro_h264_mv_size(pix_mp->width,
 285                                                    pix_mp->height);
 286        } else if (!pix_mp->plane_fmt[0].sizeimage) {
 287                /*
 288                 * For coded formats the application can specify
 289                 * sizeimage. If the application passes a zero sizeimage,
 290                 * let's default to the maximum frame size.
 291                 */
 292                pix_mp->plane_fmt[0].sizeimage = fmt->header_size +
 293                        pix_mp->width * pix_mp->height * fmt->max_depth;
 294        }
 295
 296        return 0;
 297}
 298
 299static int vidioc_try_fmt_cap_mplane(struct file *file, void *priv,
 300                                     struct v4l2_format *f)
 301{
 302        return hantro_try_fmt(fh_to_ctx(priv), &f->fmt.pix_mp, f->type);
 303}
 304
 305static int vidioc_try_fmt_out_mplane(struct file *file, void *priv,
 306                                     struct v4l2_format *f)
 307{
 308        return hantro_try_fmt(fh_to_ctx(priv), &f->fmt.pix_mp, f->type);
 309}
 310
 311static void
 312hantro_reset_fmt(struct v4l2_pix_format_mplane *fmt,
 313                 const struct hantro_fmt *vpu_fmt)
 314{
 315        memset(fmt, 0, sizeof(*fmt));
 316
 317        fmt->pixelformat = vpu_fmt->fourcc;
 318        fmt->field = V4L2_FIELD_NONE;
 319        fmt->colorspace = V4L2_COLORSPACE_JPEG;
 320        fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
 321        fmt->quantization = V4L2_QUANTIZATION_DEFAULT;
 322        fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT;
 323}
 324
 325static void
 326hantro_reset_encoded_fmt(struct hantro_ctx *ctx)
 327{
 328        const struct hantro_fmt *vpu_fmt;
 329        struct v4l2_pix_format_mplane *fmt;
 330
 331        vpu_fmt = hantro_get_default_fmt(ctx, true);
 332
 333        if (ctx->is_encoder) {
 334                ctx->vpu_dst_fmt = vpu_fmt;
 335                fmt = &ctx->dst_fmt;
 336        } else {
 337                ctx->vpu_src_fmt = vpu_fmt;
 338                fmt = &ctx->src_fmt;
 339        }
 340
 341        hantro_reset_fmt(fmt, vpu_fmt);
 342        fmt->width = vpu_fmt->frmsize.min_width;
 343        fmt->height = vpu_fmt->frmsize.min_height;
 344        if (ctx->is_encoder)
 345                hantro_set_fmt_cap(ctx, fmt);
 346        else
 347                hantro_set_fmt_out(ctx, fmt);
 348}
 349
 350static void
 351hantro_reset_raw_fmt(struct hantro_ctx *ctx)
 352{
 353        const struct hantro_fmt *raw_vpu_fmt;
 354        struct v4l2_pix_format_mplane *raw_fmt, *encoded_fmt;
 355
 356        raw_vpu_fmt = hantro_get_default_fmt(ctx, false);
 357
 358        if (ctx->is_encoder) {
 359                ctx->vpu_src_fmt = raw_vpu_fmt;
 360                raw_fmt = &ctx->src_fmt;
 361                encoded_fmt = &ctx->dst_fmt;
 362        } else {
 363                ctx->vpu_dst_fmt = raw_vpu_fmt;
 364                raw_fmt = &ctx->dst_fmt;
 365                encoded_fmt = &ctx->src_fmt;
 366        }
 367
 368        hantro_reset_fmt(raw_fmt, raw_vpu_fmt);
 369        raw_fmt->width = encoded_fmt->width;
 370        raw_fmt->height = encoded_fmt->height;
 371        if (ctx->is_encoder)
 372                hantro_set_fmt_out(ctx, raw_fmt);
 373        else
 374                hantro_set_fmt_cap(ctx, raw_fmt);
 375}
 376
 377void hantro_reset_fmts(struct hantro_ctx *ctx)
 378{
 379        hantro_reset_encoded_fmt(ctx);
 380        hantro_reset_raw_fmt(ctx);
 381}
 382
 383static void
 384hantro_update_requires_request(struct hantro_ctx *ctx, u32 fourcc)
 385{
 386        switch (fourcc) {
 387        case V4L2_PIX_FMT_JPEG:
 388                ctx->fh.m2m_ctx->out_q_ctx.q.requires_requests = false;
 389                break;
 390        case V4L2_PIX_FMT_MPEG2_SLICE:
 391        case V4L2_PIX_FMT_VP8_FRAME:
 392        case V4L2_PIX_FMT_H264_SLICE:
 393                ctx->fh.m2m_ctx->out_q_ctx.q.requires_requests = true;
 394                break;
 395        default:
 396                break;
 397        }
 398}
 399
 400static int hantro_set_fmt_out(struct hantro_ctx *ctx,
 401                              struct v4l2_pix_format_mplane *pix_mp)
 402{
 403        struct vb2_queue *vq;
 404        int ret;
 405
 406        vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
 407                             V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 408        ret = hantro_try_fmt(ctx, pix_mp, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 409        if (ret)
 410                return ret;
 411
 412        if (!ctx->is_encoder) {
 413                struct vb2_queue *peer_vq;
 414
 415                /*
 416                 * In order to support dynamic resolution change,
 417                 * the decoder admits a resolution change, as long
 418                 * as the pixelformat remains. Can't be done if streaming.
 419                 */
 420                if (vb2_is_streaming(vq) || (vb2_is_busy(vq) &&
 421                    pix_mp->pixelformat != ctx->src_fmt.pixelformat))
 422                        return -EBUSY;
 423                /*
 424                 * Since format change on the OUTPUT queue will reset
 425                 * the CAPTURE queue, we can't allow doing so
 426                 * when the CAPTURE queue has buffers allocated.
 427                 */
 428                peer_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
 429                                          V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 430                if (vb2_is_busy(peer_vq))
 431                        return -EBUSY;
 432        } else {
 433                /*
 434                 * The encoder doesn't admit a format change if
 435                 * there are OUTPUT buffers allocated.
 436                 */
 437                if (vb2_is_busy(vq))
 438                        return -EBUSY;
 439        }
 440
 441        ctx->vpu_src_fmt = hantro_find_format(ctx, pix_mp->pixelformat);
 442        ctx->src_fmt = *pix_mp;
 443
 444        /*
 445         * Current raw format might have become invalid with newly
 446         * selected codec, so reset it to default just to be safe and
 447         * keep internal driver state sane. User is mandated to set
 448         * the raw format again after we return, so we don't need
 449         * anything smarter.
 450         * Note that hantro_reset_raw_fmt() also propagates size
 451         * changes to the raw format.
 452         */
 453        if (!ctx->is_encoder)
 454                hantro_reset_raw_fmt(ctx);
 455
 456        /* Colorimetry information are always propagated. */
 457        ctx->dst_fmt.colorspace = pix_mp->colorspace;
 458        ctx->dst_fmt.ycbcr_enc = pix_mp->ycbcr_enc;
 459        ctx->dst_fmt.xfer_func = pix_mp->xfer_func;
 460        ctx->dst_fmt.quantization = pix_mp->quantization;
 461
 462        hantro_update_requires_request(ctx, pix_mp->pixelformat);
 463
 464        vpu_debug(0, "OUTPUT codec mode: %d\n", ctx->vpu_src_fmt->codec_mode);
 465        vpu_debug(0, "fmt - w: %d, h: %d\n",
 466                  pix_mp->width, pix_mp->height);
 467        return 0;
 468}
 469
 470static int hantro_set_fmt_cap(struct hantro_ctx *ctx,
 471                              struct v4l2_pix_format_mplane *pix_mp)
 472{
 473        struct vb2_queue *vq;
 474        int ret;
 475
 476        /* Change not allowed if queue is busy. */
 477        vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
 478                             V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 479        if (vb2_is_busy(vq))
 480                return -EBUSY;
 481
 482        if (ctx->is_encoder) {
 483                struct vb2_queue *peer_vq;
 484
 485                /*
 486                 * Since format change on the CAPTURE queue will reset
 487                 * the OUTPUT queue, we can't allow doing so
 488                 * when the OUTPUT queue has buffers allocated.
 489                 */
 490                peer_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
 491                                          V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 492                if (vb2_is_busy(peer_vq) &&
 493                    (pix_mp->pixelformat != ctx->dst_fmt.pixelformat ||
 494                     pix_mp->height != ctx->dst_fmt.height ||
 495                     pix_mp->width != ctx->dst_fmt.width))
 496                        return -EBUSY;
 497        }
 498
 499        ret = hantro_try_fmt(ctx, pix_mp, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 500        if (ret)
 501                return ret;
 502
 503        ctx->vpu_dst_fmt = hantro_find_format(ctx, pix_mp->pixelformat);
 504        ctx->dst_fmt = *pix_mp;
 505
 506        /*
 507         * Current raw format might have become invalid with newly
 508         * selected codec, so reset it to default just to be safe and
 509         * keep internal driver state sane. User is mandated to set
 510         * the raw format again after we return, so we don't need
 511         * anything smarter.
 512         * Note that hantro_reset_raw_fmt() also propagates size
 513         * changes to the raw format.
 514         */
 515        if (ctx->is_encoder)
 516                hantro_reset_raw_fmt(ctx);
 517
 518        /* Colorimetry information are always propagated. */
 519        ctx->src_fmt.colorspace = pix_mp->colorspace;
 520        ctx->src_fmt.ycbcr_enc = pix_mp->ycbcr_enc;
 521        ctx->src_fmt.xfer_func = pix_mp->xfer_func;
 522        ctx->src_fmt.quantization = pix_mp->quantization;
 523
 524        vpu_debug(0, "CAPTURE codec mode: %d\n", ctx->vpu_dst_fmt->codec_mode);
 525        vpu_debug(0, "fmt - w: %d, h: %d\n",
 526                  pix_mp->width, pix_mp->height);
 527
 528        hantro_update_requires_request(ctx, pix_mp->pixelformat);
 529
 530        return 0;
 531}
 532
 533static int
 534vidioc_s_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f)
 535{
 536        return hantro_set_fmt_out(fh_to_ctx(priv), &f->fmt.pix_mp);
 537}
 538
 539static int
 540vidioc_s_fmt_cap_mplane(struct file *file, void *priv, struct v4l2_format *f)
 541{
 542        return hantro_set_fmt_cap(fh_to_ctx(priv), &f->fmt.pix_mp);
 543}
 544
 545const struct v4l2_ioctl_ops hantro_ioctl_ops = {
 546        .vidioc_querycap = vidioc_querycap,
 547        .vidioc_enum_framesizes = vidioc_enum_framesizes,
 548
 549        .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_cap_mplane,
 550        .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_out_mplane,
 551        .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_out_mplane,
 552        .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_cap_mplane,
 553        .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_out_mplane,
 554        .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_cap_mplane,
 555        .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
 556        .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
 557
 558        .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
 559        .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
 560        .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
 561        .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
 562        .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
 563        .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
 564        .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
 565
 566        .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
 567        .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 568
 569        .vidioc_streamon = v4l2_m2m_ioctl_streamon,
 570        .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
 571};
 572
 573static int
 574hantro_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
 575                   unsigned int *num_planes, unsigned int sizes[],
 576                   struct device *alloc_devs[])
 577{
 578        struct hantro_ctx *ctx = vb2_get_drv_priv(vq);
 579        struct v4l2_pix_format_mplane *pixfmt;
 580        int i;
 581
 582        switch (vq->type) {
 583        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 584                pixfmt = &ctx->dst_fmt;
 585                break;
 586        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 587                pixfmt = &ctx->src_fmt;
 588                break;
 589        default:
 590                vpu_err("invalid queue type: %d\n", vq->type);
 591                return -EINVAL;
 592        }
 593
 594        if (*num_planes) {
 595                if (*num_planes != pixfmt->num_planes)
 596                        return -EINVAL;
 597                for (i = 0; i < pixfmt->num_planes; ++i)
 598                        if (sizes[i] < pixfmt->plane_fmt[i].sizeimage)
 599                                return -EINVAL;
 600                return 0;
 601        }
 602
 603        *num_planes = pixfmt->num_planes;
 604        for (i = 0; i < pixfmt->num_planes; ++i)
 605                sizes[i] = pixfmt->plane_fmt[i].sizeimage;
 606        return 0;
 607}
 608
 609static int
 610hantro_buf_plane_check(struct vb2_buffer *vb,
 611                       struct v4l2_pix_format_mplane *pixfmt)
 612{
 613        unsigned int sz;
 614        int i;
 615
 616        for (i = 0; i < pixfmt->num_planes; ++i) {
 617                sz = pixfmt->plane_fmt[i].sizeimage;
 618                vpu_debug(4, "plane %d size: %ld, sizeimage: %u\n",
 619                          i, vb2_plane_size(vb, i), sz);
 620                if (vb2_plane_size(vb, i) < sz) {
 621                        vpu_err("plane %d is too small for output\n", i);
 622                        return -EINVAL;
 623                }
 624        }
 625        return 0;
 626}
 627
 628static int hantro_buf_prepare(struct vb2_buffer *vb)
 629{
 630        struct vb2_queue *vq = vb->vb2_queue;
 631        struct hantro_ctx *ctx = vb2_get_drv_priv(vq);
 632        struct v4l2_pix_format_mplane *pix_fmt;
 633        int ret;
 634
 635        if (V4L2_TYPE_IS_OUTPUT(vq->type))
 636                pix_fmt = &ctx->src_fmt;
 637        else
 638                pix_fmt = &ctx->dst_fmt;
 639        ret = hantro_buf_plane_check(vb, pix_fmt);
 640        if (ret)
 641                return ret;
 642        vb2_set_plane_payload(vb, 0, pix_fmt->plane_fmt[0].sizeimage);
 643        return 0;
 644}
 645
 646static void hantro_buf_queue(struct vb2_buffer *vb)
 647{
 648        struct hantro_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 649        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 650
 651        v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
 652}
 653
 654static bool hantro_vq_is_coded(struct vb2_queue *q)
 655{
 656        struct hantro_ctx *ctx = vb2_get_drv_priv(q);
 657
 658        return ctx->is_encoder != V4L2_TYPE_IS_OUTPUT(q->type);
 659}
 660
 661static int hantro_start_streaming(struct vb2_queue *q, unsigned int count)
 662{
 663        struct hantro_ctx *ctx = vb2_get_drv_priv(q);
 664        int ret = 0;
 665
 666        if (V4L2_TYPE_IS_OUTPUT(q->type))
 667                ctx->sequence_out = 0;
 668        else
 669                ctx->sequence_cap = 0;
 670
 671        if (hantro_vq_is_coded(q)) {
 672                enum hantro_codec_mode codec_mode;
 673
 674                if (V4L2_TYPE_IS_OUTPUT(q->type))
 675                        codec_mode = ctx->vpu_src_fmt->codec_mode;
 676                else
 677                        codec_mode = ctx->vpu_dst_fmt->codec_mode;
 678
 679                vpu_debug(4, "Codec mode = %d\n", codec_mode);
 680                ctx->codec_ops = &ctx->dev->variant->codec_ops[codec_mode];
 681                if (ctx->codec_ops->init) {
 682                        ret = ctx->codec_ops->init(ctx);
 683                        if (ret)
 684                                return ret;
 685                }
 686
 687                if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) {
 688                        ret = hantro_postproc_alloc(ctx);
 689                        if (ret)
 690                                goto err_codec_exit;
 691                }
 692        }
 693        return ret;
 694
 695err_codec_exit:
 696        if (ctx->codec_ops->exit)
 697                ctx->codec_ops->exit(ctx);
 698        return ret;
 699}
 700
 701static void
 702hantro_return_bufs(struct vb2_queue *q,
 703                   struct vb2_v4l2_buffer *(*buf_remove)(struct v4l2_m2m_ctx *))
 704{
 705        struct hantro_ctx *ctx = vb2_get_drv_priv(q);
 706
 707        for (;;) {
 708                struct vb2_v4l2_buffer *vbuf;
 709
 710                vbuf = buf_remove(ctx->fh.m2m_ctx);
 711                if (!vbuf)
 712                        break;
 713                v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
 714                                           &ctx->ctrl_handler);
 715                v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
 716        }
 717}
 718
 719static void hantro_stop_streaming(struct vb2_queue *q)
 720{
 721        struct hantro_ctx *ctx = vb2_get_drv_priv(q);
 722
 723        if (hantro_vq_is_coded(q)) {
 724                hantro_postproc_free(ctx);
 725                if (ctx->codec_ops && ctx->codec_ops->exit)
 726                        ctx->codec_ops->exit(ctx);
 727        }
 728
 729        /*
 730         * The mem2mem framework calls v4l2_m2m_cancel_job before
 731         * .stop_streaming, so there isn't any job running and
 732         * it is safe to return all the buffers.
 733         */
 734        if (V4L2_TYPE_IS_OUTPUT(q->type))
 735                hantro_return_bufs(q, v4l2_m2m_src_buf_remove);
 736        else
 737                hantro_return_bufs(q, v4l2_m2m_dst_buf_remove);
 738}
 739
 740static void hantro_buf_request_complete(struct vb2_buffer *vb)
 741{
 742        struct hantro_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 743
 744        v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->ctrl_handler);
 745}
 746
 747static int hantro_buf_out_validate(struct vb2_buffer *vb)
 748{
 749        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 750
 751        vbuf->field = V4L2_FIELD_NONE;
 752        return 0;
 753}
 754
 755const struct vb2_ops hantro_queue_ops = {
 756        .queue_setup = hantro_queue_setup,
 757        .buf_prepare = hantro_buf_prepare,
 758        .buf_queue = hantro_buf_queue,
 759        .buf_out_validate = hantro_buf_out_validate,
 760        .buf_request_complete = hantro_buf_request_complete,
 761        .start_streaming = hantro_start_streaming,
 762        .stop_streaming = hantro_stop_streaming,
 763        .wait_prepare = vb2_ops_wait_prepare,
 764        .wait_finish = vb2_ops_wait_finish,
 765};
 766