linux/drivers/staging/media/sunxi/cedrus/cedrus_video.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Cedrus VPU driver
   4 *
   5 * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
   6 * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
   7 * Copyright (C) 2018 Bootlin
   8 *
   9 * Based on the vim2m driver, that is:
  10 *
  11 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
  12 * Pawel Osciak, <pawel@osciak.com>
  13 * Marek Szyprowski, <m.szyprowski@samsung.com>
  14 */
  15
  16#include <linux/pm_runtime.h>
  17
  18#include <media/videobuf2-dma-contig.h>
  19#include <media/v4l2-device.h>
  20#include <media/v4l2-ioctl.h>
  21#include <media/v4l2-event.h>
  22#include <media/v4l2-mem2mem.h>
  23
  24#include "cedrus.h"
  25#include "cedrus_video.h"
  26#include "cedrus_dec.h"
  27#include "cedrus_hw.h"
  28
  29#define CEDRUS_DECODE_SRC       BIT(0)
  30#define CEDRUS_DECODE_DST       BIT(1)
  31
  32#define CEDRUS_MIN_WIDTH        16U
  33#define CEDRUS_MIN_HEIGHT       16U
  34#define CEDRUS_MAX_WIDTH        4096U
  35#define CEDRUS_MAX_HEIGHT       2304U
  36
  37static struct cedrus_format cedrus_formats[] = {
  38        {
  39                .pixelformat    = V4L2_PIX_FMT_MPEG2_SLICE,
  40                .directions     = CEDRUS_DECODE_SRC,
  41                .capabilities   = CEDRUS_CAPABILITY_MPEG2_DEC,
  42        },
  43        {
  44                .pixelformat    = V4L2_PIX_FMT_H264_SLICE,
  45                .directions     = CEDRUS_DECODE_SRC,
  46                .capabilities   = CEDRUS_CAPABILITY_H264_DEC,
  47        },
  48        {
  49                .pixelformat    = V4L2_PIX_FMT_HEVC_SLICE,
  50                .directions     = CEDRUS_DECODE_SRC,
  51                .capabilities   = CEDRUS_CAPABILITY_H265_DEC,
  52        },
  53        {
  54                .pixelformat    = V4L2_PIX_FMT_VP8_FRAME,
  55                .directions     = CEDRUS_DECODE_SRC,
  56                .capabilities   = CEDRUS_CAPABILITY_VP8_DEC,
  57        },
  58        {
  59                .pixelformat    = V4L2_PIX_FMT_SUNXI_TILED_NV12,
  60                .directions     = CEDRUS_DECODE_DST,
  61        },
  62        {
  63                .pixelformat    = V4L2_PIX_FMT_NV12,
  64                .directions     = CEDRUS_DECODE_DST,
  65                .capabilities   = CEDRUS_CAPABILITY_UNTILED,
  66        },
  67};
  68
  69#define CEDRUS_FORMATS_COUNT    ARRAY_SIZE(cedrus_formats)
  70
  71static inline struct cedrus_ctx *cedrus_file2ctx(struct file *file)
  72{
  73        return container_of(file->private_data, struct cedrus_ctx, fh);
  74}
  75
  76static struct cedrus_format *cedrus_find_format(u32 pixelformat, u32 directions,
  77                                                unsigned int capabilities)
  78{
  79        struct cedrus_format *first_valid_fmt = NULL;
  80        struct cedrus_format *fmt;
  81        unsigned int i;
  82
  83        for (i = 0; i < CEDRUS_FORMATS_COUNT; i++) {
  84                fmt = &cedrus_formats[i];
  85
  86                if ((fmt->capabilities & capabilities) != fmt->capabilities ||
  87                    !(fmt->directions & directions))
  88                        continue;
  89
  90                if (fmt->pixelformat == pixelformat)
  91                        break;
  92
  93                if (!first_valid_fmt)
  94                        first_valid_fmt = fmt;
  95        }
  96
  97        if (i == CEDRUS_FORMATS_COUNT)
  98                return first_valid_fmt;
  99
 100        return &cedrus_formats[i];
 101}
 102
 103void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt)
 104{
 105        unsigned int width = pix_fmt->width;
 106        unsigned int height = pix_fmt->height;
 107        unsigned int sizeimage = pix_fmt->sizeimage;
 108        unsigned int bytesperline = pix_fmt->bytesperline;
 109
 110        pix_fmt->field = V4L2_FIELD_NONE;
 111
 112        /* Limit to hardware min/max. */
 113        width = clamp(width, CEDRUS_MIN_WIDTH, CEDRUS_MAX_WIDTH);
 114        height = clamp(height, CEDRUS_MIN_HEIGHT, CEDRUS_MAX_HEIGHT);
 115
 116        switch (pix_fmt->pixelformat) {
 117        case V4L2_PIX_FMT_MPEG2_SLICE:
 118        case V4L2_PIX_FMT_H264_SLICE:
 119        case V4L2_PIX_FMT_HEVC_SLICE:
 120        case V4L2_PIX_FMT_VP8_FRAME:
 121                /* Zero bytes per line for encoded source. */
 122                bytesperline = 0;
 123                /* Choose some minimum size since this can't be 0 */
 124                sizeimage = max_t(u32, SZ_1K, sizeimage);
 125                break;
 126
 127        case V4L2_PIX_FMT_SUNXI_TILED_NV12:
 128                /* 32-aligned stride. */
 129                bytesperline = ALIGN(width, 32);
 130
 131                /* 32-aligned height. */
 132                height = ALIGN(height, 32);
 133
 134                /* Luma plane size. */
 135                sizeimage = bytesperline * height;
 136
 137                /* Chroma plane size. */
 138                sizeimage += bytesperline * ALIGN(height, 64) / 2;
 139
 140                break;
 141
 142        case V4L2_PIX_FMT_NV12:
 143                /* 16-aligned stride. */
 144                bytesperline = ALIGN(width, 16);
 145
 146                /* 16-aligned height. */
 147                height = ALIGN(height, 16);
 148
 149                /* Luma plane size. */
 150                sizeimage = bytesperline * height;
 151
 152                /* Chroma plane size. */
 153                sizeimage += bytesperline * height / 2;
 154
 155                break;
 156        }
 157
 158        pix_fmt->width = width;
 159        pix_fmt->height = height;
 160
 161        pix_fmt->bytesperline = bytesperline;
 162        pix_fmt->sizeimage = sizeimage;
 163}
 164
 165static int cedrus_querycap(struct file *file, void *priv,
 166                           struct v4l2_capability *cap)
 167{
 168        strscpy(cap->driver, CEDRUS_NAME, sizeof(cap->driver));
 169        strscpy(cap->card, CEDRUS_NAME, sizeof(cap->card));
 170        snprintf(cap->bus_info, sizeof(cap->bus_info),
 171                 "platform:%s", CEDRUS_NAME);
 172
 173        return 0;
 174}
 175
 176static int cedrus_enum_fmt(struct file *file, struct v4l2_fmtdesc *f,
 177                           u32 direction)
 178{
 179        struct cedrus_ctx *ctx = cedrus_file2ctx(file);
 180        struct cedrus_dev *dev = ctx->dev;
 181        unsigned int capabilities = dev->capabilities;
 182        struct cedrus_format *fmt;
 183        unsigned int i, index;
 184
 185        /* Index among formats that match the requested direction. */
 186        index = 0;
 187
 188        for (i = 0; i < CEDRUS_FORMATS_COUNT; i++) {
 189                fmt = &cedrus_formats[i];
 190
 191                if (fmt->capabilities && (fmt->capabilities & capabilities) !=
 192                    fmt->capabilities)
 193                        continue;
 194
 195                if (!(cedrus_formats[i].directions & direction))
 196                        continue;
 197
 198                if (index == f->index)
 199                        break;
 200
 201                index++;
 202        }
 203
 204        /* Matched format. */
 205        if (i < CEDRUS_FORMATS_COUNT) {
 206                f->pixelformat = cedrus_formats[i].pixelformat;
 207
 208                return 0;
 209        }
 210
 211        return -EINVAL;
 212}
 213
 214static int cedrus_enum_fmt_vid_cap(struct file *file, void *priv,
 215                                   struct v4l2_fmtdesc *f)
 216{
 217        return cedrus_enum_fmt(file, f, CEDRUS_DECODE_DST);
 218}
 219
 220static int cedrus_enum_fmt_vid_out(struct file *file, void *priv,
 221                                   struct v4l2_fmtdesc *f)
 222{
 223        return cedrus_enum_fmt(file, f, CEDRUS_DECODE_SRC);
 224}
 225
 226static int cedrus_g_fmt_vid_cap(struct file *file, void *priv,
 227                                struct v4l2_format *f)
 228{
 229        struct cedrus_ctx *ctx = cedrus_file2ctx(file);
 230
 231        f->fmt.pix = ctx->dst_fmt;
 232        return 0;
 233}
 234
 235static int cedrus_g_fmt_vid_out(struct file *file, void *priv,
 236                                struct v4l2_format *f)
 237{
 238        struct cedrus_ctx *ctx = cedrus_file2ctx(file);
 239
 240        f->fmt.pix = ctx->src_fmt;
 241        return 0;
 242}
 243
 244static int cedrus_try_fmt_vid_cap(struct file *file, void *priv,
 245                                  struct v4l2_format *f)
 246{
 247        struct cedrus_ctx *ctx = cedrus_file2ctx(file);
 248        struct cedrus_dev *dev = ctx->dev;
 249        struct v4l2_pix_format *pix_fmt = &f->fmt.pix;
 250        struct cedrus_format *fmt =
 251                cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_DST,
 252                                   dev->capabilities);
 253
 254        if (!fmt)
 255                return -EINVAL;
 256
 257        pix_fmt->pixelformat = fmt->pixelformat;
 258        pix_fmt->width = ctx->src_fmt.width;
 259        pix_fmt->height = ctx->src_fmt.height;
 260        cedrus_prepare_format(pix_fmt);
 261
 262        return 0;
 263}
 264
 265static int cedrus_try_fmt_vid_out(struct file *file, void *priv,
 266                                  struct v4l2_format *f)
 267{
 268        struct cedrus_ctx *ctx = cedrus_file2ctx(file);
 269        struct cedrus_dev *dev = ctx->dev;
 270        struct v4l2_pix_format *pix_fmt = &f->fmt.pix;
 271        struct cedrus_format *fmt =
 272                cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_SRC,
 273                                   dev->capabilities);
 274
 275        if (!fmt)
 276                return -EINVAL;
 277
 278        pix_fmt->pixelformat = fmt->pixelformat;
 279        cedrus_prepare_format(pix_fmt);
 280
 281        return 0;
 282}
 283
 284static int cedrus_s_fmt_vid_cap(struct file *file, void *priv,
 285                                struct v4l2_format *f)
 286{
 287        struct cedrus_ctx *ctx = cedrus_file2ctx(file);
 288        struct vb2_queue *vq;
 289        int ret;
 290
 291        vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 292        if (vb2_is_busy(vq))
 293                return -EBUSY;
 294
 295        ret = cedrus_try_fmt_vid_cap(file, priv, f);
 296        if (ret)
 297                return ret;
 298
 299        ctx->dst_fmt = f->fmt.pix;
 300
 301        return 0;
 302}
 303
 304static int cedrus_s_fmt_vid_out(struct file *file, void *priv,
 305                                struct v4l2_format *f)
 306{
 307        struct cedrus_ctx *ctx = cedrus_file2ctx(file);
 308        struct vb2_queue *vq;
 309        struct vb2_queue *peer_vq;
 310        int ret;
 311
 312        ret = cedrus_try_fmt_vid_out(file, priv, f);
 313        if (ret)
 314                return ret;
 315
 316        vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 317        /*
 318         * In order to support dynamic resolution change,
 319         * the decoder admits a resolution change, as long
 320         * as the pixelformat remains. Can't be done if streaming.
 321         */
 322        if (vb2_is_streaming(vq) || (vb2_is_busy(vq) &&
 323            f->fmt.pix.pixelformat != ctx->src_fmt.pixelformat))
 324                return -EBUSY;
 325        /*
 326         * Since format change on the OUTPUT queue will reset
 327         * the CAPTURE queue, we can't allow doing so
 328         * when the CAPTURE queue has buffers allocated.
 329         */
 330        peer_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
 331                                  V4L2_BUF_TYPE_VIDEO_CAPTURE);
 332        if (vb2_is_busy(peer_vq))
 333                return -EBUSY;
 334
 335        ret = cedrus_try_fmt_vid_out(file, priv, f);
 336        if (ret)
 337                return ret;
 338
 339        ctx->src_fmt = f->fmt.pix;
 340
 341        switch (ctx->src_fmt.pixelformat) {
 342        case V4L2_PIX_FMT_H264_SLICE:
 343        case V4L2_PIX_FMT_HEVC_SLICE:
 344                vq->subsystem_flags |=
 345                        VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
 346                break;
 347        default:
 348                vq->subsystem_flags &=
 349                        ~VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
 350                break;
 351        }
 352
 353        /* Propagate format information to capture. */
 354        ctx->dst_fmt.colorspace = f->fmt.pix.colorspace;
 355        ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func;
 356        ctx->dst_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc;
 357        ctx->dst_fmt.quantization = f->fmt.pix.quantization;
 358        ctx->dst_fmt.width = ctx->src_fmt.width;
 359        ctx->dst_fmt.height = ctx->src_fmt.height;
 360        cedrus_prepare_format(&ctx->dst_fmt);
 361
 362        return 0;
 363}
 364
 365const struct v4l2_ioctl_ops cedrus_ioctl_ops = {
 366        .vidioc_querycap                = cedrus_querycap,
 367
 368        .vidioc_enum_fmt_vid_cap        = cedrus_enum_fmt_vid_cap,
 369        .vidioc_g_fmt_vid_cap           = cedrus_g_fmt_vid_cap,
 370        .vidioc_try_fmt_vid_cap         = cedrus_try_fmt_vid_cap,
 371        .vidioc_s_fmt_vid_cap           = cedrus_s_fmt_vid_cap,
 372
 373        .vidioc_enum_fmt_vid_out        = cedrus_enum_fmt_vid_out,
 374        .vidioc_g_fmt_vid_out           = cedrus_g_fmt_vid_out,
 375        .vidioc_try_fmt_vid_out         = cedrus_try_fmt_vid_out,
 376        .vidioc_s_fmt_vid_out           = cedrus_s_fmt_vid_out,
 377
 378        .vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
 379        .vidioc_querybuf                = v4l2_m2m_ioctl_querybuf,
 380        .vidioc_qbuf                    = v4l2_m2m_ioctl_qbuf,
 381        .vidioc_dqbuf                   = v4l2_m2m_ioctl_dqbuf,
 382        .vidioc_prepare_buf             = v4l2_m2m_ioctl_prepare_buf,
 383        .vidioc_create_bufs             = v4l2_m2m_ioctl_create_bufs,
 384        .vidioc_expbuf                  = v4l2_m2m_ioctl_expbuf,
 385
 386        .vidioc_streamon                = v4l2_m2m_ioctl_streamon,
 387        .vidioc_streamoff               = v4l2_m2m_ioctl_streamoff,
 388
 389        .vidioc_try_decoder_cmd         = v4l2_m2m_ioctl_stateless_try_decoder_cmd,
 390        .vidioc_decoder_cmd             = v4l2_m2m_ioctl_stateless_decoder_cmd,
 391
 392        .vidioc_subscribe_event         = v4l2_ctrl_subscribe_event,
 393        .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
 394};
 395
 396static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
 397                              unsigned int *nplanes, unsigned int sizes[],
 398                              struct device *alloc_devs[])
 399{
 400        struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
 401        struct v4l2_pix_format *pix_fmt;
 402
 403        if (V4L2_TYPE_IS_OUTPUT(vq->type))
 404                pix_fmt = &ctx->src_fmt;
 405        else
 406                pix_fmt = &ctx->dst_fmt;
 407
 408        if (*nplanes) {
 409                if (sizes[0] < pix_fmt->sizeimage)
 410                        return -EINVAL;
 411        } else {
 412                sizes[0] = pix_fmt->sizeimage;
 413                *nplanes = 1;
 414        }
 415
 416        return 0;
 417}
 418
 419static void cedrus_queue_cleanup(struct vb2_queue *vq, u32 state)
 420{
 421        struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
 422        struct vb2_v4l2_buffer *vbuf;
 423
 424        for (;;) {
 425                if (V4L2_TYPE_IS_OUTPUT(vq->type))
 426                        vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 427                else
 428                        vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 429
 430                if (!vbuf)
 431                        return;
 432
 433                v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
 434                                           &ctx->hdl);
 435                v4l2_m2m_buf_done(vbuf, state);
 436        }
 437}
 438
 439static int cedrus_buf_out_validate(struct vb2_buffer *vb)
 440{
 441        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 442
 443        vbuf->field = V4L2_FIELD_NONE;
 444        return 0;
 445}
 446
 447static int cedrus_buf_prepare(struct vb2_buffer *vb)
 448{
 449        struct vb2_queue *vq = vb->vb2_queue;
 450        struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
 451        struct v4l2_pix_format *pix_fmt;
 452
 453        if (V4L2_TYPE_IS_OUTPUT(vq->type))
 454                pix_fmt = &ctx->src_fmt;
 455        else
 456                pix_fmt = &ctx->dst_fmt;
 457
 458        if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage)
 459                return -EINVAL;
 460
 461        /*
 462         * Buffer's bytesused must be written by driver for CAPTURE buffers.
 463         * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets
 464         * it to buffer length).
 465         */
 466        if (V4L2_TYPE_IS_CAPTURE(vq->type))
 467                vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage);
 468
 469        return 0;
 470}
 471
 472static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count)
 473{
 474        struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
 475        struct cedrus_dev *dev = ctx->dev;
 476        int ret = 0;
 477
 478        switch (ctx->src_fmt.pixelformat) {
 479        case V4L2_PIX_FMT_MPEG2_SLICE:
 480                ctx->current_codec = CEDRUS_CODEC_MPEG2;
 481                break;
 482
 483        case V4L2_PIX_FMT_H264_SLICE:
 484                ctx->current_codec = CEDRUS_CODEC_H264;
 485                break;
 486
 487        case V4L2_PIX_FMT_HEVC_SLICE:
 488                ctx->current_codec = CEDRUS_CODEC_H265;
 489                break;
 490
 491        case V4L2_PIX_FMT_VP8_FRAME:
 492                ctx->current_codec = CEDRUS_CODEC_VP8;
 493                break;
 494
 495        default:
 496                return -EINVAL;
 497        }
 498
 499        if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
 500                ret = pm_runtime_resume_and_get(dev->dev);
 501                if (ret < 0)
 502                        goto err_cleanup;
 503
 504                if (dev->dec_ops[ctx->current_codec]->start) {
 505                        ret = dev->dec_ops[ctx->current_codec]->start(ctx);
 506                        if (ret)
 507                                goto err_pm;
 508                }
 509        }
 510
 511        return 0;
 512
 513err_pm:
 514        pm_runtime_put(dev->dev);
 515err_cleanup:
 516        cedrus_queue_cleanup(vq, VB2_BUF_STATE_QUEUED);
 517
 518        return ret;
 519}
 520
 521static void cedrus_stop_streaming(struct vb2_queue *vq)
 522{
 523        struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
 524        struct cedrus_dev *dev = ctx->dev;
 525
 526        if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
 527                if (dev->dec_ops[ctx->current_codec]->stop)
 528                        dev->dec_ops[ctx->current_codec]->stop(ctx);
 529
 530                pm_runtime_put(dev->dev);
 531        }
 532
 533        cedrus_queue_cleanup(vq, VB2_BUF_STATE_ERROR);
 534}
 535
 536static void cedrus_buf_queue(struct vb2_buffer *vb)
 537{
 538        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 539        struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 540
 541        v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
 542}
 543
 544static void cedrus_buf_request_complete(struct vb2_buffer *vb)
 545{
 546        struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 547
 548        v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
 549}
 550
 551static struct vb2_ops cedrus_qops = {
 552        .queue_setup            = cedrus_queue_setup,
 553        .buf_prepare            = cedrus_buf_prepare,
 554        .buf_queue              = cedrus_buf_queue,
 555        .buf_out_validate       = cedrus_buf_out_validate,
 556        .buf_request_complete   = cedrus_buf_request_complete,
 557        .start_streaming        = cedrus_start_streaming,
 558        .stop_streaming         = cedrus_stop_streaming,
 559        .wait_prepare           = vb2_ops_wait_prepare,
 560        .wait_finish            = vb2_ops_wait_finish,
 561};
 562
 563int cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
 564                      struct vb2_queue *dst_vq)
 565{
 566        struct cedrus_ctx *ctx = priv;
 567        int ret;
 568
 569        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 570        src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 571        src_vq->drv_priv = ctx;
 572        src_vq->buf_struct_size = sizeof(struct cedrus_buffer);
 573        src_vq->min_buffers_needed = 1;
 574        src_vq->ops = &cedrus_qops;
 575        src_vq->mem_ops = &vb2_dma_contig_memops;
 576        src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 577        src_vq->lock = &ctx->dev->dev_mutex;
 578        src_vq->dev = ctx->dev->dev;
 579        src_vq->supports_requests = true;
 580        src_vq->requires_requests = true;
 581
 582        ret = vb2_queue_init(src_vq);
 583        if (ret)
 584                return ret;
 585
 586        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 587        dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 588        dst_vq->drv_priv = ctx;
 589        dst_vq->buf_struct_size = sizeof(struct cedrus_buffer);
 590        dst_vq->min_buffers_needed = 1;
 591        dst_vq->ops = &cedrus_qops;
 592        dst_vq->mem_ops = &vb2_dma_contig_memops;
 593        dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 594        dst_vq->lock = &ctx->dev->dev_mutex;
 595        dst_vq->dev = ctx->dev->dev;
 596
 597        return vb2_queue_init(dst_vq);
 598}
 599