File Index
Files and directories
Sign in
FILE

vpu_v4l2.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/amphion/vpu_v4l2.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright 2020-2021 NXP
  4 */
  5
  6#include <linux/init.h>
  7#include <linux/interconnect.h>
  8#include <linux/ioctl.h>
  9#include <linux/list.h>
 10#include <linux/kernel.h>
 11#include <linux/module.h>
 12#include <linux/pm_runtime.h>
 13#include <linux/videodev2.h>
 14#include <media/v4l2-device.h>
 15#include <media/v4l2-event.h>
 16#include <media/v4l2-mem2mem.h>
 17#include <media/v4l2-ioctl.h>
 18#include <media/videobuf2-v4l2.h>
 19#include <media/videobuf2-dma-contig.h>
 20#include <media/videobuf2-vmalloc.h>
 21#include "vpu.h"
 22#include "vpu_core.h"
 23#include "vpu_v4l2.h"
 24#include "vpu_msgs.h"
 25#include "vpu_helpers.h"
 26
 27static char *vpu_type_name(u32 type)
 28{
 29	return V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture";
 30}
 31
 32void vpu_inst_lock(struct vpu_inst *inst)
 33{
 34	mutex_lock(&inst->lock);
 35}
 36
 37void vpu_inst_unlock(struct vpu_inst *inst)
 38{
 39	mutex_unlock(&inst->lock);
 40}
 41
 42dma_addr_t vpu_get_vb_phy_addr(struct vb2_buffer *vb, u32 plane_no)
 43{
 44	if (plane_no >= vb->num_planes)
 45		return 0;
 46	return vb2_dma_contig_plane_dma_addr(vb, plane_no) +
 47			vb->planes[plane_no].data_offset;
 48}
 49
 50static unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no)
 51{
 52	if (plane_no >= vb->num_planes)
 53		return 0;
 54	return vb2_plane_size(vb, plane_no) - vb->planes[plane_no].data_offset;
 55}
 56
 57void vpu_set_buffer_state(struct vb2_v4l2_buffer *vbuf, unsigned int state)
 58{
 59	struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf);
 60
 61	vpu_buf->state = state;
 62}
 63
 64unsigned int vpu_get_buffer_state(struct vb2_v4l2_buffer *vbuf)
 65{
 66	struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf);
 67
 68	return vpu_buf->state;
 69}
 70
 71void vpu_set_buffer_average_qp(struct vb2_v4l2_buffer *vbuf, u32 qp)
 72{
 73	struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf);
 74
 75	vpu_buf->average_qp = qp;
 76}
 77
 78void vpu_v4l2_set_error(struct vpu_inst *inst)
 79{
 80	vpu_inst_lock(inst);
 81	dev_err(inst->dev, "some error occurs in codec\n");
 82	if (inst->fh.m2m_ctx) {
 83		vb2_queue_error(v4l2_m2m_get_src_vq(inst->fh.m2m_ctx));
 84		vb2_queue_error(v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx));
 85	}
 86	vpu_inst_unlock(inst);
 87}
 88
 89static int vpu_notify_eos(struct vpu_inst *inst)
 90{
 91	static const struct v4l2_event ev = {
 92		.id = 0,
 93		.type = V4L2_EVENT_EOS
 94	};
 95
 96	vpu_trace(inst->dev, "[%d]\n", inst->id);
 97	v4l2_event_queue_fh(&inst->fh, &ev);
 98
 99	return 0;
100}
101
102int vpu_notify_source_change(struct vpu_inst *inst)
103{
104	static const struct v4l2_event ev = {
105		.id = 0,
106		.type = V4L2_EVENT_SOURCE_CHANGE,
107		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION
108	};
109
110	vpu_trace(inst->dev, "[%d]\n", inst->id);
111	v4l2_event_queue_fh(&inst->fh, &ev);
112	return 0;
113}
114
115int vpu_set_last_buffer_dequeued(struct vpu_inst *inst, bool eos)
116{
117	struct vb2_queue *q;
118
119	if (!inst || !inst->fh.m2m_ctx)
120		return -EINVAL;
121
122	q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
123	if (!list_empty(&q->done_list))
124		return -EINVAL;
125
126	if (q->last_buffer_dequeued)
127		return 0;
128	vpu_trace(inst->dev, "last buffer dequeued\n");
129	q->last_buffer_dequeued = true;
130	wake_up(&q->done_wq);
131	if (eos)
132		vpu_notify_eos(inst);
133	return 0;
134}
135
136bool vpu_is_source_empty(struct vpu_inst *inst)
137{
138	struct v4l2_m2m_buffer *buf = NULL;
139
140	if (!inst->fh.m2m_ctx)
141		return true;
142	v4l2_m2m_for_each_src_buf(inst->fh.m2m_ctx, buf) {
143		if (vpu_get_buffer_state(&buf->vb) == VPU_BUF_STATE_IDLE)
144			return false;
145	}
146	return true;
147}
148
149static int vpu_init_format(struct vpu_inst *inst, struct vpu_format *fmt)
150{
151	const struct vpu_format *info;
152
153	info = vpu_helper_find_format(inst, fmt->type, fmt->pixfmt);
154	if (!info) {
155		info = vpu_helper_enum_format(inst, fmt->type, 0);
156		if (!info)
157			return -EINVAL;
158	}
159	memcpy(fmt, info, sizeof(*fmt));
160
161	return 0;
162}
163
164static int vpu_calc_fmt_bytesperline(struct v4l2_format *f, struct vpu_format *fmt)
165{
166	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
167	int i;
168
169	if (fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
170		for (i = 0; i < fmt->comp_planes; i++)
171			fmt->bytesperline[i] = 0;
172		return 0;
173	}
174	if (pixmp->num_planes == fmt->comp_planes) {
175		for (i = 0; i < fmt->comp_planes; i++)
176			fmt->bytesperline[i] = pixmp->plane_fmt[i].bytesperline;
177		return 0;
178	}
179	if (pixmp->num_planes > 1)
180		return -EINVAL;
181
182	/*amphion vpu only support nv12 and nv12 tiled,
183	 * so the bytesperline of luma and chroma should be same
184	 */
185	for (i = 0; i < fmt->comp_planes; i++)
186		fmt->bytesperline[i] = pixmp->plane_fmt[0].bytesperline;
187
188	return 0;
189}
190
191static int vpu_calc_fmt_sizeimage(struct vpu_inst *inst, struct vpu_format *fmt)
192{
193	u32 stride = 1;
194	int i;
195
196	if (!(fmt->flags & V4L2_FMT_FLAG_COMPRESSED)) {
197		const struct vpu_core_resources *res = vpu_get_resource(inst);
198
199		if (res)
200			stride = res->stride;
201	}
202
203	for (i = 0; i < fmt->comp_planes; i++) {
204		fmt->sizeimage[i] = vpu_helper_get_plane_size(fmt->pixfmt,
205							      fmt->width,
206							      fmt->height,
207							      i,
208							      stride,
209							      fmt->field != V4L2_FIELD_NONE ? 1 : 0,
210							      &fmt->bytesperline[i]);
211		fmt->sizeimage[i] = max_t(u32, fmt->sizeimage[i], PAGE_SIZE);
212		if (fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
213			fmt->sizeimage[i] = clamp_val(fmt->sizeimage[i], SZ_128K, SZ_8M);
214			fmt->bytesperline[i] = 0;
215		}
216	}
217
218	return 0;
219}
220
221u32 vpu_get_fmt_plane_size(struct vpu_format *fmt, u32 plane_no)
222{
223	u32 size;
224	int i;
225
226	if (plane_no >= fmt->mem_planes)
227		return 0;
228
229	if (fmt->comp_planes == fmt->mem_planes)
230		return fmt->sizeimage[plane_no];
231	if (plane_no < fmt->mem_planes - 1)
232		return fmt->sizeimage[plane_no];
233
234	size = fmt->sizeimage[plane_no];
235	for (i = fmt->mem_planes; i < fmt->comp_planes; i++)
236		size += fmt->sizeimage[i];
237
238	return size;
239}
240
241int vpu_try_fmt_common(struct vpu_inst *inst, struct v4l2_format *f, struct vpu_format *fmt)
242{
243	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
244	int i;
245	int ret;
246
247	fmt->pixfmt = pixmp->pixelformat;
248	fmt->type = f->type;
249	ret = vpu_init_format(inst, fmt);
250	if (ret < 0)
251		return ret;
252
253	fmt->width = pixmp->width;
254	fmt->height = pixmp->height;
255	if (fmt->width)
256		fmt->width = vpu_helper_valid_frame_width(inst, fmt->width);
257	if (fmt->height)
258		fmt->height = vpu_helper_valid_frame_height(inst, fmt->height);
259	fmt->field = pixmp->field == V4L2_FIELD_ANY ? V4L2_FIELD_NONE : pixmp->field;
260	vpu_calc_fmt_bytesperline(f, fmt);
261	vpu_calc_fmt_sizeimage(inst, fmt);
262	if ((fmt->flags & V4L2_FMT_FLAG_COMPRESSED) && pixmp->plane_fmt[0].sizeimage)
263		fmt->sizeimage[0] = clamp_val(pixmp->plane_fmt[0].sizeimage, SZ_128K, SZ_8M);
264
265	pixmp->pixelformat = fmt->pixfmt;
266	pixmp->width = fmt->width;
267	pixmp->height = fmt->height;
268	pixmp->flags = fmt->flags;
269	pixmp->num_planes = fmt->mem_planes;
270	pixmp->field = fmt->field;
271	memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
272	for (i = 0; i < pixmp->num_planes; i++) {
273		pixmp->plane_fmt[i].bytesperline = fmt->bytesperline[i];
274		pixmp->plane_fmt[i].sizeimage = vpu_get_fmt_plane_size(fmt, i);
275		memset(pixmp->plane_fmt[i].reserved, 0, sizeof(pixmp->plane_fmt[i].reserved));
276	}
277
278	return 0;
279}
280
281static bool vpu_check_ready(struct vpu_inst *inst, u32 type)
282{
283	if (!inst)
284		return false;
285	if (inst->state == VPU_CODEC_STATE_DEINIT || inst->id < 0)
286		return false;
287	if (!inst->ops->check_ready)
288		return true;
289	return call_vop(inst, check_ready, type);
290}
291
292int vpu_process_output_buffer(struct vpu_inst *inst)
293{
294	struct v4l2_m2m_buffer *buf = NULL;
295	struct vb2_v4l2_buffer *vbuf = NULL;
296
297	if (!inst || !inst->fh.m2m_ctx)
298		return -EINVAL;
299
300	if (!vpu_check_ready(inst, inst->out_format.type))
301		return -EINVAL;
302
303	v4l2_m2m_for_each_src_buf(inst->fh.m2m_ctx, buf) {
304		vbuf = &buf->vb;
305		if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_IDLE)
306			break;
307		vbuf = NULL;
308	}
309
310	if (!vbuf)
311		return -EINVAL;
312
313	dev_dbg(inst->dev, "[%d]frame id = %d / %d\n",
314		inst->id, vbuf->sequence, inst->sequence);
315	return call_vop(inst, process_output, &vbuf->vb2_buf);
316}
317
318int vpu_process_capture_buffer(struct vpu_inst *inst)
319{
320	struct v4l2_m2m_buffer *buf = NULL;
321	struct vb2_v4l2_buffer *vbuf = NULL;
322
323	if (!inst || !inst->fh.m2m_ctx)
324		return -EINVAL;
325
326	if (!vpu_check_ready(inst, inst->cap_format.type))
327		return -EINVAL;
328
329	v4l2_m2m_for_each_dst_buf(inst->fh.m2m_ctx, buf) {
330		vbuf = &buf->vb;
331		if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_IDLE)
332			break;
333		vbuf = NULL;
334	}
335	if (!vbuf)
336		return -EINVAL;
337
338	return call_vop(inst, process_capture, &vbuf->vb2_buf);
339}
340
341struct vb2_v4l2_buffer *vpu_next_src_buf(struct vpu_inst *inst)
342{
343	struct vb2_v4l2_buffer *src_buf = NULL;
344
345	if (!inst->fh.m2m_ctx)
346		return NULL;
347
348	src_buf = v4l2_m2m_next_src_buf(inst->fh.m2m_ctx);
349	if (!src_buf || vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_IDLE)
350		return NULL;
351
352	return src_buf;
353}
354
355void vpu_skip_frame(struct vpu_inst *inst, int count)
356{
357	struct vb2_v4l2_buffer *src_buf;
358	enum vb2_buffer_state state;
359	int i = 0;
360
361	if (count <= 0 || !inst->fh.m2m_ctx)
362		return;
363
364	while (i < count) {
365		src_buf = v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx);
366		if (!src_buf || vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_IDLE)
367			return;
368		if (vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_DECODED)
369			state = VB2_BUF_STATE_DONE;
370		else
371			state = VB2_BUF_STATE_ERROR;
372		i++;
373		vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE);
374		v4l2_m2m_buf_done(src_buf, state);
375	}
376}
377
378struct vb2_v4l2_buffer *vpu_find_buf_by_sequence(struct vpu_inst *inst, u32 type, u32 sequence)
379{
380	struct v4l2_m2m_buffer *buf = NULL;
381	struct vb2_v4l2_buffer *vbuf = NULL;
382
383	if (!inst || !inst->fh.m2m_ctx)
384		return NULL;
385
386	if (V4L2_TYPE_IS_OUTPUT(type)) {
387		v4l2_m2m_for_each_src_buf(inst->fh.m2m_ctx, buf) {
388			vbuf = &buf->vb;
389			if (vbuf->sequence == sequence)
390				break;
391			vbuf = NULL;
392		}
393	} else {
394		v4l2_m2m_for_each_dst_buf(inst->fh.m2m_ctx, buf) {
395			vbuf = &buf->vb;
396			if (vbuf->sequence == sequence)
397				break;
398			vbuf = NULL;
399		}
400	}
401
402	return vbuf;
403}
404
405struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, u32 type, u32 idx)
406{
407	struct v4l2_m2m_buffer *buf = NULL;
408	struct vb2_v4l2_buffer *vbuf = NULL;
409
410	if (!inst || !inst->fh.m2m_ctx)
411		return NULL;
412
413	if (V4L2_TYPE_IS_OUTPUT(type)) {
414		v4l2_m2m_for_each_src_buf(inst->fh.m2m_ctx, buf) {
415			vbuf = &buf->vb;
416			if (vbuf->vb2_buf.index == idx)
417				break;
418			vbuf = NULL;
419		}
420	} else {
421		v4l2_m2m_for_each_dst_buf(inst->fh.m2m_ctx, buf) {
422			vbuf = &buf->vb;
423			if (vbuf->vb2_buf.index == idx)
424				break;
425			vbuf = NULL;
426		}
427	}
428
429	return vbuf;
430}
431
432int vpu_get_num_buffers(struct vpu_inst *inst, u32 type)
433{
434	struct vb2_queue *q;
435
436	if (!inst || !inst->fh.m2m_ctx)
437		return -EINVAL;
438
439	if (V4L2_TYPE_IS_OUTPUT(type))
440		q = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
441	else
442		q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
443
444	return vb2_get_num_buffers(q);
445}
446
447static void vpu_m2m_device_run(void *priv)
448{
449}
450
451static void vpu_m2m_job_abort(void *priv)
452{
453	struct vpu_inst *inst = priv;
454	struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx;
455
456	v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx);
457}
458
459static const struct v4l2_m2m_ops vpu_m2m_ops = {
460	.device_run = vpu_m2m_device_run,
461	.job_abort = vpu_m2m_job_abort
462};
463
464static int vpu_vb2_queue_setup(struct vb2_queue *vq,
465			       unsigned int *buf_count,
466			       unsigned int *plane_count,
467			       unsigned int psize[],
468			       struct device *allocators[])
469{
470	struct vpu_inst *inst = vb2_get_drv_priv(vq);
471	struct vpu_format *cur_fmt;
472	int i;
473
474	cur_fmt = vpu_get_format(inst, vq->type);
475
476	if (*plane_count) {
477		if (*plane_count != cur_fmt->mem_planes)
478			return -EINVAL;
479		for (i = 0; i < cur_fmt->mem_planes; i++) {
480			if (psize[i] < vpu_get_fmt_plane_size(cur_fmt, i))
481				return -EINVAL;
482		}
483		return 0;
484	}
485
486	if (V4L2_TYPE_IS_OUTPUT(vq->type))
487		*buf_count = max_t(unsigned int, *buf_count, inst->min_buffer_out);
488	else
489		*buf_count = max_t(unsigned int, *buf_count, inst->min_buffer_cap);
490	*plane_count = cur_fmt->mem_planes;
491	for (i = 0; i < cur_fmt->mem_planes; i++)
492		psize[i] = vpu_get_fmt_plane_size(cur_fmt, i);
493
494	if (V4L2_TYPE_IS_OUTPUT(vq->type) && inst->state == VPU_CODEC_STATE_SEEK) {
495		vpu_trace(inst->dev, "reinit when VIDIOC_REQBUFS(OUTPUT, 0)\n");
496		call_void_vop(inst, release);
497	}
498
499	if (V4L2_TYPE_IS_CAPTURE(vq->type))
500		call_void_vop(inst, reset_frame_store);
501
502	return 0;
503}
504
505static int vpu_vb2_buf_init(struct vb2_buffer *vb)
506{
507	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
508	struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf);
509	struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
510
511	vpu_buf->fs_id = -1;
512	vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);
513
514	if (!inst->ops->attach_frame_store || V4L2_TYPE_IS_OUTPUT(vb->type))
515		return 0;
516
517	call_void_vop(inst, attach_frame_store, vb);
518	return 0;
519}
520
521static int vpu_vb2_buf_out_validate(struct vb2_buffer *vb)
522{
523	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
524
525	vbuf->field = V4L2_FIELD_NONE;
526
527	return 0;
528}
529
530static int vpu_vb2_buf_prepare(struct vb2_buffer *vb)
531{
532	struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
533	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
534	struct vpu_format *cur_fmt;
535	u32 i;
536
537	cur_fmt = vpu_get_format(inst, vb->type);
538	for (i = 0; i < cur_fmt->mem_planes; i++) {
539		if (vpu_get_vb_length(vb, i) < vpu_get_fmt_plane_size(cur_fmt, i)) {
540			dev_dbg(inst->dev, "[%d] %s buf[%d] is invalid\n",
541				inst->id, vpu_type_name(vb->type), vb->index);
542			vpu_set_buffer_state(vbuf, VPU_BUF_STATE_ERROR);
543		}
544	}
545
546	return 0;
547}
548
549static void vpu_vb2_buf_finish(struct vb2_buffer *vb)
550{
551	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
552	struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
553	struct vb2_queue *q = vb->vb2_queue;
554
555	if (V4L2_TYPE_IS_CAPTURE(vb->type)) {
556		struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf);
557		struct v4l2_ctrl *ctrl = v4l2_ctrl_find(&inst->ctrl_handler,
558							V4L2_CID_MPEG_VIDEO_AVERAGE_QP);
559
560		if (ctrl)
561			v4l2_ctrl_s_ctrl(ctrl, vpu_buf->average_qp);
562	}
563
564	if (vbuf->flags & V4L2_BUF_FLAG_LAST)
565		vpu_notify_eos(inst);
566
567	if (list_empty(&q->done_list))
568		call_void_vop(inst, on_queue_empty, q->type);
569}
570
571static void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type,
572				   enum vb2_buffer_state state)
573{
574	struct vb2_v4l2_buffer *buf;
575
576	if (V4L2_TYPE_IS_OUTPUT(type)) {
577		while ((buf = v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx))) {
578			vpu_set_buffer_state(buf, VPU_BUF_STATE_IDLE);
579			v4l2_m2m_buf_done(buf, state);
580		}
581	} else {
582		while ((buf = v4l2_m2m_dst_buf_remove(inst->fh.m2m_ctx))) {
583			vpu_set_buffer_state(buf, VPU_BUF_STATE_IDLE);
584			v4l2_m2m_buf_done(buf, state);
585		}
586	}
587}
588
589static int vpu_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
590{
591	struct vpu_inst *inst = vb2_get_drv_priv(q);
592	struct vpu_format *fmt = vpu_get_format(inst, q->type);
593	int ret;
594
595	vpu_inst_unlock(inst);
596	ret = vpu_inst_register(inst);
597	vpu_inst_lock(inst);
598	if (ret) {
599		vpu_vb2_buffers_return(inst, q->type, VB2_BUF_STATE_QUEUED);
600		return ret;
601	}
602
603	vpu_trace(inst->dev, "[%d] %s %c%c%c%c %dx%d %u(%u) %u(%u) %u(%u) %d\n",
604		  inst->id, vpu_type_name(q->type),
605		  fmt->pixfmt,
606		  fmt->pixfmt >> 8,
607		  fmt->pixfmt >> 16,
608		  fmt->pixfmt >> 24,
609		  fmt->width, fmt->height,
610		  fmt->sizeimage[0], fmt->bytesperline[0],
611		  fmt->sizeimage[1], fmt->bytesperline[1],
612		  fmt->sizeimage[2], fmt->bytesperline[2],
613		  vb2_get_num_buffers(q));
614	vb2_clear_last_buffer_dequeued(q);
615	ret = call_vop(inst, start, q->type);
616	if (ret)
617		vpu_vb2_buffers_return(inst, q->type, VB2_BUF_STATE_QUEUED);
618
619	return ret;
620}
621
622static void vpu_vb2_stop_streaming(struct vb2_queue *q)
623{
624	struct vpu_inst *inst = vb2_get_drv_priv(q);
625
626	vpu_trace(inst->dev, "[%d] %s\n", inst->id, vpu_type_name(q->type));
627
628	call_void_vop(inst, stop, q->type);
629	vpu_vb2_buffers_return(inst, q->type, VB2_BUF_STATE_ERROR);
630	if (V4L2_TYPE_IS_OUTPUT(q->type))
631		inst->sequence = 0;
632}
633
634static void vpu_vb2_buf_queue(struct vb2_buffer *vb)
635{
636	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
637	struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
638
639	if (V4L2_TYPE_IS_OUTPUT(vb->type))
640		vbuf->sequence = inst->sequence++;
641
642	v4l2_m2m_buf_queue(inst->fh.m2m_ctx, vbuf);
643	vpu_process_output_buffer(inst);
644	vpu_process_capture_buffer(inst);
645}
646
647static const struct vb2_ops vpu_vb2_ops = {
648	.queue_setup        = vpu_vb2_queue_setup,
649	.buf_init           = vpu_vb2_buf_init,
650	.buf_out_validate   = vpu_vb2_buf_out_validate,
651	.buf_prepare        = vpu_vb2_buf_prepare,
652	.buf_finish         = vpu_vb2_buf_finish,
653	.start_streaming    = vpu_vb2_start_streaming,
654	.stop_streaming     = vpu_vb2_stop_streaming,
655	.buf_queue          = vpu_vb2_buf_queue,
656};
657
658static int vpu_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
659{
660	struct vpu_inst *inst = priv;
661	int ret;
662
663	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
664	inst->out_format.type = src_vq->type;
665	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
666	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
667	src_vq->ops = &vpu_vb2_ops;
668	src_vq->mem_ops = &vb2_dma_contig_memops;
669	if (inst->type == VPU_CORE_TYPE_DEC && inst->use_stream_buffer)
670		src_vq->mem_ops = &vb2_vmalloc_memops;
671	src_vq->drv_priv = inst;
672	src_vq->buf_struct_size = sizeof(struct vpu_vb2_buffer);
673	src_vq->dev = inst->vpu->dev;
674	src_vq->lock = &inst->lock;
675	ret = vb2_queue_init(src_vq);
676	if (ret)
677		return ret;
678
679	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
680	inst->cap_format.type = dst_vq->type;
681	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
682	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
683	dst_vq->ops = &vpu_vb2_ops;
684	dst_vq->mem_ops = &vb2_dma_contig_memops;
685	if (inst->type == VPU_CORE_TYPE_ENC && inst->use_stream_buffer)
686		dst_vq->mem_ops = &vb2_vmalloc_memops;
687	dst_vq->drv_priv = inst;
688	dst_vq->buf_struct_size = sizeof(struct vpu_vb2_buffer);
689	dst_vq->dev = inst->vpu->dev;
690	dst_vq->lock = &inst->lock;
691	ret = vb2_queue_init(dst_vq);
692	if (ret) {
693		vb2_queue_release(src_vq);
694		return ret;
695	}
696
697	return 0;
698}
699
700static int vpu_v4l2_release(struct vpu_inst *inst)
701{
702	vpu_trace(inst->vpu->dev, "%p\n", inst);
703
704	if (inst->workqueue) {
705		cancel_work_sync(&inst->msg_work);
706		destroy_workqueue(inst->workqueue);
707		inst->workqueue = NULL;
708	}
709
710	vpu_release_core(inst->core);
711	put_device(inst->dev);
712
713	v4l2_ctrl_handler_free(&inst->ctrl_handler);
714	mutex_destroy(&inst->lock);
715
716	call_void_vop(inst, cleanup);
717
718	return 0;
719}
720
721int vpu_v4l2_open(struct file *file, struct vpu_inst *inst)
722{
723	struct vpu_dev *vpu = video_drvdata(file);
724	struct vpu_func *func;
725	int ret = 0;
726
727	if (!inst || !inst->ops)
728		return -EINVAL;
729
730	if (inst->type == VPU_CORE_TYPE_ENC)
731		func = &vpu->encoder;
732	else
733		func = &vpu->decoder;
734
735	atomic_set(&inst->ref_count, 0);
736	atomic_long_set(&inst->last_response_cmd, 0);
737	vpu_inst_get(inst);
738	inst->vpu = vpu;
739	inst->core = vpu_request_core(vpu, inst->type);
740	if (inst->core)
741		inst->dev = get_device(inst->core->dev);
742	mutex_init(&inst->lock);
743	INIT_LIST_HEAD(&inst->cmd_q);
744	inst->id = VPU_INST_NULL_ID;
745	inst->release = vpu_v4l2_release;
746	inst->pid = current->pid;
747	inst->tgid = current->tgid;
748	inst->min_buffer_cap = 2;
749	inst->min_buffer_out = 2;
750	v4l2_fh_init(&inst->fh, func->vfd);
751	v4l2_fh_add(&inst->fh, file);
752
753	ret = call_vop(inst, ctrl_init);
754	if (ret)
755		goto error;
756
757	inst->fh.m2m_ctx = v4l2_m2m_ctx_init(func->m2m_dev, inst, vpu_m2m_queue_init);
758	if (IS_ERR(inst->fh.m2m_ctx)) {
759		dev_err(vpu->dev, "v4l2_m2m_ctx_init fail\n");
760		ret = PTR_ERR(inst->fh.m2m_ctx);
761		goto error;
762	}
763
764	inst->fh.ctrl_handler = &inst->ctrl_handler;
765	inst->state = VPU_CODEC_STATE_DEINIT;
766	inst->workqueue = alloc_ordered_workqueue("vpu_inst", WQ_MEM_RECLAIM);
767	if (inst->workqueue) {
768		INIT_WORK(&inst->msg_work, vpu_inst_run_work);
769		ret = kfifo_init(&inst->msg_fifo,
770				 inst->msg_buffer,
771				 rounddown_pow_of_two(sizeof(inst->msg_buffer)));
772		if (ret) {
773			destroy_workqueue(inst->workqueue);
774			inst->workqueue = NULL;
775		}
776	}
777	vpu_trace(vpu->dev, "tgid = %d, pid = %d, type = %s, inst = %p\n",
778		  inst->tgid, inst->pid, vpu_core_type_desc(inst->type), inst);
779
780	return 0;
781error:
782	v4l2_fh_del(&inst->fh, file);
783	v4l2_fh_exit(&inst->fh);
784	vpu_inst_put(inst);
785	return ret;
786}
787
788int vpu_v4l2_close(struct file *file)
789{
790	struct vpu_dev *vpu = video_drvdata(file);
791	struct vpu_inst *inst = to_inst(file);
792
793	vpu_trace(vpu->dev, "tgid = %d, pid = %d, inst = %p\n", inst->tgid, inst->pid, inst);
794
795	vpu_inst_lock(inst);
796	if (inst->fh.m2m_ctx) {
797		v4l2_m2m_ctx_release(inst->fh.m2m_ctx);
798		inst->fh.m2m_ctx = NULL;
799	}
800	call_void_vop(inst, release);
801	vpu_inst_unlock(inst);
802
803	v4l2_fh_del(&inst->fh, file);
804	v4l2_fh_exit(&inst->fh);
805
806	vpu_inst_unregister(inst);
807	vpu_inst_put(inst);
808
809	return 0;
810}
811
812int vpu_add_func(struct vpu_dev *vpu, struct vpu_func *func)
813{
814	struct video_device *vfd;
815	int ret;
816
817	if (!vpu || !func)
818		return -EINVAL;
819
820	if (func->vfd)
821		return 0;
822
823	func->m2m_dev = v4l2_m2m_init(&vpu_m2m_ops);
824	if (IS_ERR(func->m2m_dev)) {
825		dev_err(vpu->dev, "v4l2_m2m_init fail\n");
826		func->vfd = NULL;
827		return PTR_ERR(func->m2m_dev);
828	}
829
830	vfd = video_device_alloc();
831	if (!vfd) {
832		v4l2_m2m_release(func->m2m_dev);
833		dev_err(vpu->dev, "alloc vpu decoder video device fail\n");
834		return -ENOMEM;
835	}
836	vfd->release = video_device_release;
837	vfd->vfl_dir = VFL_DIR_M2M;
838	vfd->v4l2_dev = &vpu->v4l2_dev;
839	vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
840	if (func->type == VPU_CORE_TYPE_ENC) {
841		strscpy(vfd->name, "amphion-vpu-encoder", sizeof(vfd->name));
842		vfd->fops = venc_get_fops();
843		vfd->ioctl_ops = venc_get_ioctl_ops();
844	} else {
845		strscpy(vfd->name, "amphion-vpu-decoder", sizeof(vfd->name));
846		vfd->fops = vdec_get_fops();
847		vfd->ioctl_ops = vdec_get_ioctl_ops();
848	}
849	video_set_drvdata(vfd, vpu);
850
851	ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
852	if (ret) {
853		video_device_release(vfd);
854		v4l2_m2m_release(func->m2m_dev);
855		return ret;
856	}
857	func->vfd = vfd;
858
859	ret = v4l2_m2m_register_media_controller(func->m2m_dev, func->vfd, func->function);
860	if (ret) {
861		v4l2_m2m_release(func->m2m_dev);
862		func->m2m_dev = NULL;
863		video_unregister_device(func->vfd);
864		func->vfd = NULL;
865		return ret;
866	}
867
868	return 0;
869}
870
871void vpu_remove_func(struct vpu_func *func)
872{
873	if (!func)
874		return;
875
876	if (func->m2m_dev) {
877		v4l2_m2m_unregister_media_controller(func->m2m_dev);
878		v4l2_m2m_release(func->m2m_dev);
879		func->m2m_dev = NULL;
880	}
881	if (func->vfd) {
882		video_unregister_device(func->vfd);
883		func->vfd = NULL;
884	}
885}
~/ Read-only file preview.