xref: /linux/drivers/media/platform/qcom/venus/helpers.c (revision 7371093f983d35d60a7fac3a6f082de7fefe3648)
197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2af2c3834SStanimir Varbanov /*
3af2c3834SStanimir Varbanov  * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
4af2c3834SStanimir Varbanov  * Copyright (C) 2017 Linaro Ltd.
5af2c3834SStanimir Varbanov  */
6af2c3834SStanimir Varbanov #include <linux/list.h>
7af2c3834SStanimir Varbanov #include <linux/mutex.h>
8af2c3834SStanimir Varbanov #include <linux/slab.h>
92c2dc2fdSStanimir Varbanov #include <linux/kernel.h>
10cc82fd69SAlexandre Courbot #include <media/videobuf2-dma-contig.h>
11af2c3834SStanimir Varbanov #include <media/v4l2-mem2mem.h>
12af2c3834SStanimir Varbanov #include <asm/div64.h>
13af2c3834SStanimir Varbanov 
14af2c3834SStanimir Varbanov #include "core.h"
15af2c3834SStanimir Varbanov #include "helpers.h"
16af2c3834SStanimir Varbanov #include "hfi_helper.h"
177482a983SStanimir Varbanov #include "pm_helpers.h"
18aa603389SStanimir Varbanov #include "hfi_platform.h"
19*7371093fSStanimir Varbanov #include "hfi_parser.h"
20af2c3834SStanimir Varbanov 
21af2c3834SStanimir Varbanov struct intbuf {
22af2c3834SStanimir Varbanov 	struct list_head list;
23af2c3834SStanimir Varbanov 	u32 type;
24af2c3834SStanimir Varbanov 	size_t size;
25af2c3834SStanimir Varbanov 	void *va;
26af2c3834SStanimir Varbanov 	dma_addr_t da;
27af2c3834SStanimir Varbanov 	unsigned long attrs;
28af2c3834SStanimir Varbanov };
29af2c3834SStanimir Varbanov 
30d8db57c2SStanimir Varbanov bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt)
31d8db57c2SStanimir Varbanov {
32d8db57c2SStanimir Varbanov 	struct venus_core *core = inst->core;
33d8db57c2SStanimir Varbanov 	u32 session_type = inst->session_type;
34d8db57c2SStanimir Varbanov 	u32 codec;
35d8db57c2SStanimir Varbanov 
36d8db57c2SStanimir Varbanov 	switch (v4l2_pixfmt) {
37d8db57c2SStanimir Varbanov 	case V4L2_PIX_FMT_H264:
38d8db57c2SStanimir Varbanov 		codec = HFI_VIDEO_CODEC_H264;
39d8db57c2SStanimir Varbanov 		break;
40d8db57c2SStanimir Varbanov 	case V4L2_PIX_FMT_H263:
41d8db57c2SStanimir Varbanov 		codec = HFI_VIDEO_CODEC_H263;
42d8db57c2SStanimir Varbanov 		break;
43d8db57c2SStanimir Varbanov 	case V4L2_PIX_FMT_MPEG1:
44d8db57c2SStanimir Varbanov 		codec = HFI_VIDEO_CODEC_MPEG1;
45d8db57c2SStanimir Varbanov 		break;
46d8db57c2SStanimir Varbanov 	case V4L2_PIX_FMT_MPEG2:
47d8db57c2SStanimir Varbanov 		codec = HFI_VIDEO_CODEC_MPEG2;
48d8db57c2SStanimir Varbanov 		break;
49d8db57c2SStanimir Varbanov 	case V4L2_PIX_FMT_MPEG4:
50d8db57c2SStanimir Varbanov 		codec = HFI_VIDEO_CODEC_MPEG4;
51d8db57c2SStanimir Varbanov 		break;
52d8db57c2SStanimir Varbanov 	case V4L2_PIX_FMT_VC1_ANNEX_G:
53d8db57c2SStanimir Varbanov 	case V4L2_PIX_FMT_VC1_ANNEX_L:
54d8db57c2SStanimir Varbanov 		codec = HFI_VIDEO_CODEC_VC1;
55d8db57c2SStanimir Varbanov 		break;
56d8db57c2SStanimir Varbanov 	case V4L2_PIX_FMT_VP8:
57d8db57c2SStanimir Varbanov 		codec = HFI_VIDEO_CODEC_VP8;
58d8db57c2SStanimir Varbanov 		break;
59d8db57c2SStanimir Varbanov 	case V4L2_PIX_FMT_VP9:
60d8db57c2SStanimir Varbanov 		codec = HFI_VIDEO_CODEC_VP9;
61d8db57c2SStanimir Varbanov 		break;
62d8db57c2SStanimir Varbanov 	case V4L2_PIX_FMT_XVID:
63d8db57c2SStanimir Varbanov 		codec = HFI_VIDEO_CODEC_DIVX;
64d8db57c2SStanimir Varbanov 		break;
651fb9a605SStanimir Varbanov 	case V4L2_PIX_FMT_HEVC:
661fb9a605SStanimir Varbanov 		codec = HFI_VIDEO_CODEC_HEVC;
671fb9a605SStanimir Varbanov 		break;
68d8db57c2SStanimir Varbanov 	default:
69d8db57c2SStanimir Varbanov 		return false;
70d8db57c2SStanimir Varbanov 	}
71d8db57c2SStanimir Varbanov 
72d8db57c2SStanimir Varbanov 	if (session_type == VIDC_SESSION_TYPE_ENC && core->enc_codecs & codec)
73d8db57c2SStanimir Varbanov 		return true;
74d8db57c2SStanimir Varbanov 
75d8db57c2SStanimir Varbanov 	if (session_type == VIDC_SESSION_TYPE_DEC && core->dec_codecs & codec)
76d8db57c2SStanimir Varbanov 		return true;
77d8db57c2SStanimir Varbanov 
78d8db57c2SStanimir Varbanov 	return false;
79d8db57c2SStanimir Varbanov }
80d8db57c2SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_check_codec);
81d8db57c2SStanimir Varbanov 
821e485ee5SStanimir Varbanov int venus_helper_queue_dpb_bufs(struct venus_inst *inst)
83f012b23dSStanimir Varbanov {
84f012b23dSStanimir Varbanov 	struct intbuf *buf;
85f012b23dSStanimir Varbanov 	int ret = 0;
86f012b23dSStanimir Varbanov 
87f012b23dSStanimir Varbanov 	list_for_each_entry(buf, &inst->dpbbufs, list) {
88f012b23dSStanimir Varbanov 		struct hfi_frame_data fdata;
89f012b23dSStanimir Varbanov 
90f012b23dSStanimir Varbanov 		memset(&fdata, 0, sizeof(fdata));
91f012b23dSStanimir Varbanov 		fdata.alloc_len = buf->size;
92f012b23dSStanimir Varbanov 		fdata.device_addr = buf->da;
93f012b23dSStanimir Varbanov 		fdata.buffer_type = buf->type;
94f012b23dSStanimir Varbanov 
95f012b23dSStanimir Varbanov 		ret = hfi_session_process_buf(inst, &fdata);
96f012b23dSStanimir Varbanov 		if (ret)
97f012b23dSStanimir Varbanov 			goto fail;
98f012b23dSStanimir Varbanov 	}
99f012b23dSStanimir Varbanov 
100f012b23dSStanimir Varbanov fail:
101f012b23dSStanimir Varbanov 	return ret;
102f012b23dSStanimir Varbanov }
1031e485ee5SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_queue_dpb_bufs);
104f012b23dSStanimir Varbanov 
105f012b23dSStanimir Varbanov int venus_helper_free_dpb_bufs(struct venus_inst *inst)
106f012b23dSStanimir Varbanov {
107f012b23dSStanimir Varbanov 	struct intbuf *buf, *n;
108f012b23dSStanimir Varbanov 
109f012b23dSStanimir Varbanov 	list_for_each_entry_safe(buf, n, &inst->dpbbufs, list) {
110f012b23dSStanimir Varbanov 		list_del_init(&buf->list);
111f012b23dSStanimir Varbanov 		dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,
112f012b23dSStanimir Varbanov 			       buf->attrs);
113f012b23dSStanimir Varbanov 		kfree(buf);
114f012b23dSStanimir Varbanov 	}
115f012b23dSStanimir Varbanov 
116f012b23dSStanimir Varbanov 	INIT_LIST_HEAD(&inst->dpbbufs);
117f012b23dSStanimir Varbanov 
118f012b23dSStanimir Varbanov 	return 0;
119f012b23dSStanimir Varbanov }
120f012b23dSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_free_dpb_bufs);
121f012b23dSStanimir Varbanov 
122f012b23dSStanimir Varbanov int venus_helper_alloc_dpb_bufs(struct venus_inst *inst)
123f012b23dSStanimir Varbanov {
124f012b23dSStanimir Varbanov 	struct venus_core *core = inst->core;
125f012b23dSStanimir Varbanov 	struct device *dev = core->dev;
126f012b23dSStanimir Varbanov 	enum hfi_version ver = core->res->hfi_version;
127f012b23dSStanimir Varbanov 	struct hfi_buffer_requirements bufreq;
128f012b23dSStanimir Varbanov 	u32 buftype = inst->dpb_buftype;
129f012b23dSStanimir Varbanov 	unsigned int dpb_size = 0;
130f012b23dSStanimir Varbanov 	struct intbuf *buf;
131f012b23dSStanimir Varbanov 	unsigned int i;
132f012b23dSStanimir Varbanov 	u32 count;
133f012b23dSStanimir Varbanov 	int ret;
134f012b23dSStanimir Varbanov 
135f012b23dSStanimir Varbanov 	/* no need to allocate dpb buffers */
136f012b23dSStanimir Varbanov 	if (!inst->dpb_fmt)
137f012b23dSStanimir Varbanov 		return 0;
138f012b23dSStanimir Varbanov 
139f012b23dSStanimir Varbanov 	if (inst->dpb_buftype == HFI_BUFFER_OUTPUT)
140f012b23dSStanimir Varbanov 		dpb_size = inst->output_buf_size;
141f012b23dSStanimir Varbanov 	else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2)
142f012b23dSStanimir Varbanov 		dpb_size = inst->output2_buf_size;
143f012b23dSStanimir Varbanov 
144f012b23dSStanimir Varbanov 	if (!dpb_size)
145f012b23dSStanimir Varbanov 		return 0;
146f012b23dSStanimir Varbanov 
147f012b23dSStanimir Varbanov 	ret = venus_helper_get_bufreq(inst, buftype, &bufreq);
148f012b23dSStanimir Varbanov 	if (ret)
149f012b23dSStanimir Varbanov 		return ret;
150f012b23dSStanimir Varbanov 
151f012b23dSStanimir Varbanov 	count = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
152f012b23dSStanimir Varbanov 
153f012b23dSStanimir Varbanov 	for (i = 0; i < count; i++) {
154f012b23dSStanimir Varbanov 		buf = kzalloc(sizeof(*buf), GFP_KERNEL);
155f012b23dSStanimir Varbanov 		if (!buf) {
156f012b23dSStanimir Varbanov 			ret = -ENOMEM;
157f012b23dSStanimir Varbanov 			goto fail;
158f012b23dSStanimir Varbanov 		}
159f012b23dSStanimir Varbanov 
160f012b23dSStanimir Varbanov 		buf->type = buftype;
161f012b23dSStanimir Varbanov 		buf->size = dpb_size;
162f012b23dSStanimir Varbanov 		buf->attrs = DMA_ATTR_WRITE_COMBINE |
163f012b23dSStanimir Varbanov 			     DMA_ATTR_NO_KERNEL_MAPPING;
164f012b23dSStanimir Varbanov 		buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL,
165f012b23dSStanimir Varbanov 					  buf->attrs);
166f012b23dSStanimir Varbanov 		if (!buf->va) {
167f012b23dSStanimir Varbanov 			kfree(buf);
168f012b23dSStanimir Varbanov 			ret = -ENOMEM;
169f012b23dSStanimir Varbanov 			goto fail;
170f012b23dSStanimir Varbanov 		}
171f012b23dSStanimir Varbanov 
172f012b23dSStanimir Varbanov 		list_add_tail(&buf->list, &inst->dpbbufs);
173f012b23dSStanimir Varbanov 	}
174f012b23dSStanimir Varbanov 
175f012b23dSStanimir Varbanov 	return 0;
176f012b23dSStanimir Varbanov 
177f012b23dSStanimir Varbanov fail:
178f012b23dSStanimir Varbanov 	venus_helper_free_dpb_bufs(inst);
179f012b23dSStanimir Varbanov 	return ret;
180f012b23dSStanimir Varbanov }
181f012b23dSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_alloc_dpb_bufs);
182f012b23dSStanimir Varbanov 
183af2c3834SStanimir Varbanov static int intbufs_set_buffer(struct venus_inst *inst, u32 type)
184af2c3834SStanimir Varbanov {
185af2c3834SStanimir Varbanov 	struct venus_core *core = inst->core;
186af2c3834SStanimir Varbanov 	struct device *dev = core->dev;
187af2c3834SStanimir Varbanov 	struct hfi_buffer_requirements bufreq;
188af2c3834SStanimir Varbanov 	struct hfi_buffer_desc bd;
189af2c3834SStanimir Varbanov 	struct intbuf *buf;
190af2c3834SStanimir Varbanov 	unsigned int i;
191af2c3834SStanimir Varbanov 	int ret;
192af2c3834SStanimir Varbanov 
193af2c3834SStanimir Varbanov 	ret = venus_helper_get_bufreq(inst, type, &bufreq);
194af2c3834SStanimir Varbanov 	if (ret)
195af2c3834SStanimir Varbanov 		return 0;
196af2c3834SStanimir Varbanov 
197af2c3834SStanimir Varbanov 	if (!bufreq.size)
198af2c3834SStanimir Varbanov 		return 0;
199af2c3834SStanimir Varbanov 
200af2c3834SStanimir Varbanov 	for (i = 0; i < bufreq.count_actual; i++) {
201af2c3834SStanimir Varbanov 		buf = kzalloc(sizeof(*buf), GFP_KERNEL);
202af2c3834SStanimir Varbanov 		if (!buf) {
203af2c3834SStanimir Varbanov 			ret = -ENOMEM;
204af2c3834SStanimir Varbanov 			goto fail;
205af2c3834SStanimir Varbanov 		}
206af2c3834SStanimir Varbanov 
207af2c3834SStanimir Varbanov 		buf->type = bufreq.type;
208af2c3834SStanimir Varbanov 		buf->size = bufreq.size;
209af2c3834SStanimir Varbanov 		buf->attrs = DMA_ATTR_WRITE_COMBINE |
210af2c3834SStanimir Varbanov 			     DMA_ATTR_NO_KERNEL_MAPPING;
211af2c3834SStanimir Varbanov 		buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL,
212af2c3834SStanimir Varbanov 					  buf->attrs);
213af2c3834SStanimir Varbanov 		if (!buf->va) {
214af2c3834SStanimir Varbanov 			ret = -ENOMEM;
215af2c3834SStanimir Varbanov 			goto fail;
216af2c3834SStanimir Varbanov 		}
217af2c3834SStanimir Varbanov 
218af2c3834SStanimir Varbanov 		memset(&bd, 0, sizeof(bd));
219af2c3834SStanimir Varbanov 		bd.buffer_size = buf->size;
220af2c3834SStanimir Varbanov 		bd.buffer_type = buf->type;
221af2c3834SStanimir Varbanov 		bd.num_buffers = 1;
222af2c3834SStanimir Varbanov 		bd.device_addr = buf->da;
223af2c3834SStanimir Varbanov 
224af2c3834SStanimir Varbanov 		ret = hfi_session_set_buffers(inst, &bd);
225af2c3834SStanimir Varbanov 		if (ret) {
226af2c3834SStanimir Varbanov 			dev_err(dev, "set session buffers failed\n");
227af2c3834SStanimir Varbanov 			goto dma_free;
228af2c3834SStanimir Varbanov 		}
229af2c3834SStanimir Varbanov 
230af2c3834SStanimir Varbanov 		list_add_tail(&buf->list, &inst->internalbufs);
231af2c3834SStanimir Varbanov 	}
232af2c3834SStanimir Varbanov 
233af2c3834SStanimir Varbanov 	return 0;
234af2c3834SStanimir Varbanov 
235af2c3834SStanimir Varbanov dma_free:
236af2c3834SStanimir Varbanov 	dma_free_attrs(dev, buf->size, buf->va, buf->da, buf->attrs);
237af2c3834SStanimir Varbanov fail:
238af2c3834SStanimir Varbanov 	kfree(buf);
239af2c3834SStanimir Varbanov 	return ret;
240af2c3834SStanimir Varbanov }
241af2c3834SStanimir Varbanov 
242af2c3834SStanimir Varbanov static int intbufs_unset_buffers(struct venus_inst *inst)
243af2c3834SStanimir Varbanov {
244af2c3834SStanimir Varbanov 	struct hfi_buffer_desc bd = {0};
245af2c3834SStanimir Varbanov 	struct intbuf *buf, *n;
246af2c3834SStanimir Varbanov 	int ret = 0;
247af2c3834SStanimir Varbanov 
248af2c3834SStanimir Varbanov 	list_for_each_entry_safe(buf, n, &inst->internalbufs, list) {
249af2c3834SStanimir Varbanov 		bd.buffer_size = buf->size;
250af2c3834SStanimir Varbanov 		bd.buffer_type = buf->type;
251af2c3834SStanimir Varbanov 		bd.num_buffers = 1;
252af2c3834SStanimir Varbanov 		bd.device_addr = buf->da;
253af2c3834SStanimir Varbanov 		bd.response_required = true;
254af2c3834SStanimir Varbanov 
255af2c3834SStanimir Varbanov 		ret = hfi_session_unset_buffers(inst, &bd);
256af2c3834SStanimir Varbanov 
257af2c3834SStanimir Varbanov 		list_del_init(&buf->list);
258af2c3834SStanimir Varbanov 		dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,
259af2c3834SStanimir Varbanov 			       buf->attrs);
260af2c3834SStanimir Varbanov 		kfree(buf);
261af2c3834SStanimir Varbanov 	}
262af2c3834SStanimir Varbanov 
263af2c3834SStanimir Varbanov 	return ret;
264af2c3834SStanimir Varbanov }
265af2c3834SStanimir Varbanov 
266f04997bdSStanimir Varbanov static const unsigned int intbuf_types_1xx[] = {
267f04997bdSStanimir Varbanov 	HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_1XX),
268f04997bdSStanimir Varbanov 	HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_1XX),
269f04997bdSStanimir Varbanov 	HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_1XX),
270f04997bdSStanimir Varbanov 	HFI_BUFFER_INTERNAL_PERSIST,
271f04997bdSStanimir Varbanov 	HFI_BUFFER_INTERNAL_PERSIST_1,
272f04997bdSStanimir Varbanov };
273f04997bdSStanimir Varbanov 
274f04997bdSStanimir Varbanov static const unsigned int intbuf_types_4xx[] = {
275f04997bdSStanimir Varbanov 	HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_4XX),
276f04997bdSStanimir Varbanov 	HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_4XX),
277f04997bdSStanimir Varbanov 	HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_4XX),
278af2c3834SStanimir Varbanov 	HFI_BUFFER_INTERNAL_PERSIST,
279af2c3834SStanimir Varbanov 	HFI_BUFFER_INTERNAL_PERSIST_1,
280af2c3834SStanimir Varbanov };
281af2c3834SStanimir Varbanov 
2821e485ee5SStanimir Varbanov int venus_helper_intbufs_alloc(struct venus_inst *inst)
283af2c3834SStanimir Varbanov {
284f04997bdSStanimir Varbanov 	const unsigned int *intbuf;
285f04997bdSStanimir Varbanov 	size_t arr_sz, i;
286af2c3834SStanimir Varbanov 	int ret;
287af2c3834SStanimir Varbanov 
288f04997bdSStanimir Varbanov 	if (IS_V4(inst->core)) {
289f04997bdSStanimir Varbanov 		arr_sz = ARRAY_SIZE(intbuf_types_4xx);
290f04997bdSStanimir Varbanov 		intbuf = intbuf_types_4xx;
291f04997bdSStanimir Varbanov 	} else {
292f04997bdSStanimir Varbanov 		arr_sz = ARRAY_SIZE(intbuf_types_1xx);
293f04997bdSStanimir Varbanov 		intbuf = intbuf_types_1xx;
294f04997bdSStanimir Varbanov 	}
295f04997bdSStanimir Varbanov 
296f04997bdSStanimir Varbanov 	for (i = 0; i < arr_sz; i++) {
297f04997bdSStanimir Varbanov 		ret = intbufs_set_buffer(inst, intbuf[i]);
298af2c3834SStanimir Varbanov 		if (ret)
299af2c3834SStanimir Varbanov 			goto error;
300af2c3834SStanimir Varbanov 	}
301af2c3834SStanimir Varbanov 
302af2c3834SStanimir Varbanov 	return 0;
303af2c3834SStanimir Varbanov 
304af2c3834SStanimir Varbanov error:
305af2c3834SStanimir Varbanov 	intbufs_unset_buffers(inst);
306af2c3834SStanimir Varbanov 	return ret;
307af2c3834SStanimir Varbanov }
3081e485ee5SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_intbufs_alloc);
309af2c3834SStanimir Varbanov 
3101e485ee5SStanimir Varbanov int venus_helper_intbufs_free(struct venus_inst *inst)
311af2c3834SStanimir Varbanov {
312af2c3834SStanimir Varbanov 	return intbufs_unset_buffers(inst);
313af2c3834SStanimir Varbanov }
3141e485ee5SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_intbufs_free);
315af2c3834SStanimir Varbanov 
31614ea00d6SStanimir Varbanov int venus_helper_intbufs_realloc(struct venus_inst *inst)
31714ea00d6SStanimir Varbanov {
31814ea00d6SStanimir Varbanov 	enum hfi_version ver = inst->core->res->hfi_version;
31914ea00d6SStanimir Varbanov 	struct hfi_buffer_desc bd;
32014ea00d6SStanimir Varbanov 	struct intbuf *buf, *n;
32114ea00d6SStanimir Varbanov 	int ret;
32214ea00d6SStanimir Varbanov 
32314ea00d6SStanimir Varbanov 	list_for_each_entry_safe(buf, n, &inst->internalbufs, list) {
32414ea00d6SStanimir Varbanov 		if (buf->type == HFI_BUFFER_INTERNAL_PERSIST ||
32514ea00d6SStanimir Varbanov 		    buf->type == HFI_BUFFER_INTERNAL_PERSIST_1)
32614ea00d6SStanimir Varbanov 			continue;
32714ea00d6SStanimir Varbanov 
32814ea00d6SStanimir Varbanov 		memset(&bd, 0, sizeof(bd));
32914ea00d6SStanimir Varbanov 		bd.buffer_size = buf->size;
33014ea00d6SStanimir Varbanov 		bd.buffer_type = buf->type;
33114ea00d6SStanimir Varbanov 		bd.num_buffers = 1;
33214ea00d6SStanimir Varbanov 		bd.device_addr = buf->da;
33314ea00d6SStanimir Varbanov 		bd.response_required = true;
33414ea00d6SStanimir Varbanov 
33514ea00d6SStanimir Varbanov 		ret = hfi_session_unset_buffers(inst, &bd);
33614ea00d6SStanimir Varbanov 
33714ea00d6SStanimir Varbanov 		dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,
33814ea00d6SStanimir Varbanov 			       buf->attrs);
33914ea00d6SStanimir Varbanov 
34014ea00d6SStanimir Varbanov 		list_del_init(&buf->list);
34114ea00d6SStanimir Varbanov 		kfree(buf);
34214ea00d6SStanimir Varbanov 	}
34314ea00d6SStanimir Varbanov 
34414ea00d6SStanimir Varbanov 	ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH(ver));
34514ea00d6SStanimir Varbanov 	if (ret)
34614ea00d6SStanimir Varbanov 		goto err;
34714ea00d6SStanimir Varbanov 
34814ea00d6SStanimir Varbanov 	ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH_1(ver));
34914ea00d6SStanimir Varbanov 	if (ret)
35014ea00d6SStanimir Varbanov 		goto err;
35114ea00d6SStanimir Varbanov 
35214ea00d6SStanimir Varbanov 	ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH_2(ver));
35314ea00d6SStanimir Varbanov 	if (ret)
35414ea00d6SStanimir Varbanov 		goto err;
35514ea00d6SStanimir Varbanov 
35614ea00d6SStanimir Varbanov 	return 0;
35714ea00d6SStanimir Varbanov err:
35814ea00d6SStanimir Varbanov 	return ret;
35914ea00d6SStanimir Varbanov }
36014ea00d6SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_intbufs_realloc);
36114ea00d6SStanimir Varbanov 
362af2c3834SStanimir Varbanov static void fill_buffer_desc(const struct venus_buffer *buf,
363af2c3834SStanimir Varbanov 			     struct hfi_buffer_desc *bd, bool response)
364af2c3834SStanimir Varbanov {
365af2c3834SStanimir Varbanov 	memset(bd, 0, sizeof(*bd));
366af2c3834SStanimir Varbanov 	bd->buffer_type = HFI_BUFFER_OUTPUT;
367af2c3834SStanimir Varbanov 	bd->buffer_size = buf->size;
368af2c3834SStanimir Varbanov 	bd->num_buffers = 1;
369af2c3834SStanimir Varbanov 	bd->device_addr = buf->dma_addr;
370af2c3834SStanimir Varbanov 	bd->response_required = response;
371af2c3834SStanimir Varbanov }
372af2c3834SStanimir Varbanov 
373af2c3834SStanimir Varbanov static void return_buf_error(struct venus_inst *inst,
374af2c3834SStanimir Varbanov 			     struct vb2_v4l2_buffer *vbuf)
375af2c3834SStanimir Varbanov {
376af2c3834SStanimir Varbanov 	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
377af2c3834SStanimir Varbanov 
378af2c3834SStanimir Varbanov 	if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
379af2c3834SStanimir Varbanov 		v4l2_m2m_src_buf_remove_by_buf(m2m_ctx, vbuf);
380af2c3834SStanimir Varbanov 	else
3810de0ef6cSGustavo A. R. Silva 		v4l2_m2m_dst_buf_remove_by_buf(m2m_ctx, vbuf);
382af2c3834SStanimir Varbanov 
383af2c3834SStanimir Varbanov 	v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
384af2c3834SStanimir Varbanov }
385af2c3834SStanimir Varbanov 
386d42974e4SStanimir Varbanov static void
387d42974e4SStanimir Varbanov put_ts_metadata(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)
388d42974e4SStanimir Varbanov {
389d42974e4SStanimir Varbanov 	struct vb2_buffer *vb = &vbuf->vb2_buf;
390d42974e4SStanimir Varbanov 	unsigned int i;
391d42974e4SStanimir Varbanov 	int slot = -1;
392d42974e4SStanimir Varbanov 	u64 ts_us = vb->timestamp;
393d42974e4SStanimir Varbanov 
394d42974e4SStanimir Varbanov 	for (i = 0; i < ARRAY_SIZE(inst->tss); i++) {
395d42974e4SStanimir Varbanov 		if (!inst->tss[i].used) {
396d42974e4SStanimir Varbanov 			slot = i;
397d42974e4SStanimir Varbanov 			break;
398d42974e4SStanimir Varbanov 		}
399d42974e4SStanimir Varbanov 	}
400d42974e4SStanimir Varbanov 
401d42974e4SStanimir Varbanov 	if (slot == -1) {
4028c91dc08SStanimir Varbanov 		dev_dbg(inst->core->dev, VDBGL "no free slot\n");
403d42974e4SStanimir Varbanov 		return;
404d42974e4SStanimir Varbanov 	}
405d42974e4SStanimir Varbanov 
406d42974e4SStanimir Varbanov 	do_div(ts_us, NSEC_PER_USEC);
407d42974e4SStanimir Varbanov 
408d42974e4SStanimir Varbanov 	inst->tss[slot].used = true;
409d42974e4SStanimir Varbanov 	inst->tss[slot].flags = vbuf->flags;
410d42974e4SStanimir Varbanov 	inst->tss[slot].tc = vbuf->timecode;
411d42974e4SStanimir Varbanov 	inst->tss[slot].ts_us = ts_us;
412d42974e4SStanimir Varbanov 	inst->tss[slot].ts_ns = vb->timestamp;
413d42974e4SStanimir Varbanov }
414d42974e4SStanimir Varbanov 
415d42974e4SStanimir Varbanov void venus_helper_get_ts_metadata(struct venus_inst *inst, u64 timestamp_us,
416d42974e4SStanimir Varbanov 				  struct vb2_v4l2_buffer *vbuf)
417d42974e4SStanimir Varbanov {
418d42974e4SStanimir Varbanov 	struct vb2_buffer *vb = &vbuf->vb2_buf;
419d42974e4SStanimir Varbanov 	unsigned int i;
420d42974e4SStanimir Varbanov 
421d42974e4SStanimir Varbanov 	for (i = 0; i < ARRAY_SIZE(inst->tss); ++i) {
422d42974e4SStanimir Varbanov 		if (!inst->tss[i].used)
423d42974e4SStanimir Varbanov 			continue;
424d42974e4SStanimir Varbanov 
425d42974e4SStanimir Varbanov 		if (inst->tss[i].ts_us != timestamp_us)
426d42974e4SStanimir Varbanov 			continue;
427d42974e4SStanimir Varbanov 
428d42974e4SStanimir Varbanov 		inst->tss[i].used = false;
429d42974e4SStanimir Varbanov 		vbuf->flags |= inst->tss[i].flags;
430d42974e4SStanimir Varbanov 		vbuf->timecode = inst->tss[i].tc;
431d42974e4SStanimir Varbanov 		vb->timestamp = inst->tss[i].ts_ns;
432d42974e4SStanimir Varbanov 		break;
433d42974e4SStanimir Varbanov 	}
434d42974e4SStanimir Varbanov }
435d42974e4SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_ts_metadata);
436d42974e4SStanimir Varbanov 
437af2c3834SStanimir Varbanov static int
438af2c3834SStanimir Varbanov session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)
439af2c3834SStanimir Varbanov {
440af2c3834SStanimir Varbanov 	struct venus_buffer *buf = to_venus_buffer(vbuf);
441af2c3834SStanimir Varbanov 	struct vb2_buffer *vb = &vbuf->vb2_buf;
442af2c3834SStanimir Varbanov 	unsigned int type = vb->type;
443af2c3834SStanimir Varbanov 	struct hfi_frame_data fdata;
444af2c3834SStanimir Varbanov 	int ret;
445af2c3834SStanimir Varbanov 
446af2c3834SStanimir Varbanov 	memset(&fdata, 0, sizeof(fdata));
447af2c3834SStanimir Varbanov 	fdata.alloc_len = buf->size;
448af2c3834SStanimir Varbanov 	fdata.device_addr = buf->dma_addr;
449af2c3834SStanimir Varbanov 	fdata.timestamp = vb->timestamp;
450af2c3834SStanimir Varbanov 	do_div(fdata.timestamp, NSEC_PER_USEC);
451af2c3834SStanimir Varbanov 	fdata.flags = 0;
452af2c3834SStanimir Varbanov 	fdata.clnt_data = vbuf->vb2_buf.index;
453af2c3834SStanimir Varbanov 
454af2c3834SStanimir Varbanov 	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
455af2c3834SStanimir Varbanov 		fdata.buffer_type = HFI_BUFFER_INPUT;
456af2c3834SStanimir Varbanov 		fdata.filled_len = vb2_get_plane_payload(vb, 0);
457af2c3834SStanimir Varbanov 		fdata.offset = vb->planes[0].data_offset;
458af2c3834SStanimir Varbanov 
459af2c3834SStanimir Varbanov 		if (vbuf->flags & V4L2_BUF_FLAG_LAST || !fdata.filled_len)
460af2c3834SStanimir Varbanov 			fdata.flags |= HFI_BUFFERFLAG_EOS;
461d42974e4SStanimir Varbanov 
462d42974e4SStanimir Varbanov 		if (inst->session_type == VIDC_SESSION_TYPE_DEC)
463d42974e4SStanimir Varbanov 			put_ts_metadata(inst, vbuf);
464c0e284ccSAniket Masule 
4657482a983SStanimir Varbanov 		venus_pm_load_scale(inst);
466af2c3834SStanimir Varbanov 	} else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
467f012b23dSStanimir Varbanov 		if (inst->session_type == VIDC_SESSION_TYPE_ENC)
468af2c3834SStanimir Varbanov 			fdata.buffer_type = HFI_BUFFER_OUTPUT;
469f012b23dSStanimir Varbanov 		else
470f012b23dSStanimir Varbanov 			fdata.buffer_type = inst->opb_buftype;
471af2c3834SStanimir Varbanov 		fdata.filled_len = 0;
472af2c3834SStanimir Varbanov 		fdata.offset = 0;
473af2c3834SStanimir Varbanov 	}
474af2c3834SStanimir Varbanov 
475af2c3834SStanimir Varbanov 	ret = hfi_session_process_buf(inst, &fdata);
476af2c3834SStanimir Varbanov 	if (ret)
477af2c3834SStanimir Varbanov 		return ret;
478af2c3834SStanimir Varbanov 
479af2c3834SStanimir Varbanov 	return 0;
480af2c3834SStanimir Varbanov }
481af2c3834SStanimir Varbanov 
482f0383520SStanimir Varbanov static bool is_dynamic_bufmode(struct venus_inst *inst)
483af2c3834SStanimir Varbanov {
484f0383520SStanimir Varbanov 	struct venus_core *core = inst->core;
4858f3b41dcSStanimir Varbanov 	struct hfi_plat_caps *caps;
486f0383520SStanimir Varbanov 
487bc8c479aSStanimir Varbanov 	/*
488bc8c479aSStanimir Varbanov 	 * v4 doesn't send BUFFER_ALLOC_MODE_SUPPORTED property and supports
489bc8c479aSStanimir Varbanov 	 * dynamic buffer mode by default for HFI_BUFFER_OUTPUT/OUTPUT2.
490bc8c479aSStanimir Varbanov 	 */
491bc8c479aSStanimir Varbanov 	if (IS_V4(core))
492bc8c479aSStanimir Varbanov 		return true;
493bc8c479aSStanimir Varbanov 
494f0383520SStanimir Varbanov 	caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);
495f0383520SStanimir Varbanov 	if (!caps)
4961cafbb86SGustavo A. R. Silva 		return false;
497af2c3834SStanimir Varbanov 
498f0383520SStanimir Varbanov 	return caps->cap_bufs_mode_dynamic;
499af2c3834SStanimir Varbanov }
500af2c3834SStanimir Varbanov 
5011e485ee5SStanimir Varbanov int venus_helper_unregister_bufs(struct venus_inst *inst)
502af2c3834SStanimir Varbanov {
503af2c3834SStanimir Varbanov 	struct venus_buffer *buf, *n;
504af2c3834SStanimir Varbanov 	struct hfi_buffer_desc bd;
505af2c3834SStanimir Varbanov 	int ret = 0;
506af2c3834SStanimir Varbanov 
507f0383520SStanimir Varbanov 	if (is_dynamic_bufmode(inst))
508af2c3834SStanimir Varbanov 		return 0;
509af2c3834SStanimir Varbanov 
510af2c3834SStanimir Varbanov 	list_for_each_entry_safe(buf, n, &inst->registeredbufs, reg_list) {
511af2c3834SStanimir Varbanov 		fill_buffer_desc(buf, &bd, true);
512af2c3834SStanimir Varbanov 		ret = hfi_session_unset_buffers(inst, &bd);
513af2c3834SStanimir Varbanov 		list_del_init(&buf->reg_list);
514af2c3834SStanimir Varbanov 	}
515af2c3834SStanimir Varbanov 
516af2c3834SStanimir Varbanov 	return ret;
517af2c3834SStanimir Varbanov }
5181e485ee5SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_unregister_bufs);
519af2c3834SStanimir Varbanov 
520af2c3834SStanimir Varbanov static int session_register_bufs(struct venus_inst *inst)
521af2c3834SStanimir Varbanov {
522af2c3834SStanimir Varbanov 	struct venus_core *core = inst->core;
523af2c3834SStanimir Varbanov 	struct device *dev = core->dev;
524af2c3834SStanimir Varbanov 	struct hfi_buffer_desc bd;
525af2c3834SStanimir Varbanov 	struct venus_buffer *buf;
526af2c3834SStanimir Varbanov 	int ret = 0;
527af2c3834SStanimir Varbanov 
528f0383520SStanimir Varbanov 	if (is_dynamic_bufmode(inst))
529af2c3834SStanimir Varbanov 		return 0;
530af2c3834SStanimir Varbanov 
531af2c3834SStanimir Varbanov 	list_for_each_entry(buf, &inst->registeredbufs, reg_list) {
532af2c3834SStanimir Varbanov 		fill_buffer_desc(buf, &bd, false);
533af2c3834SStanimir Varbanov 		ret = hfi_session_set_buffers(inst, &bd);
534af2c3834SStanimir Varbanov 		if (ret) {
535af2c3834SStanimir Varbanov 			dev_err(dev, "%s: set buffer failed\n", __func__);
536af2c3834SStanimir Varbanov 			break;
537af2c3834SStanimir Varbanov 		}
538af2c3834SStanimir Varbanov 	}
539af2c3834SStanimir Varbanov 
540af2c3834SStanimir Varbanov 	return ret;
541af2c3834SStanimir Varbanov }
542af2c3834SStanimir Varbanov 
543ab97a3fbSStanimir Varbanov static u32 to_hfi_raw_fmt(u32 v4l2_fmt)
544ab97a3fbSStanimir Varbanov {
545ab97a3fbSStanimir Varbanov 	switch (v4l2_fmt) {
546ab97a3fbSStanimir Varbanov 	case V4L2_PIX_FMT_NV12:
547ab97a3fbSStanimir Varbanov 		return HFI_COLOR_FORMAT_NV12;
548ab97a3fbSStanimir Varbanov 	case V4L2_PIX_FMT_NV21:
549ab97a3fbSStanimir Varbanov 		return HFI_COLOR_FORMAT_NV21;
550ab97a3fbSStanimir Varbanov 	default:
551ab97a3fbSStanimir Varbanov 		break;
552ab97a3fbSStanimir Varbanov 	}
553ab97a3fbSStanimir Varbanov 
554ab97a3fbSStanimir Varbanov 	return 0;
555ab97a3fbSStanimir Varbanov }
556ab97a3fbSStanimir Varbanov 
557*7371093fSStanimir Varbanov static int platform_get_bufreq(struct venus_inst *inst, u32 buftype,
558*7371093fSStanimir Varbanov 			       struct hfi_buffer_requirements *req)
559*7371093fSStanimir Varbanov {
560*7371093fSStanimir Varbanov 	enum hfi_version version = inst->core->res->hfi_version;
561*7371093fSStanimir Varbanov 	const struct hfi_platform *hfi_plat;
562*7371093fSStanimir Varbanov 	struct hfi_plat_buffers_params params;
563*7371093fSStanimir Varbanov 	bool is_dec = inst->session_type == VIDC_SESSION_TYPE_DEC;
564*7371093fSStanimir Varbanov 	struct venc_controls *enc_ctr = &inst->controls.enc;
565*7371093fSStanimir Varbanov 
566*7371093fSStanimir Varbanov 	hfi_plat = hfi_platform_get(version);
567*7371093fSStanimir Varbanov 
568*7371093fSStanimir Varbanov 	if (!hfi_plat || !hfi_plat->bufreq)
569*7371093fSStanimir Varbanov 		return -EINVAL;
570*7371093fSStanimir Varbanov 
571*7371093fSStanimir Varbanov 	params.version = version;
572*7371093fSStanimir Varbanov 	params.num_vpp_pipes = hfi_platform_num_vpp_pipes(version);
573*7371093fSStanimir Varbanov 
574*7371093fSStanimir Varbanov 	if (is_dec) {
575*7371093fSStanimir Varbanov 		params.width = inst->width;
576*7371093fSStanimir Varbanov 		params.height = inst->height;
577*7371093fSStanimir Varbanov 		params.codec = inst->fmt_out->pixfmt;
578*7371093fSStanimir Varbanov 		params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_cap->pixfmt);
579*7371093fSStanimir Varbanov 		params.dec.max_mbs_per_frame = mbs_per_frame_max(inst);
580*7371093fSStanimir Varbanov 		params.dec.buffer_size_limit = 0;
581*7371093fSStanimir Varbanov 		params.dec.is_secondary_output =
582*7371093fSStanimir Varbanov 			inst->opb_buftype == HFI_BUFFER_OUTPUT2;
583*7371093fSStanimir Varbanov 		params.dec.is_interlaced =
584*7371093fSStanimir Varbanov 			inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE ?
585*7371093fSStanimir Varbanov 				true : false;
586*7371093fSStanimir Varbanov 	} else {
587*7371093fSStanimir Varbanov 		params.width = inst->out_width;
588*7371093fSStanimir Varbanov 		params.height = inst->out_height;
589*7371093fSStanimir Varbanov 		params.codec = inst->fmt_cap->pixfmt;
590*7371093fSStanimir Varbanov 		params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_out->pixfmt);
591*7371093fSStanimir Varbanov 		params.enc.work_mode = VIDC_WORK_MODE_2;
592*7371093fSStanimir Varbanov 		params.enc.rc_type = HFI_RATE_CONTROL_OFF;
593*7371093fSStanimir Varbanov 		if (enc_ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
594*7371093fSStanimir Varbanov 			params.enc.rc_type = HFI_RATE_CONTROL_CQ;
595*7371093fSStanimir Varbanov 		params.enc.num_b_frames = enc_ctr->num_b_frames;
596*7371093fSStanimir Varbanov 		params.enc.is_tenbit = inst->bit_depth == VIDC_BITDEPTH_10;
597*7371093fSStanimir Varbanov 	}
598*7371093fSStanimir Varbanov 
599*7371093fSStanimir Varbanov 	return hfi_plat->bufreq(&params, inst->session_type, buftype, req);
600*7371093fSStanimir Varbanov }
601*7371093fSStanimir Varbanov 
602af2c3834SStanimir Varbanov int venus_helper_get_bufreq(struct venus_inst *inst, u32 type,
603af2c3834SStanimir Varbanov 			    struct hfi_buffer_requirements *req)
604af2c3834SStanimir Varbanov {
605af2c3834SStanimir Varbanov 	u32 ptype = HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS;
606af2c3834SStanimir Varbanov 	union hfi_get_property hprop;
607af2c3834SStanimir Varbanov 	unsigned int i;
608af2c3834SStanimir Varbanov 	int ret;
609af2c3834SStanimir Varbanov 
610af2c3834SStanimir Varbanov 	if (req)
611af2c3834SStanimir Varbanov 		memset(req, 0, sizeof(*req));
612af2c3834SStanimir Varbanov 
613*7371093fSStanimir Varbanov 	ret = platform_get_bufreq(inst, type, req);
614*7371093fSStanimir Varbanov 	if (!ret)
615*7371093fSStanimir Varbanov 		return 0;
616*7371093fSStanimir Varbanov 
617af2c3834SStanimir Varbanov 	ret = hfi_session_get_property(inst, ptype, &hprop);
618af2c3834SStanimir Varbanov 	if (ret)
619af2c3834SStanimir Varbanov 		return ret;
620af2c3834SStanimir Varbanov 
621af2c3834SStanimir Varbanov 	ret = -EINVAL;
622af2c3834SStanimir Varbanov 
623af2c3834SStanimir Varbanov 	for (i = 0; i < HFI_BUFFER_TYPE_MAX; i++) {
624af2c3834SStanimir Varbanov 		if (hprop.bufreq[i].type != type)
625af2c3834SStanimir Varbanov 			continue;
626af2c3834SStanimir Varbanov 
627af2c3834SStanimir Varbanov 		if (req)
628af2c3834SStanimir Varbanov 			memcpy(req, &hprop.bufreq[i], sizeof(*req));
629af2c3834SStanimir Varbanov 		ret = 0;
630af2c3834SStanimir Varbanov 		break;
631af2c3834SStanimir Varbanov 	}
632af2c3834SStanimir Varbanov 
633af2c3834SStanimir Varbanov 	return ret;
634af2c3834SStanimir Varbanov }
635af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_bufreq);
636af2c3834SStanimir Varbanov 
6372c2dc2fdSStanimir Varbanov struct id_mapping {
6382c2dc2fdSStanimir Varbanov 	u32 hfi_id;
6392c2dc2fdSStanimir Varbanov 	u32 v4l2_id;
6402c2dc2fdSStanimir Varbanov };
6412c2dc2fdSStanimir Varbanov 
6422c2dc2fdSStanimir Varbanov static const struct id_mapping mpeg4_profiles[] = {
6432c2dc2fdSStanimir Varbanov 	{ HFI_MPEG4_PROFILE_SIMPLE, V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE },
6442c2dc2fdSStanimir Varbanov 	{ HFI_MPEG4_PROFILE_ADVANCEDSIMPLE, V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE },
6452c2dc2fdSStanimir Varbanov };
6462c2dc2fdSStanimir Varbanov 
6472c2dc2fdSStanimir Varbanov static const struct id_mapping mpeg4_levels[] = {
6482c2dc2fdSStanimir Varbanov 	{ HFI_MPEG4_LEVEL_0, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0 },
6492c2dc2fdSStanimir Varbanov 	{ HFI_MPEG4_LEVEL_0b, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B },
6502c2dc2fdSStanimir Varbanov 	{ HFI_MPEG4_LEVEL_1, V4L2_MPEG_VIDEO_MPEG4_LEVEL_1 },
6512c2dc2fdSStanimir Varbanov 	{ HFI_MPEG4_LEVEL_2, V4L2_MPEG_VIDEO_MPEG4_LEVEL_2 },
6522c2dc2fdSStanimir Varbanov 	{ HFI_MPEG4_LEVEL_3, V4L2_MPEG_VIDEO_MPEG4_LEVEL_3 },
6532c2dc2fdSStanimir Varbanov 	{ HFI_MPEG4_LEVEL_4, V4L2_MPEG_VIDEO_MPEG4_LEVEL_4 },
6542c2dc2fdSStanimir Varbanov 	{ HFI_MPEG4_LEVEL_5, V4L2_MPEG_VIDEO_MPEG4_LEVEL_5 },
6552c2dc2fdSStanimir Varbanov };
6562c2dc2fdSStanimir Varbanov 
6572c2dc2fdSStanimir Varbanov static const struct id_mapping mpeg2_profiles[] = {
6582c2dc2fdSStanimir Varbanov 	{ HFI_MPEG2_PROFILE_SIMPLE, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SIMPLE },
6592c2dc2fdSStanimir Varbanov 	{ HFI_MPEG2_PROFILE_MAIN, V4L2_MPEG_VIDEO_MPEG2_PROFILE_MAIN },
6602c2dc2fdSStanimir Varbanov 	{ HFI_MPEG2_PROFILE_SNR, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SNR_SCALABLE },
6612c2dc2fdSStanimir Varbanov 	{ HFI_MPEG2_PROFILE_SPATIAL, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SPATIALLY_SCALABLE },
6622c2dc2fdSStanimir Varbanov 	{ HFI_MPEG2_PROFILE_HIGH, V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH },
6632c2dc2fdSStanimir Varbanov };
6642c2dc2fdSStanimir Varbanov 
6652c2dc2fdSStanimir Varbanov static const struct id_mapping mpeg2_levels[] = {
6662c2dc2fdSStanimir Varbanov 	{ HFI_MPEG2_LEVEL_LL, V4L2_MPEG_VIDEO_MPEG2_LEVEL_LOW },
6672c2dc2fdSStanimir Varbanov 	{ HFI_MPEG2_LEVEL_ML, V4L2_MPEG_VIDEO_MPEG2_LEVEL_MAIN },
6682c2dc2fdSStanimir Varbanov 	{ HFI_MPEG2_LEVEL_H14, V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH_1440 },
6692c2dc2fdSStanimir Varbanov 	{ HFI_MPEG2_LEVEL_HL, V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH },
6702c2dc2fdSStanimir Varbanov };
6712c2dc2fdSStanimir Varbanov 
6722c2dc2fdSStanimir Varbanov static const struct id_mapping h264_profiles[] = {
6732c2dc2fdSStanimir Varbanov 	{ HFI_H264_PROFILE_BASELINE, V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE },
6742c2dc2fdSStanimir Varbanov 	{ HFI_H264_PROFILE_MAIN, V4L2_MPEG_VIDEO_H264_PROFILE_MAIN },
6752c2dc2fdSStanimir Varbanov 	{ HFI_H264_PROFILE_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_HIGH },
6762c2dc2fdSStanimir Varbanov 	{ HFI_H264_PROFILE_STEREO_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH },
6772c2dc2fdSStanimir Varbanov 	{ HFI_H264_PROFILE_MULTIVIEW_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH },
6782c2dc2fdSStanimir Varbanov 	{ HFI_H264_PROFILE_CONSTRAINED_BASE, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE },
6792c2dc2fdSStanimir Varbanov 	{ HFI_H264_PROFILE_CONSTRAINED_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH },
6802c2dc2fdSStanimir Varbanov };
6812c2dc2fdSStanimir Varbanov 
6822c2dc2fdSStanimir Varbanov static const struct id_mapping h264_levels[] = {
6832c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_1, V4L2_MPEG_VIDEO_H264_LEVEL_1_0 },
6842c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_1b, V4L2_MPEG_VIDEO_H264_LEVEL_1B },
6852c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_11, V4L2_MPEG_VIDEO_H264_LEVEL_1_1 },
6862c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_12, V4L2_MPEG_VIDEO_H264_LEVEL_1_2 },
6872c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_13, V4L2_MPEG_VIDEO_H264_LEVEL_1_3 },
6882c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_2, V4L2_MPEG_VIDEO_H264_LEVEL_2_0 },
6892c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_21, V4L2_MPEG_VIDEO_H264_LEVEL_2_1 },
6902c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_22, V4L2_MPEG_VIDEO_H264_LEVEL_2_2 },
6912c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_3, V4L2_MPEG_VIDEO_H264_LEVEL_3_0 },
6922c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_31, V4L2_MPEG_VIDEO_H264_LEVEL_3_1 },
6932c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_32, V4L2_MPEG_VIDEO_H264_LEVEL_3_2 },
6942c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_4, V4L2_MPEG_VIDEO_H264_LEVEL_4_0 },
6952c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_41, V4L2_MPEG_VIDEO_H264_LEVEL_4_1 },
6962c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_42, V4L2_MPEG_VIDEO_H264_LEVEL_4_2 },
6972c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_5, V4L2_MPEG_VIDEO_H264_LEVEL_5_0 },
6982c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_51, V4L2_MPEG_VIDEO_H264_LEVEL_5_1 },
6992c2dc2fdSStanimir Varbanov 	{ HFI_H264_LEVEL_52, V4L2_MPEG_VIDEO_H264_LEVEL_5_1 },
7002c2dc2fdSStanimir Varbanov };
7012c2dc2fdSStanimir Varbanov 
7022c2dc2fdSStanimir Varbanov static const struct id_mapping hevc_profiles[] = {
7032c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_PROFILE_MAIN, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN },
7042c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_PROFILE_MAIN_STILL_PIC, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE },
7052c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_PROFILE_MAIN10, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10 },
7062c2dc2fdSStanimir Varbanov };
7072c2dc2fdSStanimir Varbanov 
7082c2dc2fdSStanimir Varbanov static const struct id_mapping hevc_levels[] = {
7092c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_LEVEL_1, V4L2_MPEG_VIDEO_HEVC_LEVEL_1 },
7102c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_LEVEL_2, V4L2_MPEG_VIDEO_HEVC_LEVEL_2 },
7112c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_LEVEL_21, V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1 },
7122c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_LEVEL_3, V4L2_MPEG_VIDEO_HEVC_LEVEL_3 },
7132c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_LEVEL_31, V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1 },
7142c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_LEVEL_4, V4L2_MPEG_VIDEO_HEVC_LEVEL_4 },
7152c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_LEVEL_41, V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1 },
7162c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_LEVEL_5, V4L2_MPEG_VIDEO_HEVC_LEVEL_5 },
7172c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_LEVEL_51, V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1 },
7182c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_LEVEL_52, V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2 },
7192c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_LEVEL_6, V4L2_MPEG_VIDEO_HEVC_LEVEL_6 },
7202c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_LEVEL_61, V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1 },
7212c2dc2fdSStanimir Varbanov 	{ HFI_HEVC_LEVEL_62, V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2 },
7222c2dc2fdSStanimir Varbanov };
7232c2dc2fdSStanimir Varbanov 
7242c2dc2fdSStanimir Varbanov static const struct id_mapping vp8_profiles[] = {
7252c2dc2fdSStanimir Varbanov 	{ HFI_VPX_PROFILE_VERSION_0, V4L2_MPEG_VIDEO_VP8_PROFILE_0 },
7262c2dc2fdSStanimir Varbanov 	{ HFI_VPX_PROFILE_VERSION_1, V4L2_MPEG_VIDEO_VP8_PROFILE_1 },
7272c2dc2fdSStanimir Varbanov 	{ HFI_VPX_PROFILE_VERSION_2, V4L2_MPEG_VIDEO_VP8_PROFILE_2 },
7282c2dc2fdSStanimir Varbanov 	{ HFI_VPX_PROFILE_VERSION_3, V4L2_MPEG_VIDEO_VP8_PROFILE_3 },
7292c2dc2fdSStanimir Varbanov };
7302c2dc2fdSStanimir Varbanov 
7312c2dc2fdSStanimir Varbanov static const struct id_mapping vp9_profiles[] = {
7322c2dc2fdSStanimir Varbanov 	{ HFI_VP9_PROFILE_P0, V4L2_MPEG_VIDEO_VP9_PROFILE_0 },
7332c2dc2fdSStanimir Varbanov 	{ HFI_VP9_PROFILE_P2_10B, V4L2_MPEG_VIDEO_VP9_PROFILE_2 },
7342c2dc2fdSStanimir Varbanov };
7352c2dc2fdSStanimir Varbanov 
7362c2dc2fdSStanimir Varbanov static const struct id_mapping vp9_levels[] = {
7372c2dc2fdSStanimir Varbanov 	{ HFI_VP9_LEVEL_1, V4L2_MPEG_VIDEO_VP9_LEVEL_1_0 },
7382c2dc2fdSStanimir Varbanov 	{ HFI_VP9_LEVEL_11, V4L2_MPEG_VIDEO_VP9_LEVEL_1_1 },
7392c2dc2fdSStanimir Varbanov 	{ HFI_VP9_LEVEL_2, V4L2_MPEG_VIDEO_VP9_LEVEL_2_0},
7402c2dc2fdSStanimir Varbanov 	{ HFI_VP9_LEVEL_21, V4L2_MPEG_VIDEO_VP9_LEVEL_2_1 },
7412c2dc2fdSStanimir Varbanov 	{ HFI_VP9_LEVEL_3, V4L2_MPEG_VIDEO_VP9_LEVEL_3_0},
7422c2dc2fdSStanimir Varbanov 	{ HFI_VP9_LEVEL_31, V4L2_MPEG_VIDEO_VP9_LEVEL_3_1 },
7432c2dc2fdSStanimir Varbanov 	{ HFI_VP9_LEVEL_4, V4L2_MPEG_VIDEO_VP9_LEVEL_4_0 },
7442c2dc2fdSStanimir Varbanov 	{ HFI_VP9_LEVEL_41, V4L2_MPEG_VIDEO_VP9_LEVEL_4_1 },
7452c2dc2fdSStanimir Varbanov 	{ HFI_VP9_LEVEL_5, V4L2_MPEG_VIDEO_VP9_LEVEL_5_0 },
7462c2dc2fdSStanimir Varbanov 	{ HFI_VP9_LEVEL_51, V4L2_MPEG_VIDEO_VP9_LEVEL_5_1 },
7472c2dc2fdSStanimir Varbanov 	{ HFI_VP9_LEVEL_6, V4L2_MPEG_VIDEO_VP9_LEVEL_6_0 },
7482c2dc2fdSStanimir Varbanov 	{ HFI_VP9_LEVEL_61, V4L2_MPEG_VIDEO_VP9_LEVEL_6_1 },
7492c2dc2fdSStanimir Varbanov };
7502c2dc2fdSStanimir Varbanov 
7512c2dc2fdSStanimir Varbanov static u32 find_v4l2_id(u32 hfi_id, const struct id_mapping *array, unsigned int array_sz)
7522c2dc2fdSStanimir Varbanov {
7532c2dc2fdSStanimir Varbanov 	unsigned int i;
7542c2dc2fdSStanimir Varbanov 
7552c2dc2fdSStanimir Varbanov 	if (!array || !array_sz)
7562c2dc2fdSStanimir Varbanov 		return 0;
7572c2dc2fdSStanimir Varbanov 
7582c2dc2fdSStanimir Varbanov 	for (i = 0; i < array_sz; i++)
7592c2dc2fdSStanimir Varbanov 		if (hfi_id == array[i].hfi_id)
7602c2dc2fdSStanimir Varbanov 			return array[i].v4l2_id;
7612c2dc2fdSStanimir Varbanov 
7622c2dc2fdSStanimir Varbanov 	return 0;
7632c2dc2fdSStanimir Varbanov }
7642c2dc2fdSStanimir Varbanov 
7652c2dc2fdSStanimir Varbanov static u32 find_hfi_id(u32 v4l2_id, const struct id_mapping *array, unsigned int array_sz)
7662c2dc2fdSStanimir Varbanov {
7672c2dc2fdSStanimir Varbanov 	unsigned int i;
7682c2dc2fdSStanimir Varbanov 
7692c2dc2fdSStanimir Varbanov 	if (!array || !array_sz)
7702c2dc2fdSStanimir Varbanov 		return 0;
7712c2dc2fdSStanimir Varbanov 
7722c2dc2fdSStanimir Varbanov 	for (i = 0; i < array_sz; i++)
7732c2dc2fdSStanimir Varbanov 		if (v4l2_id == array[i].v4l2_id)
7742c2dc2fdSStanimir Varbanov 			return array[i].hfi_id;
7752c2dc2fdSStanimir Varbanov 
7762c2dc2fdSStanimir Varbanov 	return 0;
7772c2dc2fdSStanimir Varbanov }
7782c2dc2fdSStanimir Varbanov 
7792c2dc2fdSStanimir Varbanov static void
7802c2dc2fdSStanimir Varbanov v4l2_id_profile_level(u32 hfi_codec, struct hfi_profile_level *pl, u32 *profile, u32 *level)
7812c2dc2fdSStanimir Varbanov {
7822c2dc2fdSStanimir Varbanov 	u32 hfi_pf = pl->profile;
7832c2dc2fdSStanimir Varbanov 	u32 hfi_lvl = pl->level;
7842c2dc2fdSStanimir Varbanov 
7852c2dc2fdSStanimir Varbanov 	switch (hfi_codec) {
7862c2dc2fdSStanimir Varbanov 	case HFI_VIDEO_CODEC_H264:
7872c2dc2fdSStanimir Varbanov 		*profile = find_v4l2_id(hfi_pf, h264_profiles, ARRAY_SIZE(h264_profiles));
7882c2dc2fdSStanimir Varbanov 		*level = find_v4l2_id(hfi_lvl, h264_levels, ARRAY_SIZE(h264_levels));
7892c2dc2fdSStanimir Varbanov 		break;
7902c2dc2fdSStanimir Varbanov 	case HFI_VIDEO_CODEC_MPEG2:
7912c2dc2fdSStanimir Varbanov 		*profile = find_v4l2_id(hfi_pf, mpeg2_profiles, ARRAY_SIZE(mpeg2_profiles));
7922c2dc2fdSStanimir Varbanov 		*level = find_v4l2_id(hfi_lvl, mpeg2_levels, ARRAY_SIZE(mpeg2_levels));
7932c2dc2fdSStanimir Varbanov 		break;
7942c2dc2fdSStanimir Varbanov 	case HFI_VIDEO_CODEC_MPEG4:
7952c2dc2fdSStanimir Varbanov 		*profile = find_v4l2_id(hfi_pf, mpeg4_profiles, ARRAY_SIZE(mpeg4_profiles));
7962c2dc2fdSStanimir Varbanov 		*level = find_v4l2_id(hfi_lvl, mpeg4_levels, ARRAY_SIZE(mpeg4_levels));
7972c2dc2fdSStanimir Varbanov 		break;
7982c2dc2fdSStanimir Varbanov 	case HFI_VIDEO_CODEC_VP8:
7992c2dc2fdSStanimir Varbanov 		*profile = find_v4l2_id(hfi_pf, vp8_profiles, ARRAY_SIZE(vp8_profiles));
8002c2dc2fdSStanimir Varbanov 		*level = 0;
8012c2dc2fdSStanimir Varbanov 		break;
8022c2dc2fdSStanimir Varbanov 	case HFI_VIDEO_CODEC_VP9:
8032c2dc2fdSStanimir Varbanov 		*profile = find_v4l2_id(hfi_pf, vp9_profiles, ARRAY_SIZE(vp9_profiles));
8042c2dc2fdSStanimir Varbanov 		*level = find_v4l2_id(hfi_lvl, vp9_levels, ARRAY_SIZE(vp9_levels));
8052c2dc2fdSStanimir Varbanov 		break;
8062c2dc2fdSStanimir Varbanov 	case HFI_VIDEO_CODEC_HEVC:
8072c2dc2fdSStanimir Varbanov 		*profile = find_v4l2_id(hfi_pf, hevc_profiles, ARRAY_SIZE(hevc_profiles));
8082c2dc2fdSStanimir Varbanov 		*level = find_v4l2_id(hfi_lvl, hevc_levels, ARRAY_SIZE(hevc_levels));
8092c2dc2fdSStanimir Varbanov 		break;
8102c2dc2fdSStanimir Varbanov 	default:
8112c2dc2fdSStanimir Varbanov 		break;
8122c2dc2fdSStanimir Varbanov 	}
8132c2dc2fdSStanimir Varbanov }
8142c2dc2fdSStanimir Varbanov 
8152c2dc2fdSStanimir Varbanov static void
8162c2dc2fdSStanimir Varbanov hfi_id_profile_level(u32 hfi_codec, u32 v4l2_pf, u32 v4l2_lvl, struct hfi_profile_level *pl)
8172c2dc2fdSStanimir Varbanov {
8182c2dc2fdSStanimir Varbanov 	switch (hfi_codec) {
8192c2dc2fdSStanimir Varbanov 	case HFI_VIDEO_CODEC_H264:
8202c2dc2fdSStanimir Varbanov 		pl->profile = find_hfi_id(v4l2_pf, h264_profiles, ARRAY_SIZE(h264_profiles));
8212c2dc2fdSStanimir Varbanov 		pl->level = find_hfi_id(v4l2_lvl, h264_levels, ARRAY_SIZE(h264_levels));
8222c2dc2fdSStanimir Varbanov 		break;
8232c2dc2fdSStanimir Varbanov 	case HFI_VIDEO_CODEC_MPEG2:
8242c2dc2fdSStanimir Varbanov 		pl->profile = find_hfi_id(v4l2_pf, mpeg2_profiles, ARRAY_SIZE(mpeg2_profiles));
8252c2dc2fdSStanimir Varbanov 		pl->level = find_hfi_id(v4l2_lvl, mpeg2_levels, ARRAY_SIZE(mpeg2_levels));
8262c2dc2fdSStanimir Varbanov 		break;
8272c2dc2fdSStanimir Varbanov 	case HFI_VIDEO_CODEC_MPEG4:
8282c2dc2fdSStanimir Varbanov 		pl->profile = find_hfi_id(v4l2_pf, mpeg4_profiles, ARRAY_SIZE(mpeg4_profiles));
8292c2dc2fdSStanimir Varbanov 		pl->level = find_hfi_id(v4l2_lvl, mpeg4_levels, ARRAY_SIZE(mpeg4_levels));
8302c2dc2fdSStanimir Varbanov 		break;
8312c2dc2fdSStanimir Varbanov 	case HFI_VIDEO_CODEC_VP8:
8322c2dc2fdSStanimir Varbanov 		pl->profile = find_hfi_id(v4l2_pf, vp8_profiles, ARRAY_SIZE(vp8_profiles));
8332c2dc2fdSStanimir Varbanov 		pl->level = 0;
8342c2dc2fdSStanimir Varbanov 		break;
8352c2dc2fdSStanimir Varbanov 	case HFI_VIDEO_CODEC_VP9:
8362c2dc2fdSStanimir Varbanov 		pl->profile = find_hfi_id(v4l2_pf, vp9_profiles, ARRAY_SIZE(vp9_profiles));
8372c2dc2fdSStanimir Varbanov 		pl->level = find_hfi_id(v4l2_lvl, vp9_levels, ARRAY_SIZE(vp9_levels));
8382c2dc2fdSStanimir Varbanov 		break;
8392c2dc2fdSStanimir Varbanov 	case HFI_VIDEO_CODEC_HEVC:
8402c2dc2fdSStanimir Varbanov 		pl->profile = find_hfi_id(v4l2_pf, hevc_profiles, ARRAY_SIZE(hevc_profiles));
8412c2dc2fdSStanimir Varbanov 		pl->level = find_hfi_id(v4l2_lvl, hevc_levels, ARRAY_SIZE(hevc_levels));
8422c2dc2fdSStanimir Varbanov 		break;
8432c2dc2fdSStanimir Varbanov 	default:
8442c2dc2fdSStanimir Varbanov 		break;
8452c2dc2fdSStanimir Varbanov 	}
8462c2dc2fdSStanimir Varbanov }
8472c2dc2fdSStanimir Varbanov 
8482c2dc2fdSStanimir Varbanov int venus_helper_get_profile_level(struct venus_inst *inst, u32 *profile, u32 *level)
8492c2dc2fdSStanimir Varbanov {
8502c2dc2fdSStanimir Varbanov 	const u32 ptype = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT;
8512c2dc2fdSStanimir Varbanov 	union hfi_get_property hprop;
8522c2dc2fdSStanimir Varbanov 	int ret;
8532c2dc2fdSStanimir Varbanov 
8542c2dc2fdSStanimir Varbanov 	ret = hfi_session_get_property(inst, ptype, &hprop);
8552c2dc2fdSStanimir Varbanov 	if (ret)
8562c2dc2fdSStanimir Varbanov 		return ret;
8572c2dc2fdSStanimir Varbanov 
8582c2dc2fdSStanimir Varbanov 	v4l2_id_profile_level(inst->hfi_codec, &hprop.profile_level, profile, level);
8592c2dc2fdSStanimir Varbanov 
8602c2dc2fdSStanimir Varbanov 	return 0;
8612c2dc2fdSStanimir Varbanov }
8622c2dc2fdSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_profile_level);
8632c2dc2fdSStanimir Varbanov 
8642c2dc2fdSStanimir Varbanov int venus_helper_set_profile_level(struct venus_inst *inst, u32 profile, u32 level)
8652c2dc2fdSStanimir Varbanov {
8662c2dc2fdSStanimir Varbanov 	const u32 ptype = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT;
8672c2dc2fdSStanimir Varbanov 	struct hfi_profile_level pl;
8682c2dc2fdSStanimir Varbanov 
8692c2dc2fdSStanimir Varbanov 	hfi_id_profile_level(inst->hfi_codec, profile, level, &pl);
8702c2dc2fdSStanimir Varbanov 
8712c2dc2fdSStanimir Varbanov 	return hfi_session_set_property(inst, ptype, &pl);
8722c2dc2fdSStanimir Varbanov }
8732c2dc2fdSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_profile_level);
8742c2dc2fdSStanimir Varbanov 
875e1cb72deSStanimir Varbanov static u32 get_framesize_raw_nv12(u32 width, u32 height)
876e1cb72deSStanimir Varbanov {
877e1cb72deSStanimir Varbanov 	u32 y_stride, uv_stride, y_plane;
878e1cb72deSStanimir Varbanov 	u32 y_sclines, uv_sclines, uv_plane;
879e1cb72deSStanimir Varbanov 	u32 size;
880e1cb72deSStanimir Varbanov 
881e1cb72deSStanimir Varbanov 	y_stride = ALIGN(width, 128);
882e1cb72deSStanimir Varbanov 	uv_stride = ALIGN(width, 128);
883e1cb72deSStanimir Varbanov 	y_sclines = ALIGN(height, 32);
884e1cb72deSStanimir Varbanov 	uv_sclines = ALIGN(((height + 1) >> 1), 16);
885e1cb72deSStanimir Varbanov 
886e1cb72deSStanimir Varbanov 	y_plane = y_stride * y_sclines;
887e1cb72deSStanimir Varbanov 	uv_plane = uv_stride * uv_sclines + SZ_4K;
888e1cb72deSStanimir Varbanov 	size = y_plane + uv_plane + SZ_8K;
889e1cb72deSStanimir Varbanov 
890e1cb72deSStanimir Varbanov 	return ALIGN(size, SZ_4K);
891e1cb72deSStanimir Varbanov }
892e1cb72deSStanimir Varbanov 
893e1cb72deSStanimir Varbanov static u32 get_framesize_raw_nv12_ubwc(u32 width, u32 height)
894e1cb72deSStanimir Varbanov {
895e1cb72deSStanimir Varbanov 	u32 y_meta_stride, y_meta_plane;
896e1cb72deSStanimir Varbanov 	u32 y_stride, y_plane;
897e1cb72deSStanimir Varbanov 	u32 uv_meta_stride, uv_meta_plane;
898e1cb72deSStanimir Varbanov 	u32 uv_stride, uv_plane;
899e1cb72deSStanimir Varbanov 	u32 extradata = SZ_16K;
900e1cb72deSStanimir Varbanov 
901e1cb72deSStanimir Varbanov 	y_meta_stride = ALIGN(DIV_ROUND_UP(width, 32), 64);
902e1cb72deSStanimir Varbanov 	y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(height, 8), 16);
903e1cb72deSStanimir Varbanov 	y_meta_plane = ALIGN(y_meta_plane, SZ_4K);
904e1cb72deSStanimir Varbanov 
905e1cb72deSStanimir Varbanov 	y_stride = ALIGN(width, 128);
906e1cb72deSStanimir Varbanov 	y_plane = ALIGN(y_stride * ALIGN(height, 32), SZ_4K);
907e1cb72deSStanimir Varbanov 
908e1cb72deSStanimir Varbanov 	uv_meta_stride = ALIGN(DIV_ROUND_UP(width / 2, 16), 64);
909e1cb72deSStanimir Varbanov 	uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP(height / 2, 8), 16);
910e1cb72deSStanimir Varbanov 	uv_meta_plane = ALIGN(uv_meta_plane, SZ_4K);
911e1cb72deSStanimir Varbanov 
912e1cb72deSStanimir Varbanov 	uv_stride = ALIGN(width, 128);
913e1cb72deSStanimir Varbanov 	uv_plane = ALIGN(uv_stride * ALIGN(height / 2, 32), SZ_4K);
914e1cb72deSStanimir Varbanov 
915e1cb72deSStanimir Varbanov 	return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane +
916e1cb72deSStanimir Varbanov 		     max(extradata, y_stride * 48), SZ_4K);
917e1cb72deSStanimir Varbanov }
918e1cb72deSStanimir Varbanov 
919ab1eda44SAniket Masule static u32 get_framesize_raw_p010(u32 width, u32 height)
920ab1eda44SAniket Masule {
921ab1eda44SAniket Masule 	u32 y_plane, uv_plane, y_stride, uv_stride, y_sclines, uv_sclines;
922ab1eda44SAniket Masule 
923ab1eda44SAniket Masule 	y_stride = ALIGN(width * 2, 256);
924ab1eda44SAniket Masule 	uv_stride = ALIGN(width * 2, 256);
925ab1eda44SAniket Masule 	y_sclines = ALIGN(height, 32);
926ab1eda44SAniket Masule 	uv_sclines = ALIGN((height + 1) >> 1, 16);
927ab1eda44SAniket Masule 	y_plane = y_stride * y_sclines;
928ab1eda44SAniket Masule 	uv_plane = uv_stride * uv_sclines;
929ab1eda44SAniket Masule 
930ab1eda44SAniket Masule 	return ALIGN((y_plane + uv_plane), SZ_4K);
931ab1eda44SAniket Masule }
932ab1eda44SAniket Masule 
933ab1eda44SAniket Masule static u32 get_framesize_raw_p010_ubwc(u32 width, u32 height)
934ab1eda44SAniket Masule {
935ab1eda44SAniket Masule 	u32 y_stride, uv_stride, y_sclines, uv_sclines;
936ab1eda44SAniket Masule 	u32 y_ubwc_plane, uv_ubwc_plane;
937ab1eda44SAniket Masule 	u32 y_meta_stride, y_meta_scanlines;
938ab1eda44SAniket Masule 	u32 uv_meta_stride, uv_meta_scanlines;
939ab1eda44SAniket Masule 	u32 y_meta_plane, uv_meta_plane;
940ab1eda44SAniket Masule 	u32 size;
941ab1eda44SAniket Masule 
942ab1eda44SAniket Masule 	y_stride = ALIGN(width * 2, 256);
943ab1eda44SAniket Masule 	uv_stride = ALIGN(width * 2, 256);
944ab1eda44SAniket Masule 	y_sclines = ALIGN(height, 16);
945ab1eda44SAniket Masule 	uv_sclines = ALIGN((height + 1) >> 1, 16);
946ab1eda44SAniket Masule 
947ab1eda44SAniket Masule 	y_ubwc_plane = ALIGN(y_stride * y_sclines, SZ_4K);
948ab1eda44SAniket Masule 	uv_ubwc_plane = ALIGN(uv_stride * uv_sclines, SZ_4K);
949ab1eda44SAniket Masule 	y_meta_stride = ALIGN(DIV_ROUND_UP(width, 32), 64);
950ab1eda44SAniket Masule 	y_meta_scanlines = ALIGN(DIV_ROUND_UP(height, 4), 16);
951ab1eda44SAniket Masule 	y_meta_plane = ALIGN(y_meta_stride * y_meta_scanlines, SZ_4K);
952ab1eda44SAniket Masule 	uv_meta_stride = ALIGN(DIV_ROUND_UP((width + 1) >> 1, 16), 64);
953ab1eda44SAniket Masule 	uv_meta_scanlines = ALIGN(DIV_ROUND_UP((height + 1) >> 1, 4), 16);
954ab1eda44SAniket Masule 	uv_meta_plane = ALIGN(uv_meta_stride * uv_meta_scanlines, SZ_4K);
955ab1eda44SAniket Masule 
956ab1eda44SAniket Masule 	size = y_ubwc_plane + uv_ubwc_plane + y_meta_plane + uv_meta_plane;
957ab1eda44SAniket Masule 
958ab1eda44SAniket Masule 	return ALIGN(size, SZ_4K);
959ab1eda44SAniket Masule }
960ab1eda44SAniket Masule 
961ab1eda44SAniket Masule static u32 get_framesize_raw_yuv420_tp10_ubwc(u32 width, u32 height)
962ab1eda44SAniket Masule {
963ab1eda44SAniket Masule 	u32 y_stride, uv_stride, y_sclines, uv_sclines;
964ab1eda44SAniket Masule 	u32 y_ubwc_plane, uv_ubwc_plane;
965ab1eda44SAniket Masule 	u32 y_meta_stride, y_meta_scanlines;
966ab1eda44SAniket Masule 	u32 uv_meta_stride, uv_meta_scanlines;
967ab1eda44SAniket Masule 	u32 y_meta_plane, uv_meta_plane;
968ab1eda44SAniket Masule 	u32 extradata = SZ_16K;
969ab1eda44SAniket Masule 	u32 size;
970ab1eda44SAniket Masule 
971ab1eda44SAniket Masule 	y_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256);
972ab1eda44SAniket Masule 	uv_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256);
973ab1eda44SAniket Masule 	y_sclines = ALIGN(height, 16);
974ab1eda44SAniket Masule 	uv_sclines = ALIGN((height + 1) >> 1, 16);
975ab1eda44SAniket Masule 
976ab1eda44SAniket Masule 	y_ubwc_plane = ALIGN(y_stride * y_sclines, SZ_4K);
977ab1eda44SAniket Masule 	uv_ubwc_plane = ALIGN(uv_stride * uv_sclines, SZ_4K);
978ab1eda44SAniket Masule 	y_meta_stride = ALIGN(DIV_ROUND_UP(width, 48), 64);
979ab1eda44SAniket Masule 	y_meta_scanlines = ALIGN(DIV_ROUND_UP(height, 4), 16);
980ab1eda44SAniket Masule 	y_meta_plane = ALIGN(y_meta_stride * y_meta_scanlines, SZ_4K);
981ab1eda44SAniket Masule 	uv_meta_stride = ALIGN(DIV_ROUND_UP((width + 1) >> 1, 24), 64);
982ab1eda44SAniket Masule 	uv_meta_scanlines = ALIGN(DIV_ROUND_UP((height + 1) >> 1, 4), 16);
983ab1eda44SAniket Masule 	uv_meta_plane = ALIGN(uv_meta_stride * uv_meta_scanlines, SZ_4K);
984ab1eda44SAniket Masule 
985ab1eda44SAniket Masule 	size = y_ubwc_plane + uv_ubwc_plane + y_meta_plane + uv_meta_plane;
986ab1eda44SAniket Masule 	size += max(extradata + SZ_8K, y_stride * 48);
987ab1eda44SAniket Masule 
988ab1eda44SAniket Masule 	return ALIGN(size, SZ_4K);
989ab1eda44SAniket Masule }
990ab1eda44SAniket Masule 
991e1cb72deSStanimir Varbanov u32 venus_helper_get_framesz_raw(u32 hfi_fmt, u32 width, u32 height)
992e1cb72deSStanimir Varbanov {
993e1cb72deSStanimir Varbanov 	switch (hfi_fmt) {
994e1cb72deSStanimir Varbanov 	case HFI_COLOR_FORMAT_NV12:
995e1cb72deSStanimir Varbanov 	case HFI_COLOR_FORMAT_NV21:
996e1cb72deSStanimir Varbanov 		return get_framesize_raw_nv12(width, height);
997e1cb72deSStanimir Varbanov 	case HFI_COLOR_FORMAT_NV12_UBWC:
998e1cb72deSStanimir Varbanov 		return get_framesize_raw_nv12_ubwc(width, height);
999ab1eda44SAniket Masule 	case HFI_COLOR_FORMAT_P010:
1000ab1eda44SAniket Masule 		return get_framesize_raw_p010(width, height);
1001ab1eda44SAniket Masule 	case HFI_COLOR_FORMAT_P010_UBWC:
1002ab1eda44SAniket Masule 		return get_framesize_raw_p010_ubwc(width, height);
1003ab1eda44SAniket Masule 	case HFI_COLOR_FORMAT_YUV420_TP10_UBWC:
1004ab1eda44SAniket Masule 		return get_framesize_raw_yuv420_tp10_ubwc(width, height);
1005e1cb72deSStanimir Varbanov 	default:
1006e1cb72deSStanimir Varbanov 		return 0;
1007e1cb72deSStanimir Varbanov 	}
1008e1cb72deSStanimir Varbanov }
1009e1cb72deSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_framesz_raw);
1010e1cb72deSStanimir Varbanov 
1011e1cb72deSStanimir Varbanov u32 venus_helper_get_framesz(u32 v4l2_fmt, u32 width, u32 height)
1012e1cb72deSStanimir Varbanov {
1013e1cb72deSStanimir Varbanov 	u32 hfi_fmt, sz;
1014e1cb72deSStanimir Varbanov 	bool compressed;
1015e1cb72deSStanimir Varbanov 
1016e1cb72deSStanimir Varbanov 	switch (v4l2_fmt) {
1017e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_MPEG:
1018e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_H264:
1019e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_H264_NO_SC:
1020e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_H264_MVC:
1021e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_H263:
1022e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_MPEG1:
1023e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_MPEG2:
1024e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_MPEG4:
1025e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_XVID:
1026e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_VC1_ANNEX_G:
1027e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_VC1_ANNEX_L:
1028e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_VP8:
1029e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_VP9:
1030e1cb72deSStanimir Varbanov 	case V4L2_PIX_FMT_HEVC:
1031e1cb72deSStanimir Varbanov 		compressed = true;
1032e1cb72deSStanimir Varbanov 		break;
1033e1cb72deSStanimir Varbanov 	default:
1034e1cb72deSStanimir Varbanov 		compressed = false;
1035e1cb72deSStanimir Varbanov 		break;
1036e1cb72deSStanimir Varbanov 	}
1037e1cb72deSStanimir Varbanov 
1038e1cb72deSStanimir Varbanov 	if (compressed) {
1039e1cb72deSStanimir Varbanov 		sz = ALIGN(height, 32) * ALIGN(width, 32) * 3 / 2 / 2;
1040ddd1fc49SStanimir Varbanov 		if (width < 1280 || height < 720)
1041ddd1fc49SStanimir Varbanov 			sz *= 8;
1042e1cb72deSStanimir Varbanov 		return ALIGN(sz, SZ_4K);
1043e1cb72deSStanimir Varbanov 	}
1044e1cb72deSStanimir Varbanov 
1045e1cb72deSStanimir Varbanov 	hfi_fmt = to_hfi_raw_fmt(v4l2_fmt);
1046e1cb72deSStanimir Varbanov 	if (!hfi_fmt)
1047e1cb72deSStanimir Varbanov 		return 0;
1048e1cb72deSStanimir Varbanov 
1049e1cb72deSStanimir Varbanov 	return venus_helper_get_framesz_raw(hfi_fmt, width, height);
1050e1cb72deSStanimir Varbanov }
1051e1cb72deSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_framesz);
1052e1cb72deSStanimir Varbanov 
1053af2c3834SStanimir Varbanov int venus_helper_set_input_resolution(struct venus_inst *inst,
1054af2c3834SStanimir Varbanov 				      unsigned int width, unsigned int height)
1055af2c3834SStanimir Varbanov {
1056af2c3834SStanimir Varbanov 	u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE;
1057af2c3834SStanimir Varbanov 	struct hfi_framesize fs;
1058af2c3834SStanimir Varbanov 
1059af2c3834SStanimir Varbanov 	fs.buffer_type = HFI_BUFFER_INPUT;
1060af2c3834SStanimir Varbanov 	fs.width = width;
1061af2c3834SStanimir Varbanov 	fs.height = height;
1062af2c3834SStanimir Varbanov 
1063af2c3834SStanimir Varbanov 	return hfi_session_set_property(inst, ptype, &fs);
1064af2c3834SStanimir Varbanov }
1065af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_input_resolution);
1066af2c3834SStanimir Varbanov 
1067af2c3834SStanimir Varbanov int venus_helper_set_output_resolution(struct venus_inst *inst,
1068404054e1SStanimir Varbanov 				       unsigned int width, unsigned int height,
1069404054e1SStanimir Varbanov 				       u32 buftype)
1070af2c3834SStanimir Varbanov {
1071af2c3834SStanimir Varbanov 	u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE;
1072af2c3834SStanimir Varbanov 	struct hfi_framesize fs;
1073af2c3834SStanimir Varbanov 
1074404054e1SStanimir Varbanov 	fs.buffer_type = buftype;
1075af2c3834SStanimir Varbanov 	fs.width = width;
1076af2c3834SStanimir Varbanov 	fs.height = height;
1077af2c3834SStanimir Varbanov 
1078af2c3834SStanimir Varbanov 	return hfi_session_set_property(inst, ptype, &fs);
1079af2c3834SStanimir Varbanov }
1080af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_output_resolution);
1081af2c3834SStanimir Varbanov 
108201165b84SStanimir Varbanov int venus_helper_set_work_mode(struct venus_inst *inst, u32 mode)
108301165b84SStanimir Varbanov {
108401165b84SStanimir Varbanov 	const u32 ptype = HFI_PROPERTY_PARAM_WORK_MODE;
108501165b84SStanimir Varbanov 	struct hfi_video_work_mode wm;
108601165b84SStanimir Varbanov 
108701165b84SStanimir Varbanov 	if (!IS_V4(inst->core))
108801165b84SStanimir Varbanov 		return 0;
108901165b84SStanimir Varbanov 
109001165b84SStanimir Varbanov 	wm.video_work_mode = mode;
109101165b84SStanimir Varbanov 
109201165b84SStanimir Varbanov 	return hfi_session_set_property(inst, ptype, &wm);
109301165b84SStanimir Varbanov }
109401165b84SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_work_mode);
109501165b84SStanimir Varbanov 
1096af2c3834SStanimir Varbanov int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs,
10971eb04b2eSStanimir Varbanov 			      unsigned int output_bufs,
10981eb04b2eSStanimir Varbanov 			      unsigned int output2_bufs)
1099af2c3834SStanimir Varbanov {
1100af2c3834SStanimir Varbanov 	u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL;
1101af2c3834SStanimir Varbanov 	struct hfi_buffer_count_actual buf_count;
1102af2c3834SStanimir Varbanov 	int ret;
1103af2c3834SStanimir Varbanov 
1104af2c3834SStanimir Varbanov 	buf_count.type = HFI_BUFFER_INPUT;
1105af2c3834SStanimir Varbanov 	buf_count.count_actual = input_bufs;
1106af2c3834SStanimir Varbanov 
1107af2c3834SStanimir Varbanov 	ret = hfi_session_set_property(inst, ptype, &buf_count);
1108af2c3834SStanimir Varbanov 	if (ret)
1109af2c3834SStanimir Varbanov 		return ret;
1110af2c3834SStanimir Varbanov 
1111af2c3834SStanimir Varbanov 	buf_count.type = HFI_BUFFER_OUTPUT;
1112af2c3834SStanimir Varbanov 	buf_count.count_actual = output_bufs;
1113af2c3834SStanimir Varbanov 
11141eb04b2eSStanimir Varbanov 	ret = hfi_session_set_property(inst, ptype, &buf_count);
11151eb04b2eSStanimir Varbanov 	if (ret)
11161eb04b2eSStanimir Varbanov 		return ret;
11171eb04b2eSStanimir Varbanov 
11181eb04b2eSStanimir Varbanov 	if (output2_bufs) {
11191eb04b2eSStanimir Varbanov 		buf_count.type = HFI_BUFFER_OUTPUT2;
11201eb04b2eSStanimir Varbanov 		buf_count.count_actual = output2_bufs;
11211eb04b2eSStanimir Varbanov 
11221eb04b2eSStanimir Varbanov 		ret = hfi_session_set_property(inst, ptype, &buf_count);
11231eb04b2eSStanimir Varbanov 	}
11241eb04b2eSStanimir Varbanov 
11251eb04b2eSStanimir Varbanov 	return ret;
1126af2c3834SStanimir Varbanov }
1127af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_num_bufs);
1128af2c3834SStanimir Varbanov 
1129ab97a3fbSStanimir Varbanov int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format,
1130ab97a3fbSStanimir Varbanov 				u32 buftype)
1131ab97a3fbSStanimir Varbanov {
1132ab97a3fbSStanimir Varbanov 	const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT;
1133ab97a3fbSStanimir Varbanov 	struct hfi_uncompressed_format_select fmt;
1134ab97a3fbSStanimir Varbanov 
1135ab97a3fbSStanimir Varbanov 	fmt.buffer_type = buftype;
1136ab97a3fbSStanimir Varbanov 	fmt.format = hfi_format;
1137ab97a3fbSStanimir Varbanov 
1138ab97a3fbSStanimir Varbanov 	return hfi_session_set_property(inst, ptype, &fmt);
1139ab97a3fbSStanimir Varbanov }
1140ab97a3fbSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_raw_format);
1141ab97a3fbSStanimir Varbanov 
1142af2c3834SStanimir Varbanov int venus_helper_set_color_format(struct venus_inst *inst, u32 pixfmt)
1143af2c3834SStanimir Varbanov {
1144ab97a3fbSStanimir Varbanov 	u32 hfi_format, buftype;
1145af2c3834SStanimir Varbanov 
1146af2c3834SStanimir Varbanov 	if (inst->session_type == VIDC_SESSION_TYPE_DEC)
1147ab97a3fbSStanimir Varbanov 		buftype = HFI_BUFFER_OUTPUT;
1148af2c3834SStanimir Varbanov 	else if (inst->session_type == VIDC_SESSION_TYPE_ENC)
1149ab97a3fbSStanimir Varbanov 		buftype = HFI_BUFFER_INPUT;
1150af2c3834SStanimir Varbanov 	else
1151af2c3834SStanimir Varbanov 		return -EINVAL;
1152af2c3834SStanimir Varbanov 
1153ab97a3fbSStanimir Varbanov 	hfi_format = to_hfi_raw_fmt(pixfmt);
1154ab97a3fbSStanimir Varbanov 	if (!hfi_format)
1155af2c3834SStanimir Varbanov 		return -EINVAL;
1156af2c3834SStanimir Varbanov 
1157ab97a3fbSStanimir Varbanov 	return venus_helper_set_raw_format(inst, hfi_format, buftype);
1158af2c3834SStanimir Varbanov }
1159af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_color_format);
1160af2c3834SStanimir Varbanov 
1161f012b23dSStanimir Varbanov int venus_helper_set_multistream(struct venus_inst *inst, bool out_en,
1162f012b23dSStanimir Varbanov 				 bool out2_en)
1163f012b23dSStanimir Varbanov {
1164f012b23dSStanimir Varbanov 	struct hfi_multi_stream multi = {0};
1165f012b23dSStanimir Varbanov 	u32 ptype = HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM;
1166f012b23dSStanimir Varbanov 	int ret;
1167f012b23dSStanimir Varbanov 
1168f012b23dSStanimir Varbanov 	multi.buffer_type = HFI_BUFFER_OUTPUT;
1169f012b23dSStanimir Varbanov 	multi.enable = out_en;
1170f012b23dSStanimir Varbanov 
1171f012b23dSStanimir Varbanov 	ret = hfi_session_set_property(inst, ptype, &multi);
1172f012b23dSStanimir Varbanov 	if (ret)
1173f012b23dSStanimir Varbanov 		return ret;
1174f012b23dSStanimir Varbanov 
1175f012b23dSStanimir Varbanov 	multi.buffer_type = HFI_BUFFER_OUTPUT2;
1176f012b23dSStanimir Varbanov 	multi.enable = out2_en;
1177f012b23dSStanimir Varbanov 
1178f012b23dSStanimir Varbanov 	return hfi_session_set_property(inst, ptype, &multi);
1179f012b23dSStanimir Varbanov }
1180f012b23dSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_multistream);
1181f012b23dSStanimir Varbanov 
11822b0a8517SStanimir Varbanov int venus_helper_set_dyn_bufmode(struct venus_inst *inst)
11832b0a8517SStanimir Varbanov {
11842b0a8517SStanimir Varbanov 	const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE;
11852b0a8517SStanimir Varbanov 	struct hfi_buffer_alloc_mode mode;
11862b0a8517SStanimir Varbanov 	int ret;
11872b0a8517SStanimir Varbanov 
11882b0a8517SStanimir Varbanov 	if (!is_dynamic_bufmode(inst))
11892b0a8517SStanimir Varbanov 		return 0;
11902b0a8517SStanimir Varbanov 
11912b0a8517SStanimir Varbanov 	mode.type = HFI_BUFFER_OUTPUT;
11922b0a8517SStanimir Varbanov 	mode.mode = HFI_BUFFER_MODE_DYNAMIC;
11932b0a8517SStanimir Varbanov 
11942b0a8517SStanimir Varbanov 	ret = hfi_session_set_property(inst, ptype, &mode);
11952b0a8517SStanimir Varbanov 	if (ret)
11962b0a8517SStanimir Varbanov 		return ret;
11972b0a8517SStanimir Varbanov 
11982b0a8517SStanimir Varbanov 	mode.type = HFI_BUFFER_OUTPUT2;
11992b0a8517SStanimir Varbanov 
12002b0a8517SStanimir Varbanov 	return hfi_session_set_property(inst, ptype, &mode);
12012b0a8517SStanimir Varbanov }
12022b0a8517SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_dyn_bufmode);
12032b0a8517SStanimir Varbanov 
1204d4a5b0a6SStanimir Varbanov int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype)
1205d4a5b0a6SStanimir Varbanov {
1206d4a5b0a6SStanimir Varbanov 	const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL;
1207d4a5b0a6SStanimir Varbanov 	struct hfi_buffer_size_actual bufsz;
1208d4a5b0a6SStanimir Varbanov 
1209d4a5b0a6SStanimir Varbanov 	bufsz.type = buftype;
1210d4a5b0a6SStanimir Varbanov 	bufsz.size = bufsize;
1211d4a5b0a6SStanimir Varbanov 
1212d4a5b0a6SStanimir Varbanov 	return hfi_session_set_property(inst, ptype, &bufsz);
1213d4a5b0a6SStanimir Varbanov }
1214d4a5b0a6SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_bufsize);
1215d4a5b0a6SStanimir Varbanov 
1216130c0117SStanimir Varbanov unsigned int venus_helper_get_opb_size(struct venus_inst *inst)
1217130c0117SStanimir Varbanov {
1218130c0117SStanimir Varbanov 	/* the encoder has only one output */
1219130c0117SStanimir Varbanov 	if (inst->session_type == VIDC_SESSION_TYPE_ENC)
1220130c0117SStanimir Varbanov 		return inst->output_buf_size;
1221130c0117SStanimir Varbanov 
1222130c0117SStanimir Varbanov 	if (inst->opb_buftype == HFI_BUFFER_OUTPUT)
1223130c0117SStanimir Varbanov 		return inst->output_buf_size;
1224130c0117SStanimir Varbanov 	else if (inst->opb_buftype == HFI_BUFFER_OUTPUT2)
1225130c0117SStanimir Varbanov 		return inst->output2_buf_size;
1226130c0117SStanimir Varbanov 
1227130c0117SStanimir Varbanov 	return 0;
1228130c0117SStanimir Varbanov }
1229130c0117SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_opb_size);
1230130c0117SStanimir Varbanov 
1231af2c3834SStanimir Varbanov static void delayed_process_buf_func(struct work_struct *work)
1232af2c3834SStanimir Varbanov {
1233af2c3834SStanimir Varbanov 	struct venus_buffer *buf, *n;
1234af2c3834SStanimir Varbanov 	struct venus_inst *inst;
1235af2c3834SStanimir Varbanov 	int ret;
1236af2c3834SStanimir Varbanov 
1237af2c3834SStanimir Varbanov 	inst = container_of(work, struct venus_inst, delayed_process_work);
1238af2c3834SStanimir Varbanov 
1239af2c3834SStanimir Varbanov 	mutex_lock(&inst->lock);
1240af2c3834SStanimir Varbanov 
1241af2c3834SStanimir Varbanov 	if (!(inst->streamon_out & inst->streamon_cap))
1242af2c3834SStanimir Varbanov 		goto unlock;
1243af2c3834SStanimir Varbanov 
1244af2c3834SStanimir Varbanov 	list_for_each_entry_safe(buf, n, &inst->delayed_process, ref_list) {
1245af2c3834SStanimir Varbanov 		if (buf->flags & HFI_BUFFERFLAG_READONLY)
1246af2c3834SStanimir Varbanov 			continue;
1247af2c3834SStanimir Varbanov 
1248af2c3834SStanimir Varbanov 		ret = session_process_buf(inst, &buf->vb);
1249af2c3834SStanimir Varbanov 		if (ret)
1250af2c3834SStanimir Varbanov 			return_buf_error(inst, &buf->vb);
1251af2c3834SStanimir Varbanov 
1252af2c3834SStanimir Varbanov 		list_del_init(&buf->ref_list);
1253af2c3834SStanimir Varbanov 	}
1254af2c3834SStanimir Varbanov unlock:
1255af2c3834SStanimir Varbanov 	mutex_unlock(&inst->lock);
1256af2c3834SStanimir Varbanov }
1257af2c3834SStanimir Varbanov 
1258af2c3834SStanimir Varbanov void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx)
1259af2c3834SStanimir Varbanov {
1260af2c3834SStanimir Varbanov 	struct venus_buffer *buf;
1261af2c3834SStanimir Varbanov 
1262af2c3834SStanimir Varbanov 	list_for_each_entry(buf, &inst->registeredbufs, reg_list) {
1263af2c3834SStanimir Varbanov 		if (buf->vb.vb2_buf.index == idx) {
1264af2c3834SStanimir Varbanov 			buf->flags &= ~HFI_BUFFERFLAG_READONLY;
1265af2c3834SStanimir Varbanov 			schedule_work(&inst->delayed_process_work);
1266af2c3834SStanimir Varbanov 			break;
1267af2c3834SStanimir Varbanov 		}
1268af2c3834SStanimir Varbanov 	}
1269af2c3834SStanimir Varbanov }
1270af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_release_buf_ref);
1271af2c3834SStanimir Varbanov 
1272af2c3834SStanimir Varbanov void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf)
1273af2c3834SStanimir Varbanov {
1274af2c3834SStanimir Varbanov 	struct venus_buffer *buf = to_venus_buffer(vbuf);
1275af2c3834SStanimir Varbanov 
1276af2c3834SStanimir Varbanov 	buf->flags |= HFI_BUFFERFLAG_READONLY;
1277af2c3834SStanimir Varbanov }
1278af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_acquire_buf_ref);
1279af2c3834SStanimir Varbanov 
1280af2c3834SStanimir Varbanov static int is_buf_refed(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)
1281af2c3834SStanimir Varbanov {
1282af2c3834SStanimir Varbanov 	struct venus_buffer *buf = to_venus_buffer(vbuf);
1283af2c3834SStanimir Varbanov 
1284af2c3834SStanimir Varbanov 	if (buf->flags & HFI_BUFFERFLAG_READONLY) {
1285af2c3834SStanimir Varbanov 		list_add_tail(&buf->ref_list, &inst->delayed_process);
1286af2c3834SStanimir Varbanov 		schedule_work(&inst->delayed_process_work);
1287af2c3834SStanimir Varbanov 		return 1;
1288af2c3834SStanimir Varbanov 	}
1289af2c3834SStanimir Varbanov 
1290af2c3834SStanimir Varbanov 	return 0;
1291af2c3834SStanimir Varbanov }
1292af2c3834SStanimir Varbanov 
1293af2c3834SStanimir Varbanov struct vb2_v4l2_buffer *
1294af2c3834SStanimir Varbanov venus_helper_find_buf(struct venus_inst *inst, unsigned int type, u32 idx)
1295af2c3834SStanimir Varbanov {
1296af2c3834SStanimir Varbanov 	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
1297af2c3834SStanimir Varbanov 
1298af2c3834SStanimir Varbanov 	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1299af2c3834SStanimir Varbanov 		return v4l2_m2m_src_buf_remove_by_idx(m2m_ctx, idx);
1300af2c3834SStanimir Varbanov 	else
1301af2c3834SStanimir Varbanov 		return v4l2_m2m_dst_buf_remove_by_idx(m2m_ctx, idx);
1302af2c3834SStanimir Varbanov }
1303af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_find_buf);
1304af2c3834SStanimir Varbanov 
1305af2c3834SStanimir Varbanov int venus_helper_vb2_buf_init(struct vb2_buffer *vb)
1306af2c3834SStanimir Varbanov {
1307af2c3834SStanimir Varbanov 	struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1308af2c3834SStanimir Varbanov 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1309af2c3834SStanimir Varbanov 	struct venus_buffer *buf = to_venus_buffer(vbuf);
1310af2c3834SStanimir Varbanov 
1311af2c3834SStanimir Varbanov 	buf->size = vb2_plane_size(vb, 0);
1312cc82fd69SAlexandre Courbot 	buf->dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
1313af2c3834SStanimir Varbanov 
1314af2c3834SStanimir Varbanov 	if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1315af2c3834SStanimir Varbanov 		list_add_tail(&buf->reg_list, &inst->registeredbufs);
1316af2c3834SStanimir Varbanov 
1317af2c3834SStanimir Varbanov 	return 0;
1318af2c3834SStanimir Varbanov }
1319af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_init);
1320af2c3834SStanimir Varbanov 
1321af2c3834SStanimir Varbanov int venus_helper_vb2_buf_prepare(struct vb2_buffer *vb)
1322af2c3834SStanimir Varbanov {
1323af2c3834SStanimir Varbanov 	struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1324f012b23dSStanimir Varbanov 	unsigned int out_buf_size = venus_helper_get_opb_size(inst);
132505979046SStanimir Varbanov 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
132605979046SStanimir Varbanov 
132705979046SStanimir Varbanov 	if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
132805979046SStanimir Varbanov 		if (vbuf->field == V4L2_FIELD_ANY)
132905979046SStanimir Varbanov 			vbuf->field = V4L2_FIELD_NONE;
133005979046SStanimir Varbanov 		if (vbuf->field != V4L2_FIELD_NONE) {
133105979046SStanimir Varbanov 			dev_err(inst->core->dev, "%s field isn't supported\n",
133205979046SStanimir Varbanov 				__func__);
133305979046SStanimir Varbanov 			return -EINVAL;
133405979046SStanimir Varbanov 		}
133505979046SStanimir Varbanov 	}
1336af2c3834SStanimir Varbanov 
1337af2c3834SStanimir Varbanov 	if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
1338f012b23dSStanimir Varbanov 	    vb2_plane_size(vb, 0) < out_buf_size)
1339af2c3834SStanimir Varbanov 		return -EINVAL;
1340af2c3834SStanimir Varbanov 	if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
1341af2c3834SStanimir Varbanov 	    vb2_plane_size(vb, 0) < inst->input_buf_size)
1342af2c3834SStanimir Varbanov 		return -EINVAL;
1343af2c3834SStanimir Varbanov 
1344af2c3834SStanimir Varbanov 	return 0;
1345af2c3834SStanimir Varbanov }
1346af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_prepare);
1347af2c3834SStanimir Varbanov 
1348fd1ee315SStanimir Varbanov static void cache_payload(struct venus_inst *inst, struct vb2_buffer *vb)
1349fd1ee315SStanimir Varbanov {
1350fd1ee315SStanimir Varbanov 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1351fd1ee315SStanimir Varbanov 	unsigned int idx = vbuf->vb2_buf.index;
1352fd1ee315SStanimir Varbanov 
1353fd1ee315SStanimir Varbanov 	if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1354fd1ee315SStanimir Varbanov 		inst->payloads[idx] = vb2_get_plane_payload(vb, 0);
1355fd1ee315SStanimir Varbanov }
1356fd1ee315SStanimir Varbanov 
1357af2c3834SStanimir Varbanov void venus_helper_vb2_buf_queue(struct vb2_buffer *vb)
1358af2c3834SStanimir Varbanov {
1359af2c3834SStanimir Varbanov 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1360af2c3834SStanimir Varbanov 	struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1361af2c3834SStanimir Varbanov 	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
1362af2c3834SStanimir Varbanov 	int ret;
1363af2c3834SStanimir Varbanov 
1364af2c3834SStanimir Varbanov 	v4l2_m2m_buf_queue(m2m_ctx, vbuf);
1365af2c3834SStanimir Varbanov 
1366acf8a57dSStanimir Varbanov 	/* Skip processing queued capture buffers after LAST flag */
1367acf8a57dSStanimir Varbanov 	if (inst->session_type == VIDC_SESSION_TYPE_DEC &&
1368acf8a57dSStanimir Varbanov 	    V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) &&
1369acf8a57dSStanimir Varbanov 	    inst->codec_state == VENUS_DEC_STATE_DRC)
137021560ddfSStanimir Varbanov 		return;
1371acf8a57dSStanimir Varbanov 
1372fd1ee315SStanimir Varbanov 	cache_payload(inst, vb);
1373fd1ee315SStanimir Varbanov 
1374beac8290SStanimir Varbanov 	if (inst->session_type == VIDC_SESSION_TYPE_ENC &&
1375beac8290SStanimir Varbanov 	    !(inst->streamon_out && inst->streamon_cap))
137621560ddfSStanimir Varbanov 		return;
1377af2c3834SStanimir Varbanov 
1378beac8290SStanimir Varbanov 	if (vb2_start_streaming_called(vb->vb2_queue)) {
1379af2c3834SStanimir Varbanov 		ret = is_buf_refed(inst, vbuf);
1380af2c3834SStanimir Varbanov 		if (ret)
138121560ddfSStanimir Varbanov 			return;
1382af2c3834SStanimir Varbanov 
1383af2c3834SStanimir Varbanov 		ret = session_process_buf(inst, vbuf);
1384af2c3834SStanimir Varbanov 		if (ret)
1385af2c3834SStanimir Varbanov 			return_buf_error(inst, vbuf);
1386beac8290SStanimir Varbanov 	}
1387af2c3834SStanimir Varbanov }
1388af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_queue);
1389af2c3834SStanimir Varbanov 
13900febf923SStanimir Varbanov void venus_helper_buffers_done(struct venus_inst *inst, unsigned int type,
1391af2c3834SStanimir Varbanov 			       enum vb2_buffer_state state)
1392af2c3834SStanimir Varbanov {
1393af2c3834SStanimir Varbanov 	struct vb2_v4l2_buffer *buf;
1394af2c3834SStanimir Varbanov 
13950febf923SStanimir Varbanov 	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1396af2c3834SStanimir Varbanov 		while ((buf = v4l2_m2m_src_buf_remove(inst->m2m_ctx)))
1397af2c3834SStanimir Varbanov 			v4l2_m2m_buf_done(buf, state);
13980febf923SStanimir Varbanov 	} else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1399af2c3834SStanimir Varbanov 		while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx)))
1400af2c3834SStanimir Varbanov 			v4l2_m2m_buf_done(buf, state);
1401af2c3834SStanimir Varbanov 	}
14020febf923SStanimir Varbanov }
1403af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_buffers_done);
1404af2c3834SStanimir Varbanov 
1405af2c3834SStanimir Varbanov void venus_helper_vb2_stop_streaming(struct vb2_queue *q)
1406af2c3834SStanimir Varbanov {
1407af2c3834SStanimir Varbanov 	struct venus_inst *inst = vb2_get_drv_priv(q);
1408af2c3834SStanimir Varbanov 	struct venus_core *core = inst->core;
1409af2c3834SStanimir Varbanov 	int ret;
1410af2c3834SStanimir Varbanov 
1411af2c3834SStanimir Varbanov 	mutex_lock(&inst->lock);
1412af2c3834SStanimir Varbanov 
1413af2c3834SStanimir Varbanov 	if (inst->streamon_out & inst->streamon_cap) {
1414af2c3834SStanimir Varbanov 		ret = hfi_session_stop(inst);
1415af2c3834SStanimir Varbanov 		ret |= hfi_session_unload_res(inst);
14161e485ee5SStanimir Varbanov 		ret |= venus_helper_unregister_bufs(inst);
14171e485ee5SStanimir Varbanov 		ret |= venus_helper_intbufs_free(inst);
1418af2c3834SStanimir Varbanov 		ret |= hfi_session_deinit(inst);
1419af2c3834SStanimir Varbanov 
1420af2c3834SStanimir Varbanov 		if (inst->session_error || core->sys_error)
1421af2c3834SStanimir Varbanov 			ret = -EIO;
1422af2c3834SStanimir Varbanov 
1423af2c3834SStanimir Varbanov 		if (ret)
1424af2c3834SStanimir Varbanov 			hfi_session_abort(inst);
1425af2c3834SStanimir Varbanov 
1426f012b23dSStanimir Varbanov 		venus_helper_free_dpb_bufs(inst);
1427f012b23dSStanimir Varbanov 
14287482a983SStanimir Varbanov 		venus_pm_load_scale(inst);
1429bbd770aeSStanimir Varbanov 		INIT_LIST_HEAD(&inst->registeredbufs);
1430af2c3834SStanimir Varbanov 	}
1431af2c3834SStanimir Varbanov 
14320febf923SStanimir Varbanov 	venus_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
14330febf923SStanimir Varbanov 				  VB2_BUF_STATE_ERROR);
14340febf923SStanimir Varbanov 	venus_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
14350febf923SStanimir Varbanov 				  VB2_BUF_STATE_ERROR);
1436af2c3834SStanimir Varbanov 
1437af2c3834SStanimir Varbanov 	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1438af2c3834SStanimir Varbanov 		inst->streamon_out = 0;
1439af2c3834SStanimir Varbanov 	else
1440af2c3834SStanimir Varbanov 		inst->streamon_cap = 0;
1441af2c3834SStanimir Varbanov 
14424ebf9693SAniket Masule 	venus_pm_release_core(inst);
14434ebf9693SAniket Masule 
1444af2c3834SStanimir Varbanov 	mutex_unlock(&inst->lock);
1445af2c3834SStanimir Varbanov }
1446af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_vb2_stop_streaming);
1447af2c3834SStanimir Varbanov 
144814ea00d6SStanimir Varbanov int venus_helper_process_initial_cap_bufs(struct venus_inst *inst)
144914ea00d6SStanimir Varbanov {
145014ea00d6SStanimir Varbanov 	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
145114ea00d6SStanimir Varbanov 	struct v4l2_m2m_buffer *buf, *n;
145214ea00d6SStanimir Varbanov 	int ret;
145314ea00d6SStanimir Varbanov 
145414ea00d6SStanimir Varbanov 	v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) {
145514ea00d6SStanimir Varbanov 		ret = session_process_buf(inst, &buf->vb);
145614ea00d6SStanimir Varbanov 		if (ret) {
145714ea00d6SStanimir Varbanov 			return_buf_error(inst, &buf->vb);
145814ea00d6SStanimir Varbanov 			return ret;
145914ea00d6SStanimir Varbanov 		}
146014ea00d6SStanimir Varbanov 	}
146114ea00d6SStanimir Varbanov 
146214ea00d6SStanimir Varbanov 	return 0;
146314ea00d6SStanimir Varbanov }
146414ea00d6SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_process_initial_cap_bufs);
146514ea00d6SStanimir Varbanov 
146614ea00d6SStanimir Varbanov int venus_helper_process_initial_out_bufs(struct venus_inst *inst)
146714ea00d6SStanimir Varbanov {
146814ea00d6SStanimir Varbanov 	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
146914ea00d6SStanimir Varbanov 	struct v4l2_m2m_buffer *buf, *n;
147014ea00d6SStanimir Varbanov 	int ret;
147114ea00d6SStanimir Varbanov 
147214ea00d6SStanimir Varbanov 	v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) {
147314ea00d6SStanimir Varbanov 		ret = session_process_buf(inst, &buf->vb);
147414ea00d6SStanimir Varbanov 		if (ret) {
147514ea00d6SStanimir Varbanov 			return_buf_error(inst, &buf->vb);
147614ea00d6SStanimir Varbanov 			return ret;
147714ea00d6SStanimir Varbanov 		}
147814ea00d6SStanimir Varbanov 	}
147914ea00d6SStanimir Varbanov 
148014ea00d6SStanimir Varbanov 	return 0;
148114ea00d6SStanimir Varbanov }
148214ea00d6SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_process_initial_out_bufs);
148314ea00d6SStanimir Varbanov 
1484af2c3834SStanimir Varbanov int venus_helper_vb2_start_streaming(struct venus_inst *inst)
1485af2c3834SStanimir Varbanov {
1486af2c3834SStanimir Varbanov 	int ret;
1487af2c3834SStanimir Varbanov 
14881e485ee5SStanimir Varbanov 	ret = venus_helper_intbufs_alloc(inst);
1489af2c3834SStanimir Varbanov 	if (ret)
1490af2c3834SStanimir Varbanov 		return ret;
1491af2c3834SStanimir Varbanov 
1492af2c3834SStanimir Varbanov 	ret = session_register_bufs(inst);
1493af2c3834SStanimir Varbanov 	if (ret)
1494af2c3834SStanimir Varbanov 		goto err_bufs_free;
1495af2c3834SStanimir Varbanov 
14967482a983SStanimir Varbanov 	venus_pm_load_scale(inst);
1497af2c3834SStanimir Varbanov 
1498af2c3834SStanimir Varbanov 	ret = hfi_session_load_res(inst);
1499af2c3834SStanimir Varbanov 	if (ret)
1500af2c3834SStanimir Varbanov 		goto err_unreg_bufs;
1501af2c3834SStanimir Varbanov 
1502af2c3834SStanimir Varbanov 	ret = hfi_session_start(inst);
1503af2c3834SStanimir Varbanov 	if (ret)
1504af2c3834SStanimir Varbanov 		goto err_unload_res;
1505af2c3834SStanimir Varbanov 
1506af2c3834SStanimir Varbanov 	return 0;
1507af2c3834SStanimir Varbanov 
1508af2c3834SStanimir Varbanov err_unload_res:
1509af2c3834SStanimir Varbanov 	hfi_session_unload_res(inst);
1510af2c3834SStanimir Varbanov err_unreg_bufs:
15111e485ee5SStanimir Varbanov 	venus_helper_unregister_bufs(inst);
1512af2c3834SStanimir Varbanov err_bufs_free:
15131e485ee5SStanimir Varbanov 	venus_helper_intbufs_free(inst);
1514af2c3834SStanimir Varbanov 	return ret;
1515af2c3834SStanimir Varbanov }
1516af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_vb2_start_streaming);
1517af2c3834SStanimir Varbanov 
1518af2c3834SStanimir Varbanov void venus_helper_m2m_device_run(void *priv)
1519af2c3834SStanimir Varbanov {
1520af2c3834SStanimir Varbanov 	struct venus_inst *inst = priv;
1521af2c3834SStanimir Varbanov 	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
1522af2c3834SStanimir Varbanov 	struct v4l2_m2m_buffer *buf, *n;
1523af2c3834SStanimir Varbanov 	int ret;
1524af2c3834SStanimir Varbanov 
1525af2c3834SStanimir Varbanov 	mutex_lock(&inst->lock);
1526af2c3834SStanimir Varbanov 
1527af2c3834SStanimir Varbanov 	v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) {
1528af2c3834SStanimir Varbanov 		ret = session_process_buf(inst, &buf->vb);
1529af2c3834SStanimir Varbanov 		if (ret)
1530af2c3834SStanimir Varbanov 			return_buf_error(inst, &buf->vb);
1531af2c3834SStanimir Varbanov 	}
1532af2c3834SStanimir Varbanov 
1533af2c3834SStanimir Varbanov 	v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) {
1534af2c3834SStanimir Varbanov 		ret = session_process_buf(inst, &buf->vb);
1535af2c3834SStanimir Varbanov 		if (ret)
1536af2c3834SStanimir Varbanov 			return_buf_error(inst, &buf->vb);
1537af2c3834SStanimir Varbanov 	}
1538af2c3834SStanimir Varbanov 
1539af2c3834SStanimir Varbanov 	mutex_unlock(&inst->lock);
1540af2c3834SStanimir Varbanov }
1541af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_m2m_device_run);
1542af2c3834SStanimir Varbanov 
1543af2c3834SStanimir Varbanov void venus_helper_m2m_job_abort(void *priv)
1544af2c3834SStanimir Varbanov {
1545af2c3834SStanimir Varbanov 	struct venus_inst *inst = priv;
1546af2c3834SStanimir Varbanov 
1547af2c3834SStanimir Varbanov 	v4l2_m2m_job_finish(inst->m2m_dev, inst->m2m_ctx);
1548af2c3834SStanimir Varbanov }
1549af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_m2m_job_abort);
1550af2c3834SStanimir Varbanov 
1551aa603389SStanimir Varbanov int venus_helper_session_init(struct venus_inst *inst)
1552aa603389SStanimir Varbanov {
1553aa603389SStanimir Varbanov 	enum hfi_version version = inst->core->res->hfi_version;
1554aa603389SStanimir Varbanov 	u32 session_type = inst->session_type;
1555aa603389SStanimir Varbanov 	u32 codec;
1556aa603389SStanimir Varbanov 	int ret;
1557aa603389SStanimir Varbanov 
1558aa603389SStanimir Varbanov 	codec = inst->session_type == VIDC_SESSION_TYPE_DEC ?
1559aa603389SStanimir Varbanov 			inst->fmt_out->pixfmt : inst->fmt_cap->pixfmt;
1560aa603389SStanimir Varbanov 
1561aa603389SStanimir Varbanov 	ret = hfi_session_init(inst, codec);
1562aa603389SStanimir Varbanov 	if (ret)
1563aa603389SStanimir Varbanov 		return ret;
1564aa603389SStanimir Varbanov 
1565aa603389SStanimir Varbanov 	inst->clk_data.vpp_freq = hfi_platform_get_codec_vpp_freq(version, codec,
1566aa603389SStanimir Varbanov 								  session_type);
1567aa603389SStanimir Varbanov 	inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(version, codec,
1568aa603389SStanimir Varbanov 								  session_type);
1569aa603389SStanimir Varbanov 
1570aa603389SStanimir Varbanov 	return 0;
1571aa603389SStanimir Varbanov }
1572aa603389SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_session_init);
1573aa603389SStanimir Varbanov 
1574af2c3834SStanimir Varbanov void venus_helper_init_instance(struct venus_inst *inst)
1575af2c3834SStanimir Varbanov {
1576af2c3834SStanimir Varbanov 	if (inst->session_type == VIDC_SESSION_TYPE_DEC) {
1577af2c3834SStanimir Varbanov 		INIT_LIST_HEAD(&inst->delayed_process);
1578af2c3834SStanimir Varbanov 		INIT_WORK(&inst->delayed_process_work,
1579af2c3834SStanimir Varbanov 			  delayed_process_buf_func);
1580af2c3834SStanimir Varbanov 	}
1581af2c3834SStanimir Varbanov }
1582af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_init_instance);
1583aa3a8414SStanimir Varbanov 
15848f3b41dcSStanimir Varbanov static bool find_fmt_from_caps(struct hfi_plat_caps *caps, u32 buftype, u32 fmt)
1585f012b23dSStanimir Varbanov {
1586f012b23dSStanimir Varbanov 	unsigned int i;
1587f012b23dSStanimir Varbanov 
1588f012b23dSStanimir Varbanov 	for (i = 0; i < caps->num_fmts; i++) {
1589f012b23dSStanimir Varbanov 		if (caps->fmts[i].buftype == buftype &&
1590f012b23dSStanimir Varbanov 		    caps->fmts[i].fmt == fmt)
1591f012b23dSStanimir Varbanov 			return true;
1592f012b23dSStanimir Varbanov 	}
1593f012b23dSStanimir Varbanov 
1594f012b23dSStanimir Varbanov 	return false;
1595f012b23dSStanimir Varbanov }
1596f012b23dSStanimir Varbanov 
1597f012b23dSStanimir Varbanov int venus_helper_get_out_fmts(struct venus_inst *inst, u32 v4l2_fmt,
1598f012b23dSStanimir Varbanov 			      u32 *out_fmt, u32 *out2_fmt, bool ubwc)
1599f012b23dSStanimir Varbanov {
1600f012b23dSStanimir Varbanov 	struct venus_core *core = inst->core;
16018f3b41dcSStanimir Varbanov 	struct hfi_plat_caps *caps;
1602f012b23dSStanimir Varbanov 	u32 ubwc_fmt, fmt = to_hfi_raw_fmt(v4l2_fmt);
1603f012b23dSStanimir Varbanov 	bool found, found_ubwc;
1604f012b23dSStanimir Varbanov 
1605f012b23dSStanimir Varbanov 	*out_fmt = *out2_fmt = 0;
1606f012b23dSStanimir Varbanov 
1607f012b23dSStanimir Varbanov 	if (!fmt)
1608f012b23dSStanimir Varbanov 		return -EINVAL;
1609f012b23dSStanimir Varbanov 
1610f012b23dSStanimir Varbanov 	caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);
1611f012b23dSStanimir Varbanov 	if (!caps)
1612f012b23dSStanimir Varbanov 		return -EINVAL;
1613f012b23dSStanimir Varbanov 
1614ab1eda44SAniket Masule 	if (inst->bit_depth == VIDC_BITDEPTH_10 &&
1615ab1eda44SAniket Masule 	    inst->session_type == VIDC_SESSION_TYPE_DEC) {
1616ab1eda44SAniket Masule 		found_ubwc =
1617ab1eda44SAniket Masule 			find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,
1618ab1eda44SAniket Masule 					   HFI_COLOR_FORMAT_YUV420_TP10_UBWC);
1619ab1eda44SAniket Masule 		found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2,
1620ab1eda44SAniket Masule 					   HFI_COLOR_FORMAT_NV12);
1621ab1eda44SAniket Masule 		if (found_ubwc && found) {
1622ab1eda44SAniket Masule 			/*
1623ab1eda44SAniket Masule 			 * Hard-code DPB buffers to be 10bit UBWC and decoder
1624ab1eda44SAniket Masule 			 * output buffers in 8bit NV12 until V4L2 is able to
1625ab1eda44SAniket Masule 			 * expose compressed/tiled formats to applications.
1626ab1eda44SAniket Masule 			 */
1627ab1eda44SAniket Masule 			*out_fmt = HFI_COLOR_FORMAT_YUV420_TP10_UBWC;
1628ab1eda44SAniket Masule 			*out2_fmt = HFI_COLOR_FORMAT_NV12;
1629ab1eda44SAniket Masule 			return 0;
1630ab1eda44SAniket Masule 		}
1631ab1eda44SAniket Masule 
1632ab1eda44SAniket Masule 		return -EINVAL;
1633ab1eda44SAniket Masule 	}
1634ab1eda44SAniket Masule 
1635f012b23dSStanimir Varbanov 	if (ubwc) {
1636f012b23dSStanimir Varbanov 		ubwc_fmt = fmt | HFI_COLOR_FORMAT_UBWC_BASE;
1637f012b23dSStanimir Varbanov 		found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,
1638f012b23dSStanimir Varbanov 						ubwc_fmt);
1639f012b23dSStanimir Varbanov 		found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);
1640f012b23dSStanimir Varbanov 
1641f012b23dSStanimir Varbanov 		if (found_ubwc && found) {
1642f012b23dSStanimir Varbanov 			*out_fmt = ubwc_fmt;
1643f012b23dSStanimir Varbanov 			*out2_fmt = fmt;
1644f012b23dSStanimir Varbanov 			return 0;
1645f012b23dSStanimir Varbanov 		}
1646f012b23dSStanimir Varbanov 	}
1647f012b23dSStanimir Varbanov 
1648f012b23dSStanimir Varbanov 	found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, fmt);
1649f012b23dSStanimir Varbanov 	if (found) {
1650f012b23dSStanimir Varbanov 		*out_fmt = fmt;
1651f012b23dSStanimir Varbanov 		*out2_fmt = 0;
1652f012b23dSStanimir Varbanov 		return 0;
1653f012b23dSStanimir Varbanov 	}
1654f012b23dSStanimir Varbanov 
1655f012b23dSStanimir Varbanov 	found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);
1656f012b23dSStanimir Varbanov 	if (found) {
1657f012b23dSStanimir Varbanov 		*out_fmt = 0;
1658f012b23dSStanimir Varbanov 		*out2_fmt = fmt;
1659f012b23dSStanimir Varbanov 		return 0;
1660f012b23dSStanimir Varbanov 	}
1661f012b23dSStanimir Varbanov 
1662f012b23dSStanimir Varbanov 	return -EINVAL;
1663f012b23dSStanimir Varbanov }
1664f012b23dSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_out_fmts);
1665