File Index
Files and directories
Sign in
FILE

cedrus_video.c

File preview with syntax highlighting.

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