File Index
Files and directories
Sign in
FILE

iris_venc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/qcom/iris/iris_venc.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
  4 */
  5
  6#include <media/v4l2-event.h>
  7#include <media/v4l2-mem2mem.h>
  8
  9#include "iris_buffer.h"
 10#include "iris_common.h"
 11#include "iris_ctrls.h"
 12#include "iris_instance.h"
 13#include "iris_power.h"
 14#include "iris_venc.h"
 15#include "iris_vpu_buffer.h"
 16
 17int iris_venc_inst_init(struct iris_inst *inst)
 18{
 19	struct iris_core *core = inst->core;
 20	struct v4l2_format *f;
 21
 22	inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL);
 23	inst->fmt_dst  = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL);
 24	if (!inst->fmt_src || !inst->fmt_dst) {
 25		kfree(inst->fmt_src);
 26		kfree(inst->fmt_dst);
 27		return -ENOMEM;
 28	}
 29
 30	f = inst->fmt_dst;
 31	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 32	f->fmt.pix_mp.width = DEFAULT_WIDTH;
 33	f->fmt.pix_mp.height = DEFAULT_HEIGHT;
 34	f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
 35	inst->codec = f->fmt.pix_mp.pixelformat;
 36	f->fmt.pix_mp.num_planes = 1;
 37	f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
 38	f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
 39	f->fmt.pix_mp.field = V4L2_FIELD_NONE;
 40	f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
 41	f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
 42	f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
 43	f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
 44	inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
 45	inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
 46
 47	f = inst->fmt_src;
 48	f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
 49	f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
 50	f->fmt.pix_mp.width = ALIGN(DEFAULT_WIDTH, 128);
 51	f->fmt.pix_mp.height = ALIGN(DEFAULT_HEIGHT, 32);
 52	f->fmt.pix_mp.num_planes = 1;
 53	f->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(DEFAULT_WIDTH, 128);
 54	f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT);
 55	f->fmt.pix_mp.field = V4L2_FIELD_NONE;
 56	f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
 57	f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
 58	f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
 59	f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
 60	inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT);
 61	inst->buffers[BUF_INPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
 62
 63	inst->crop.left = 0;
 64	inst->crop.top = 0;
 65	inst->crop.width = f->fmt.pix_mp.width;
 66	inst->crop.height = f->fmt.pix_mp.height;
 67
 68	inst->operating_rate = DEFAULT_FPS;
 69	inst->frame_rate = DEFAULT_FPS;
 70
 71	memcpy(&inst->fw_caps[0], &core->inst_fw_caps_enc[0],
 72	       INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap));
 73
 74	return iris_ctrls_init(inst);
 75}
 76
 77void iris_venc_inst_deinit(struct iris_inst *inst)
 78{
 79	kfree(inst->fmt_dst);
 80	kfree(inst->fmt_src);
 81}
 82
 83static const struct iris_fmt iris_venc_formats_cap[] = {
 84	[IRIS_FMT_H264] = {
 85		.pixfmt = V4L2_PIX_FMT_H264,
 86		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
 87	},
 88	[IRIS_FMT_HEVC] = {
 89		.pixfmt = V4L2_PIX_FMT_HEVC,
 90		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
 91	},
 92};
 93
 94static const struct iris_fmt iris_venc_formats_out[] = {
 95	[IRIS_FMT_NV12] = {
 96		.pixfmt = V4L2_PIX_FMT_NV12,
 97		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
 98	},
 99	[IRIS_FMT_QC08C] = {
100		.pixfmt = V4L2_PIX_FMT_QC08C,
101		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
102	},
103};
104
105static const struct iris_fmt *
106find_format(struct iris_inst *inst, u32 pixfmt, u32 type)
107{
108	const struct iris_fmt *fmt = NULL;
109	unsigned int size = 0;
110	unsigned int i;
111	switch (type) {
112	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
113		fmt = iris_venc_formats_out;
114		size = ARRAY_SIZE(iris_venc_formats_out);
115		break;
116	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
117		fmt = iris_venc_formats_cap;
118		size = ARRAY_SIZE(iris_venc_formats_cap);
119		break;
120	default:
121		return NULL;
122	}
123
124	for (i = 0; i < size; i++) {
125		if (fmt[i].pixfmt == pixfmt)
126			break;
127	}
128
129	if (i == size || fmt[i].type != type)
130		return NULL;
131
132	return &fmt[i];
133}
134
135static const struct iris_fmt *
136find_format_by_index(struct iris_inst *inst, u32 index, u32 type)
137{
138	const struct iris_fmt *fmt = NULL;
139	unsigned int size = 0;
140
141	switch (type) {
142	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
143		fmt = iris_venc_formats_out;
144		size = ARRAY_SIZE(iris_venc_formats_out);
145		break;
146	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
147		fmt = iris_venc_formats_cap;
148		size = ARRAY_SIZE(iris_venc_formats_cap);
149		break;
150	default:
151		return NULL;
152	}
153
154	if (index >= size || fmt[index].type != type)
155		return NULL;
156
157	return &fmt[index];
158}
159
160int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f)
161{
162	const struct iris_fmt *fmt;
163
164	switch (f->type) {
165	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
166		fmt = find_format_by_index(inst, f->index, f->type);
167		if (!fmt)
168			return -EINVAL;
169
170		f->pixelformat = fmt->pixfmt;
171		break;
172	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
173		fmt = find_format_by_index(inst, f->index, f->type);
174		if (!fmt)
175			return -EINVAL;
176
177		f->pixelformat = fmt->pixfmt;
178		f->flags = V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL;
179		break;
180	default:
181		return -EINVAL;
182	}
183
184	return 0;
185}
186
187int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f)
188{
189	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
190	const struct iris_fmt *fmt;
191	struct v4l2_format *f_inst;
192
193	memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
194	fmt = find_format(inst, pixmp->pixelformat, f->type);
195	switch (f->type) {
196	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
197		if (!fmt) {
198			f_inst = inst->fmt_src;
199			f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
200			f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height;
201			f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat;
202		}
203		break;
204	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
205		if (!fmt) {
206			f_inst = inst->fmt_dst;
207			f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
208			f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height;
209			f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat;
210		}
211		break;
212	default:
213		return -EINVAL;
214	}
215
216	if (pixmp->field == V4L2_FIELD_ANY)
217		pixmp->field = V4L2_FIELD_NONE;
218
219	pixmp->num_planes = 1;
220
221	return 0;
222}
223
224static int iris_venc_s_fmt_output(struct iris_inst *inst, struct v4l2_format *f)
225{
226	struct v4l2_format *fmt;
227
228	iris_venc_try_fmt(inst, f);
229
230	if (!(find_format(inst, f->fmt.pix_mp.pixelformat, f->type)))
231		return -EINVAL;
232
233	fmt = inst->fmt_dst;
234	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
235	fmt->fmt.pix_mp.num_planes = 1;
236	fmt->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
237	fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
238
239	if (f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_DEFAULT &&
240	    f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_REC709)
241		f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
242	fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace;
243	fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func;
244	fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
245	fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization;
246
247	inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
248	inst->buffers[BUF_OUTPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage;
249	fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
250	inst->codec = f->fmt.pix_mp.pixelformat;
251	memcpy(f, fmt, sizeof(struct v4l2_format));
252
253	return 0;
254}
255
256static int iris_venc_s_fmt_input(struct iris_inst *inst, struct v4l2_format *f)
257{
258	struct v4l2_format *fmt, *output_fmt;
259
260	iris_venc_try_fmt(inst, f);
261
262	if (!(find_format(inst, f->fmt.pix_mp.pixelformat, f->type)))
263		return -EINVAL;
264
265	fmt = inst->fmt_src;
266	fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
267	fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128);
268	fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32);
269	fmt->fmt.pix_mp.num_planes = 1;
270	fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
271	fmt->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(f->fmt.pix_mp.width, 128);
272	fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT);
273
274	fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace;
275	fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func;
276	fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
277	fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization;
278
279	output_fmt = inst->fmt_dst;
280	output_fmt->fmt.pix_mp.width = fmt->fmt.pix_mp.width;
281	output_fmt->fmt.pix_mp.height = fmt->fmt.pix_mp.height;
282	output_fmt->fmt.pix_mp.colorspace = fmt->fmt.pix_mp.colorspace;
283	output_fmt->fmt.pix_mp.xfer_func = fmt->fmt.pix_mp.xfer_func;
284	output_fmt->fmt.pix_mp.ycbcr_enc = fmt->fmt.pix_mp.ycbcr_enc;
285	output_fmt->fmt.pix_mp.quantization = fmt->fmt.pix_mp.quantization;
286
287	inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT);
288	inst->buffers[BUF_INPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage;
289
290	if (f->fmt.pix_mp.width != inst->crop.width ||
291	    f->fmt.pix_mp.height != inst->crop.height) {
292		inst->crop.top = 0;
293		inst->crop.left = 0;
294		inst->crop.width = fmt->fmt.pix_mp.width;
295		inst->crop.height = fmt->fmt.pix_mp.height;
296
297		iris_venc_s_fmt_output(inst, output_fmt);
298	}
299
300	memcpy(f, fmt, sizeof(struct v4l2_format));
301
302	return 0;
303}
304
305int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
306{
307	struct vb2_queue *q;
308
309	q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type);
310
311	if (vb2_is_busy(q))
312		return -EBUSY;
313
314	switch (f->type) {
315	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
316		return iris_venc_s_fmt_input(inst, f);
317	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
318		return iris_venc_s_fmt_output(inst, f);
319	default:
320		return -EINVAL;
321	}
322}
323
324int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat)
325{
326	const struct iris_fmt *fmt = NULL;
327
328	fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
329	if (!fmt) {
330		fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
331		if (!fmt)
332			return -EINVAL;
333	}
334
335	return 0;
336}
337
338int iris_venc_subscribe_event(struct iris_inst *inst,
339			      const struct v4l2_event_subscription *sub)
340{
341	switch (sub->type) {
342	case V4L2_EVENT_EOS:
343		return v4l2_event_subscribe(&inst->fh, sub, 0, NULL);
344	case V4L2_EVENT_CTRL:
345		return v4l2_ctrl_subscribe_event(&inst->fh, sub);
346	default:
347		return -EINVAL;
348	}
349}
350
351int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s)
352{
353	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
354		return -EINVAL;
355
356	switch (s->target) {
357	case V4L2_SEL_TGT_CROP:
358		s->r.left = 0;
359		s->r.top = 0;
360
361		if (s->r.width > inst->fmt_src->fmt.pix_mp.width ||
362		    s->r.height > inst->fmt_src->fmt.pix_mp.height)
363			return -EINVAL;
364
365		inst->crop.left = s->r.left;
366		inst->crop.top = s->r.top;
367		inst->crop.width = s->r.width;
368		inst->crop.height = s->r.height;
369		inst->fmt_dst->fmt.pix_mp.width = inst->crop.width;
370		inst->fmt_dst->fmt.pix_mp.height = inst->crop.height;
371		return iris_venc_s_fmt_output(inst, inst->fmt_dst);
372	default:
373		return -EINVAL;
374	}
375}
376
377int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm)
378{
379	struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
380	struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx);
381	struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx);
382	struct v4l2_fract *timeperframe = NULL;
383	u32 default_rate = DEFAULT_FPS;
384	bool is_frame_rate = false;
385	u32 fps, max_rate;
386
387	int ret = 0;
388
389	if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
390		timeperframe = &s_parm->parm.output.timeperframe;
391		max_rate = caps->max_operating_rate;
392		s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
393	} else {
394		timeperframe = &s_parm->parm.capture.timeperframe;
395		is_frame_rate = true;
396		max_rate = caps->max_frame_rate;
397		s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
398	}
399
400	if (!timeperframe->denominator || !timeperframe->numerator) {
401		if (!timeperframe->numerator)
402			timeperframe->numerator = 1;
403		if (!timeperframe->denominator)
404			timeperframe->denominator = default_rate;
405	}
406
407	fps = timeperframe->denominator / timeperframe->numerator;
408	if (!fps)
409		return -EINVAL;
410
411	if (fps > max_rate) {
412		ret = -ENOMEM;
413		goto reset_rate;
414	}
415
416	if (is_frame_rate)
417		inst->frame_rate = fps;
418	else
419		inst->operating_rate = fps;
420
421	if ((s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && vb2_is_streaming(src_q)) ||
422	    (s_parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && vb2_is_streaming(dst_q))) {
423		ret = iris_check_core_mbpf(inst);
424		if (ret)
425			goto reset_rate;
426		ret = iris_check_core_mbps(inst);
427		if (ret)
428			goto reset_rate;
429	}
430
431	return 0;
432
433reset_rate:
434	if (ret) {
435		if (is_frame_rate)
436			inst->frame_rate = default_rate;
437		else
438			inst->operating_rate = default_rate;
439	}
440
441	return ret;
442}
443
444int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm)
445{
446	struct v4l2_fract *timeperframe = NULL;
447
448	if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
449		timeperframe = &s_parm->parm.output.timeperframe;
450		timeperframe->numerator = 1;
451		timeperframe->denominator = inst->operating_rate;
452		s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
453	} else {
454		timeperframe = &s_parm->parm.capture.timeperframe;
455		timeperframe->numerator = 1;
456		timeperframe->denominator = inst->frame_rate;
457		s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
458	}
459
460	return 0;
461}
462
463int iris_venc_streamon_input(struct iris_inst *inst)
464{
465	int ret;
466
467	ret = iris_set_properties(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
468	if (ret)
469		return ret;
470
471	ret = iris_alloc_and_queue_persist_bufs(inst, BUF_ARP);
472	if (ret)
473		return ret;
474
475	iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
476
477	ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
478	if (ret)
479		return ret;
480
481	ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
482	if (ret)
483		return ret;
484
485	ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
486	if (ret)
487		return ret;
488
489	return iris_process_streamon_input(inst);
490}
491
492int iris_venc_streamon_output(struct iris_inst *inst)
493{
494	int ret;
495
496	ret = iris_set_properties(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
497	if (ret)
498		goto error;
499
500	ret = iris_alloc_and_queue_persist_bufs(inst, BUF_ARP);
501	if (ret)
502		return ret;
503
504	iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
505
506	ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
507	if (ret)
508		goto error;
509
510	ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
511	if (ret)
512		goto error;
513
514	ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
515	if (ret)
516		goto error;
517
518	ret = iris_process_streamon_output(inst);
519	if (ret)
520		goto error;
521
522	return ret;
523
524error:
525	iris_session_streamoff(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
526
527	return ret;
528}
529
530int iris_venc_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf)
531{
532	struct iris_buffer *buf = to_iris_buffer(vbuf);
533	struct vb2_buffer *vb2 = &vbuf->vb2_buf;
534	struct vb2_queue *q;
535	int ret;
536
537	ret = iris_vb2_buffer_to_driver(vb2, buf);
538	if (ret)
539		return ret;
540
541	if (buf->type == BUF_INPUT)
542		iris_set_ts_metadata(inst, vbuf);
543
544	q = v4l2_m2m_get_vq(inst->m2m_ctx, vb2->type);
545	if (!vb2_is_streaming(q)) {
546		buf->attr |= BUF_ATTR_DEFERRED;
547		return 0;
548	}
549
550	iris_scale_power(inst);
551
552	return iris_queue_buffer(inst, buf);
553}
554
555int iris_venc_start_cmd(struct iris_inst *inst)
556{
557	const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
558	enum iris_inst_sub_state clear_sub_state = 0;
559	struct vb2_queue *dst_vq;
560	int ret;
561
562	dst_vq = v4l2_m2m_get_dst_vq(inst->m2m_ctx);
563
564	if (inst->sub_state & IRIS_INST_SUB_DRAIN &&
565	    inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) {
566		vb2_clear_last_buffer_dequeued(dst_vq);
567		clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST;
568		if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
569			if (hfi_ops->session_resume_drain) {
570				ret = hfi_ops->session_resume_drain(inst,
571					V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
572				if (ret)
573					return ret;
574			}
575			clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
576		}
577		if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) {
578			if (hfi_ops->session_resume_drain) {
579				ret = hfi_ops->session_resume_drain(inst,
580					V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
581				if (ret)
582					return ret;
583			}
584			clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
585		}
586	} else {
587		dev_err(inst->core->dev, "start called before receiving last_flag\n");
588		iris_inst_change_state(inst, IRIS_INST_ERROR);
589		return -EBUSY;
590	}
591
592	inst->last_buffer_dequeued = false;
593
594	return iris_inst_change_sub_state(inst, clear_sub_state, 0);
595}
596
597int iris_venc_stop_cmd(struct iris_inst *inst)
598{
599	const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
600	int ret;
601
602	ret = hfi_ops->session_drain(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
603	if (ret)
604		return ret;
605
606	ret = iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_DRAIN);
607
608	iris_scale_power(inst);
609
610	return ret;
611}
~/ Read-only file preview.