brintos

brintos / linux-shallow public Read only

0
0
Text · 48.9 KiB · 8295542 Raw
1857 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.4 * Copyright (C) 2017 Linaro Ltd.5 */6#include <linux/idr.h>7#include <linux/list.h>8#include <linux/mutex.h>9#include <linux/slab.h>10#include <linux/kernel.h>11#include <media/videobuf2-dma-contig.h>12#include <media/v4l2-mem2mem.h>13#include <asm/div64.h>14 15#include "core.h"16#include "helpers.h"17#include "hfi_helper.h"18#include "pm_helpers.h"19#include "hfi_platform.h"20#include "hfi_parser.h"21 22#define NUM_MBS_720P	(((ALIGN(1280, 16)) >> 4) * ((ALIGN(736, 16)) >> 4))23#define NUM_MBS_4K	(((ALIGN(4096, 16)) >> 4) * ((ALIGN(2304, 16)) >> 4))24 25enum dpb_buf_owner {26	DRIVER,27	FIRMWARE,28};29 30struct intbuf {31	struct list_head list;32	u32 type;33	size_t size;34	void *va;35	dma_addr_t da;36	unsigned long attrs;37	enum dpb_buf_owner owned_by;38	u32 dpb_out_tag;39};40 41bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt)42{43	struct venus_core *core = inst->core;44	u32 session_type = inst->session_type;45	u32 codec;46 47	switch (v4l2_pixfmt) {48	case V4L2_PIX_FMT_H264:49		codec = HFI_VIDEO_CODEC_H264;50		break;51	case V4L2_PIX_FMT_H263:52		codec = HFI_VIDEO_CODEC_H263;53		break;54	case V4L2_PIX_FMT_MPEG1:55		codec = HFI_VIDEO_CODEC_MPEG1;56		break;57	case V4L2_PIX_FMT_MPEG2:58		codec = HFI_VIDEO_CODEC_MPEG2;59		break;60	case V4L2_PIX_FMT_MPEG4:61		codec = HFI_VIDEO_CODEC_MPEG4;62		break;63	case V4L2_PIX_FMT_VC1_ANNEX_G:64	case V4L2_PIX_FMT_VC1_ANNEX_L:65		codec = HFI_VIDEO_CODEC_VC1;66		break;67	case V4L2_PIX_FMT_VP8:68		codec = HFI_VIDEO_CODEC_VP8;69		break;70	case V4L2_PIX_FMT_VP9:71		codec = HFI_VIDEO_CODEC_VP9;72		break;73	case V4L2_PIX_FMT_XVID:74		codec = HFI_VIDEO_CODEC_DIVX;75		break;76	case V4L2_PIX_FMT_HEVC:77		codec = HFI_VIDEO_CODEC_HEVC;78		break;79	default:80		return false;81	}82 83	if (session_type == VIDC_SESSION_TYPE_ENC && core->enc_codecs & codec)84		return true;85 86	if (session_type == VIDC_SESSION_TYPE_DEC && core->dec_codecs & codec)87		return true;88 89	return false;90}91EXPORT_SYMBOL_GPL(venus_helper_check_codec);92 93static void free_dpb_buf(struct venus_inst *inst, struct intbuf *buf)94{95	ida_free(&inst->dpb_ids, buf->dpb_out_tag);96 97	list_del_init(&buf->list);98	dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,99		       buf->attrs);100	kfree(buf);101}102 103int venus_helper_queue_dpb_bufs(struct venus_inst *inst)104{105	struct intbuf *buf, *next;106	unsigned int dpb_size = 0;107	int ret = 0;108 109	if (inst->dpb_buftype == HFI_BUFFER_OUTPUT)110		dpb_size = inst->output_buf_size;111	else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2)112		dpb_size = inst->output2_buf_size;113 114	list_for_each_entry_safe(buf, next, &inst->dpbbufs, list) {115		struct hfi_frame_data fdata;116 117		memset(&fdata, 0, sizeof(fdata));118		fdata.alloc_len = buf->size;119		fdata.device_addr = buf->da;120		fdata.buffer_type = buf->type;121 122		if (buf->owned_by == FIRMWARE)123			continue;124 125		/* free buffer from previous sequence which was released later */126		if (dpb_size > buf->size) {127			free_dpb_buf(inst, buf);128			continue;129		}130 131		fdata.clnt_data = buf->dpb_out_tag;132 133		ret = hfi_session_process_buf(inst, &fdata);134		if (ret)135			goto fail;136 137		buf->owned_by = FIRMWARE;138	}139 140fail:141	return ret;142}143EXPORT_SYMBOL_GPL(venus_helper_queue_dpb_bufs);144 145int venus_helper_free_dpb_bufs(struct venus_inst *inst)146{147	struct intbuf *buf, *n;148 149	list_for_each_entry_safe(buf, n, &inst->dpbbufs, list) {150		if (buf->owned_by == FIRMWARE)151			continue;152		free_dpb_buf(inst, buf);153	}154 155	if (list_empty(&inst->dpbbufs))156		INIT_LIST_HEAD(&inst->dpbbufs);157 158	return 0;159}160EXPORT_SYMBOL_GPL(venus_helper_free_dpb_bufs);161 162int venus_helper_alloc_dpb_bufs(struct venus_inst *inst)163{164	struct venus_core *core = inst->core;165	struct device *dev = core->dev;166	enum hfi_version ver = core->res->hfi_version;167	struct hfi_buffer_requirements bufreq;168	u32 buftype = inst->dpb_buftype;169	unsigned int dpb_size = 0;170	struct intbuf *buf;171	unsigned int i;172	u32 count;173	int ret;174	int id;175 176	/* no need to allocate dpb buffers */177	if (!inst->dpb_fmt)178		return 0;179 180	if (inst->dpb_buftype == HFI_BUFFER_OUTPUT)181		dpb_size = inst->output_buf_size;182	else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2)183		dpb_size = inst->output2_buf_size;184 185	if (!dpb_size)186		return 0;187 188	ret = venus_helper_get_bufreq(inst, buftype, &bufreq);189	if (ret)190		return ret;191 192	count = hfi_bufreq_get_count_min(&bufreq, ver);193 194	for (i = 0; i < count; i++) {195		buf = kzalloc(sizeof(*buf), GFP_KERNEL);196		if (!buf) {197			ret = -ENOMEM;198			goto fail;199		}200 201		buf->type = buftype;202		buf->size = dpb_size;203		buf->attrs = DMA_ATTR_WRITE_COMBINE |204			     DMA_ATTR_NO_KERNEL_MAPPING;205		buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL,206					  buf->attrs);207		if (!buf->va) {208			ret = -ENOMEM;209			goto fail;210		}211		buf->owned_by = DRIVER;212 213		id = ida_alloc_min(&inst->dpb_ids, VB2_MAX_FRAME, GFP_KERNEL);214		if (id < 0) {215			ret = id;216			goto fail;217		}218 219		buf->dpb_out_tag = id;220 221		list_add_tail(&buf->list, &inst->dpbbufs);222	}223 224	return 0;225 226fail:227	kfree(buf);228	venus_helper_free_dpb_bufs(inst);229	return ret;230}231EXPORT_SYMBOL_GPL(venus_helper_alloc_dpb_bufs);232 233static int intbufs_set_buffer(struct venus_inst *inst, u32 type)234{235	struct venus_core *core = inst->core;236	struct device *dev = core->dev;237	struct hfi_buffer_requirements bufreq;238	struct hfi_buffer_desc bd;239	struct intbuf *buf;240	unsigned int i;241	int ret;242 243	ret = venus_helper_get_bufreq(inst, type, &bufreq);244	if (ret)245		return 0;246 247	if (!bufreq.size)248		return 0;249 250	for (i = 0; i < bufreq.count_actual; i++) {251		buf = kzalloc(sizeof(*buf), GFP_KERNEL);252		if (!buf) {253			ret = -ENOMEM;254			goto fail;255		}256 257		buf->type = bufreq.type;258		buf->size = bufreq.size;259		buf->attrs = DMA_ATTR_WRITE_COMBINE |260			     DMA_ATTR_NO_KERNEL_MAPPING;261		buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL,262					  buf->attrs);263		if (!buf->va) {264			ret = -ENOMEM;265			goto fail;266		}267 268		memset(&bd, 0, sizeof(bd));269		bd.buffer_size = buf->size;270		bd.buffer_type = buf->type;271		bd.num_buffers = 1;272		bd.device_addr = buf->da;273 274		ret = hfi_session_set_buffers(inst, &bd);275		if (ret) {276			dev_err(dev, "set session buffers failed\n");277			goto dma_free;278		}279 280		list_add_tail(&buf->list, &inst->internalbufs);281	}282 283	return 0;284 285dma_free:286	dma_free_attrs(dev, buf->size, buf->va, buf->da, buf->attrs);287fail:288	kfree(buf);289	return ret;290}291 292static int intbufs_unset_buffers(struct venus_inst *inst)293{294	struct hfi_buffer_desc bd = {0};295	struct intbuf *buf, *n;296	int ret = 0;297 298	list_for_each_entry_safe(buf, n, &inst->internalbufs, list) {299		bd.buffer_size = buf->size;300		bd.buffer_type = buf->type;301		bd.num_buffers = 1;302		bd.device_addr = buf->da;303		bd.response_required = true;304 305		ret = hfi_session_unset_buffers(inst, &bd);306 307		list_del_init(&buf->list);308		dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,309			       buf->attrs);310		kfree(buf);311	}312 313	return ret;314}315 316static const unsigned int intbuf_types_1xx[] = {317	HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_1XX),318	HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_1XX),319	HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_1XX),320	HFI_BUFFER_INTERNAL_PERSIST,321	HFI_BUFFER_INTERNAL_PERSIST_1,322};323 324static const unsigned int intbuf_types_4xx[] = {325	HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_4XX),326	HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_4XX),327	HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_4XX),328	HFI_BUFFER_INTERNAL_PERSIST,329	HFI_BUFFER_INTERNAL_PERSIST_1,330};331 332static const unsigned int intbuf_types_6xx[] = {333	HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_6XX),334	HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_6XX),335	HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_6XX),336	HFI_BUFFER_INTERNAL_PERSIST,337	HFI_BUFFER_INTERNAL_PERSIST_1,338};339 340int venus_helper_intbufs_alloc(struct venus_inst *inst)341{342	const unsigned int *intbuf;343	size_t arr_sz, i;344	int ret;345 346	if (IS_V6(inst->core)) {347		arr_sz = ARRAY_SIZE(intbuf_types_6xx);348		intbuf = intbuf_types_6xx;349	} else if (IS_V4(inst->core)) {350		arr_sz = ARRAY_SIZE(intbuf_types_4xx);351		intbuf = intbuf_types_4xx;352	} else {353		arr_sz = ARRAY_SIZE(intbuf_types_1xx);354		intbuf = intbuf_types_1xx;355	}356 357	for (i = 0; i < arr_sz; i++) {358		ret = intbufs_set_buffer(inst, intbuf[i]);359		if (ret)360			goto error;361	}362 363	return 0;364 365error:366	intbufs_unset_buffers(inst);367	return ret;368}369EXPORT_SYMBOL_GPL(venus_helper_intbufs_alloc);370 371int venus_helper_intbufs_free(struct venus_inst *inst)372{373	return intbufs_unset_buffers(inst);374}375EXPORT_SYMBOL_GPL(venus_helper_intbufs_free);376 377int venus_helper_intbufs_realloc(struct venus_inst *inst)378{379	enum hfi_version ver = inst->core->res->hfi_version;380	struct hfi_buffer_desc bd;381	struct intbuf *buf, *n;382	int ret;383 384	list_for_each_entry_safe(buf, n, &inst->internalbufs, list) {385		if (buf->type == HFI_BUFFER_INTERNAL_PERSIST ||386		    buf->type == HFI_BUFFER_INTERNAL_PERSIST_1)387			continue;388 389		memset(&bd, 0, sizeof(bd));390		bd.buffer_size = buf->size;391		bd.buffer_type = buf->type;392		bd.num_buffers = 1;393		bd.device_addr = buf->da;394		bd.response_required = true;395 396		ret = hfi_session_unset_buffers(inst, &bd);397 398		dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,399			       buf->attrs);400 401		list_del_init(&buf->list);402		kfree(buf);403	}404 405	ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH(ver));406	if (ret)407		goto err;408 409	ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH_1(ver));410	if (ret)411		goto err;412 413	ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH_2(ver));414	if (ret)415		goto err;416 417	return 0;418err:419	return ret;420}421EXPORT_SYMBOL_GPL(venus_helper_intbufs_realloc);422 423static void fill_buffer_desc(const struct venus_buffer *buf,424			     struct hfi_buffer_desc *bd, bool response)425{426	memset(bd, 0, sizeof(*bd));427	bd->buffer_type = HFI_BUFFER_OUTPUT;428	bd->buffer_size = buf->size;429	bd->num_buffers = 1;430	bd->device_addr = buf->dma_addr;431	bd->response_required = response;432}433 434static void return_buf_error(struct venus_inst *inst,435			     struct vb2_v4l2_buffer *vbuf)436{437	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;438 439	if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)440		v4l2_m2m_src_buf_remove_by_buf(m2m_ctx, vbuf);441	else442		v4l2_m2m_dst_buf_remove_by_buf(m2m_ctx, vbuf);443 444	v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);445}446 447static void448put_ts_metadata(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)449{450	struct vb2_buffer *vb = &vbuf->vb2_buf;451	unsigned int i;452	int slot = -1;453	u64 ts_us = vb->timestamp;454 455	for (i = 0; i < ARRAY_SIZE(inst->tss); i++) {456		if (!inst->tss[i].used) {457			slot = i;458			break;459		}460	}461 462	if (slot == -1) {463		dev_dbg(inst->core->dev, VDBGL "no free slot\n");464		return;465	}466 467	do_div(ts_us, NSEC_PER_USEC);468 469	inst->tss[slot].used = true;470	inst->tss[slot].flags = vbuf->flags;471	inst->tss[slot].tc = vbuf->timecode;472	inst->tss[slot].ts_us = ts_us;473	inst->tss[slot].ts_ns = vb->timestamp;474}475 476void venus_helper_get_ts_metadata(struct venus_inst *inst, u64 timestamp_us,477				  struct vb2_v4l2_buffer *vbuf)478{479	struct vb2_buffer *vb = &vbuf->vb2_buf;480	unsigned int i;481 482	for (i = 0; i < ARRAY_SIZE(inst->tss); ++i) {483		if (!inst->tss[i].used)484			continue;485 486		if (inst->tss[i].ts_us != timestamp_us)487			continue;488 489		inst->tss[i].used = false;490		vbuf->flags |= inst->tss[i].flags;491		vbuf->timecode = inst->tss[i].tc;492		vb->timestamp = inst->tss[i].ts_ns;493		break;494	}495}496EXPORT_SYMBOL_GPL(venus_helper_get_ts_metadata);497 498static int499session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)500{501	struct venus_buffer *buf = to_venus_buffer(vbuf);502	struct vb2_buffer *vb = &vbuf->vb2_buf;503	unsigned int type = vb->type;504	struct hfi_frame_data fdata;505 506	memset(&fdata, 0, sizeof(fdata));507	fdata.alloc_len = buf->size;508	fdata.device_addr = buf->dma_addr;509	fdata.timestamp = vb->timestamp;510	do_div(fdata.timestamp, NSEC_PER_USEC);511	fdata.flags = 0;512	fdata.clnt_data = vbuf->vb2_buf.index;513 514	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {515		fdata.buffer_type = HFI_BUFFER_INPUT;516		fdata.filled_len = vb2_get_plane_payload(vb, 0);517		fdata.offset = vb->planes[0].data_offset;518 519		if (vbuf->flags & V4L2_BUF_FLAG_LAST || !fdata.filled_len)520			fdata.flags |= HFI_BUFFERFLAG_EOS;521 522		if (inst->session_type == VIDC_SESSION_TYPE_DEC)523			put_ts_metadata(inst, vbuf);524 525		venus_pm_load_scale(inst);526	} else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {527		if (inst->session_type == VIDC_SESSION_TYPE_ENC)528			fdata.buffer_type = HFI_BUFFER_OUTPUT;529		else530			fdata.buffer_type = inst->opb_buftype;531		fdata.filled_len = 0;532		fdata.offset = 0;533	}534 535	return hfi_session_process_buf(inst, &fdata);536}537 538static bool is_dynamic_bufmode(struct venus_inst *inst)539{540	struct venus_core *core = inst->core;541	struct hfi_plat_caps *caps;542 543	/*544	 * v4 doesn't send BUFFER_ALLOC_MODE_SUPPORTED property and supports545	 * dynamic buffer mode by default for HFI_BUFFER_OUTPUT/OUTPUT2.546	 */547	if (IS_V4(core) || IS_V6(core))548		return true;549 550	caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);551	if (!caps)552		return false;553 554	return caps->cap_bufs_mode_dynamic;555}556 557int venus_helper_unregister_bufs(struct venus_inst *inst)558{559	struct venus_buffer *buf, *n;560	struct hfi_buffer_desc bd;561	int ret = 0;562 563	if (is_dynamic_bufmode(inst))564		return 0;565 566	list_for_each_entry_safe(buf, n, &inst->registeredbufs, reg_list) {567		fill_buffer_desc(buf, &bd, true);568		ret = hfi_session_unset_buffers(inst, &bd);569		list_del_init(&buf->reg_list);570	}571 572	return ret;573}574EXPORT_SYMBOL_GPL(venus_helper_unregister_bufs);575 576static int session_register_bufs(struct venus_inst *inst)577{578	struct venus_core *core = inst->core;579	struct device *dev = core->dev;580	struct hfi_buffer_desc bd;581	struct venus_buffer *buf;582	int ret = 0;583 584	if (is_dynamic_bufmode(inst))585		return 0;586 587	list_for_each_entry(buf, &inst->registeredbufs, reg_list) {588		fill_buffer_desc(buf, &bd, false);589		ret = hfi_session_set_buffers(inst, &bd);590		if (ret) {591			dev_err(dev, "%s: set buffer failed\n", __func__);592			break;593		}594	}595 596	return ret;597}598 599static u32 to_hfi_raw_fmt(u32 v4l2_fmt)600{601	switch (v4l2_fmt) {602	case V4L2_PIX_FMT_NV12:603		return HFI_COLOR_FORMAT_NV12;604	case V4L2_PIX_FMT_NV21:605		return HFI_COLOR_FORMAT_NV21;606	case V4L2_PIX_FMT_QC08C:607		return HFI_COLOR_FORMAT_NV12_UBWC;608	case V4L2_PIX_FMT_QC10C:609		return HFI_COLOR_FORMAT_YUV420_TP10_UBWC;610	case V4L2_PIX_FMT_P010:611		return HFI_COLOR_FORMAT_P010;612	default:613		break;614	}615 616	return 0;617}618 619static int platform_get_bufreq(struct venus_inst *inst, u32 buftype,620			       struct hfi_buffer_requirements *req)621{622	enum hfi_version version = inst->core->res->hfi_version;623	const struct hfi_platform *hfi_plat;624	struct hfi_plat_buffers_params params;625	bool is_dec = inst->session_type == VIDC_SESSION_TYPE_DEC;626	struct venc_controls *enc_ctr = &inst->controls.enc;627 628	hfi_plat = hfi_platform_get(version);629 630	if (!hfi_plat || !hfi_plat->bufreq)631		return -EINVAL;632 633	params.version = version;634	params.num_vpp_pipes = inst->core->res->num_vpp_pipes;635 636	if (is_dec) {637		params.width = inst->width;638		params.height = inst->height;639		params.out_width = inst->out_width;640		params.out_height = inst->out_height;641		params.codec = inst->fmt_out->pixfmt;642		params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_cap->pixfmt);643		params.dec.max_mbs_per_frame = mbs_per_frame_max(inst);644		params.dec.buffer_size_limit = 0;645		params.dec.is_secondary_output =646			inst->opb_buftype == HFI_BUFFER_OUTPUT2;647		if (params.dec.is_secondary_output)648			params.hfi_dpb_color_fmt = inst->dpb_fmt;649		params.dec.is_interlaced =650			inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE;651	} else {652		params.width = inst->out_width;653		params.height = inst->out_height;654		params.codec = inst->fmt_cap->pixfmt;655		params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_out->pixfmt);656		params.enc.work_mode = VIDC_WORK_MODE_2;657		params.enc.rc_type = HFI_RATE_CONTROL_OFF;658		if (enc_ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)659			params.enc.rc_type = HFI_RATE_CONTROL_CQ;660		params.enc.num_b_frames = enc_ctr->num_b_frames;661		params.enc.is_tenbit = inst->bit_depth == VIDC_BITDEPTH_10;662	}663 664	return hfi_plat->bufreq(&params, inst->session_type, buftype, req);665}666 667int venus_helper_get_bufreq(struct venus_inst *inst, u32 type,668			    struct hfi_buffer_requirements *req)669{670	u32 ptype = HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS;671	enum hfi_version ver = inst->core->res->hfi_version;672	union hfi_get_property hprop;673	unsigned int i;674	int ret;675 676	memset(req, 0, sizeof(*req));677 678	if (type == HFI_BUFFER_OUTPUT || type == HFI_BUFFER_OUTPUT2)679		hfi_bufreq_set_count_min(req, ver, inst->fw_min_cnt);680 681	ret = platform_get_bufreq(inst, type, req);682	if (!ret) {683		if (type == HFI_BUFFER_OUTPUT || type == HFI_BUFFER_OUTPUT2)684			inst->fw_min_cnt = hfi_bufreq_get_count_min(req, ver);685		return 0;686	}687 688	ret = hfi_session_get_property(inst, ptype, &hprop);689	if (ret)690		return ret;691 692	ret = -EINVAL;693 694	for (i = 0; i < HFI_BUFFER_TYPE_MAX; i++) {695		if (hprop.bufreq[i].type != type)696			continue;697 698		memcpy(req, &hprop.bufreq[i], sizeof(*req));699		ret = 0;700		break;701	}702 703	return ret;704}705EXPORT_SYMBOL_GPL(venus_helper_get_bufreq);706 707struct id_mapping {708	u32 hfi_id;709	u32 v4l2_id;710};711 712static const struct id_mapping mpeg4_profiles[] = {713	{ HFI_MPEG4_PROFILE_SIMPLE, V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE },714	{ HFI_MPEG4_PROFILE_ADVANCEDSIMPLE, V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE },715};716 717static const struct id_mapping mpeg4_levels[] = {718	{ HFI_MPEG4_LEVEL_0, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0 },719	{ HFI_MPEG4_LEVEL_0b, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B },720	{ HFI_MPEG4_LEVEL_1, V4L2_MPEG_VIDEO_MPEG4_LEVEL_1 },721	{ HFI_MPEG4_LEVEL_2, V4L2_MPEG_VIDEO_MPEG4_LEVEL_2 },722	{ HFI_MPEG4_LEVEL_3, V4L2_MPEG_VIDEO_MPEG4_LEVEL_3 },723	{ HFI_MPEG4_LEVEL_4, V4L2_MPEG_VIDEO_MPEG4_LEVEL_4 },724	{ HFI_MPEG4_LEVEL_5, V4L2_MPEG_VIDEO_MPEG4_LEVEL_5 },725};726 727static const struct id_mapping mpeg2_profiles[] = {728	{ HFI_MPEG2_PROFILE_SIMPLE, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SIMPLE },729	{ HFI_MPEG2_PROFILE_MAIN, V4L2_MPEG_VIDEO_MPEG2_PROFILE_MAIN },730	{ HFI_MPEG2_PROFILE_SNR, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SNR_SCALABLE },731	{ HFI_MPEG2_PROFILE_SPATIAL, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SPATIALLY_SCALABLE },732	{ HFI_MPEG2_PROFILE_HIGH, V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH },733};734 735static const struct id_mapping mpeg2_levels[] = {736	{ HFI_MPEG2_LEVEL_LL, V4L2_MPEG_VIDEO_MPEG2_LEVEL_LOW },737	{ HFI_MPEG2_LEVEL_ML, V4L2_MPEG_VIDEO_MPEG2_LEVEL_MAIN },738	{ HFI_MPEG2_LEVEL_H14, V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH_1440 },739	{ HFI_MPEG2_LEVEL_HL, V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH },740};741 742static const struct id_mapping h264_profiles[] = {743	{ HFI_H264_PROFILE_BASELINE, V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE },744	{ HFI_H264_PROFILE_MAIN, V4L2_MPEG_VIDEO_H264_PROFILE_MAIN },745	{ HFI_H264_PROFILE_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_HIGH },746	{ HFI_H264_PROFILE_STEREO_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH },747	{ HFI_H264_PROFILE_MULTIVIEW_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH },748	{ HFI_H264_PROFILE_CONSTRAINED_BASE, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE },749	{ HFI_H264_PROFILE_CONSTRAINED_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH },750};751 752static const struct id_mapping h264_levels[] = {753	{ HFI_H264_LEVEL_1, V4L2_MPEG_VIDEO_H264_LEVEL_1_0 },754	{ HFI_H264_LEVEL_1b, V4L2_MPEG_VIDEO_H264_LEVEL_1B },755	{ HFI_H264_LEVEL_11, V4L2_MPEG_VIDEO_H264_LEVEL_1_1 },756	{ HFI_H264_LEVEL_12, V4L2_MPEG_VIDEO_H264_LEVEL_1_2 },757	{ HFI_H264_LEVEL_13, V4L2_MPEG_VIDEO_H264_LEVEL_1_3 },758	{ HFI_H264_LEVEL_2, V4L2_MPEG_VIDEO_H264_LEVEL_2_0 },759	{ HFI_H264_LEVEL_21, V4L2_MPEG_VIDEO_H264_LEVEL_2_1 },760	{ HFI_H264_LEVEL_22, V4L2_MPEG_VIDEO_H264_LEVEL_2_2 },761	{ HFI_H264_LEVEL_3, V4L2_MPEG_VIDEO_H264_LEVEL_3_0 },762	{ HFI_H264_LEVEL_31, V4L2_MPEG_VIDEO_H264_LEVEL_3_1 },763	{ HFI_H264_LEVEL_32, V4L2_MPEG_VIDEO_H264_LEVEL_3_2 },764	{ HFI_H264_LEVEL_4, V4L2_MPEG_VIDEO_H264_LEVEL_4_0 },765	{ HFI_H264_LEVEL_41, V4L2_MPEG_VIDEO_H264_LEVEL_4_1 },766	{ HFI_H264_LEVEL_42, V4L2_MPEG_VIDEO_H264_LEVEL_4_2 },767	{ HFI_H264_LEVEL_5, V4L2_MPEG_VIDEO_H264_LEVEL_5_0 },768	{ HFI_H264_LEVEL_51, V4L2_MPEG_VIDEO_H264_LEVEL_5_1 },769	{ HFI_H264_LEVEL_52, V4L2_MPEG_VIDEO_H264_LEVEL_5_1 },770};771 772static const struct id_mapping hevc_profiles[] = {773	{ HFI_HEVC_PROFILE_MAIN, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN },774	{ HFI_HEVC_PROFILE_MAIN_STILL_PIC, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE },775	{ HFI_HEVC_PROFILE_MAIN10, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10 },776};777 778static const struct id_mapping hevc_levels[] = {779	{ HFI_HEVC_LEVEL_1, V4L2_MPEG_VIDEO_HEVC_LEVEL_1 },780	{ HFI_HEVC_LEVEL_2, V4L2_MPEG_VIDEO_HEVC_LEVEL_2 },781	{ HFI_HEVC_LEVEL_21, V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1 },782	{ HFI_HEVC_LEVEL_3, V4L2_MPEG_VIDEO_HEVC_LEVEL_3 },783	{ HFI_HEVC_LEVEL_31, V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1 },784	{ HFI_HEVC_LEVEL_4, V4L2_MPEG_VIDEO_HEVC_LEVEL_4 },785	{ HFI_HEVC_LEVEL_41, V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1 },786	{ HFI_HEVC_LEVEL_5, V4L2_MPEG_VIDEO_HEVC_LEVEL_5 },787	{ HFI_HEVC_LEVEL_51, V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1 },788	{ HFI_HEVC_LEVEL_52, V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2 },789	{ HFI_HEVC_LEVEL_6, V4L2_MPEG_VIDEO_HEVC_LEVEL_6 },790	{ HFI_HEVC_LEVEL_61, V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1 },791	{ HFI_HEVC_LEVEL_62, V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2 },792};793 794static const struct id_mapping vp8_profiles[] = {795	{ HFI_VPX_PROFILE_VERSION_0, V4L2_MPEG_VIDEO_VP8_PROFILE_0 },796	{ HFI_VPX_PROFILE_VERSION_1, V4L2_MPEG_VIDEO_VP8_PROFILE_1 },797	{ HFI_VPX_PROFILE_VERSION_2, V4L2_MPEG_VIDEO_VP8_PROFILE_2 },798	{ HFI_VPX_PROFILE_VERSION_3, V4L2_MPEG_VIDEO_VP8_PROFILE_3 },799};800 801static const struct id_mapping vp9_profiles[] = {802	{ HFI_VP9_PROFILE_P0, V4L2_MPEG_VIDEO_VP9_PROFILE_0 },803	{ HFI_VP9_PROFILE_P2_10B, V4L2_MPEG_VIDEO_VP9_PROFILE_2 },804};805 806static const struct id_mapping vp9_levels[] = {807	{ HFI_VP9_LEVEL_1, V4L2_MPEG_VIDEO_VP9_LEVEL_1_0 },808	{ HFI_VP9_LEVEL_11, V4L2_MPEG_VIDEO_VP9_LEVEL_1_1 },809	{ HFI_VP9_LEVEL_2, V4L2_MPEG_VIDEO_VP9_LEVEL_2_0},810	{ HFI_VP9_LEVEL_21, V4L2_MPEG_VIDEO_VP9_LEVEL_2_1 },811	{ HFI_VP9_LEVEL_3, V4L2_MPEG_VIDEO_VP9_LEVEL_3_0},812	{ HFI_VP9_LEVEL_31, V4L2_MPEG_VIDEO_VP9_LEVEL_3_1 },813	{ HFI_VP9_LEVEL_4, V4L2_MPEG_VIDEO_VP9_LEVEL_4_0 },814	{ HFI_VP9_LEVEL_41, V4L2_MPEG_VIDEO_VP9_LEVEL_4_1 },815	{ HFI_VP9_LEVEL_5, V4L2_MPEG_VIDEO_VP9_LEVEL_5_0 },816	{ HFI_VP9_LEVEL_51, V4L2_MPEG_VIDEO_VP9_LEVEL_5_1 },817	{ HFI_VP9_LEVEL_6, V4L2_MPEG_VIDEO_VP9_LEVEL_6_0 },818	{ HFI_VP9_LEVEL_61, V4L2_MPEG_VIDEO_VP9_LEVEL_6_1 },819};820 821static u32 find_v4l2_id(u32 hfi_id, const struct id_mapping *array, unsigned int array_sz)822{823	unsigned int i;824 825	if (!array || !array_sz)826		return 0;827 828	for (i = 0; i < array_sz; i++)829		if (hfi_id == array[i].hfi_id)830			return array[i].v4l2_id;831 832	return 0;833}834 835static u32 find_hfi_id(u32 v4l2_id, const struct id_mapping *array, unsigned int array_sz)836{837	unsigned int i;838 839	if (!array || !array_sz)840		return 0;841 842	for (i = 0; i < array_sz; i++)843		if (v4l2_id == array[i].v4l2_id)844			return array[i].hfi_id;845 846	return 0;847}848 849static void850v4l2_id_profile_level(u32 hfi_codec, struct hfi_profile_level *pl, u32 *profile, u32 *level)851{852	u32 hfi_pf = pl->profile;853	u32 hfi_lvl = pl->level;854 855	switch (hfi_codec) {856	case HFI_VIDEO_CODEC_H264:857		*profile = find_v4l2_id(hfi_pf, h264_profiles, ARRAY_SIZE(h264_profiles));858		*level = find_v4l2_id(hfi_lvl, h264_levels, ARRAY_SIZE(h264_levels));859		break;860	case HFI_VIDEO_CODEC_MPEG2:861		*profile = find_v4l2_id(hfi_pf, mpeg2_profiles, ARRAY_SIZE(mpeg2_profiles));862		*level = find_v4l2_id(hfi_lvl, mpeg2_levels, ARRAY_SIZE(mpeg2_levels));863		break;864	case HFI_VIDEO_CODEC_MPEG4:865		*profile = find_v4l2_id(hfi_pf, mpeg4_profiles, ARRAY_SIZE(mpeg4_profiles));866		*level = find_v4l2_id(hfi_lvl, mpeg4_levels, ARRAY_SIZE(mpeg4_levels));867		break;868	case HFI_VIDEO_CODEC_VP8:869		*profile = find_v4l2_id(hfi_pf, vp8_profiles, ARRAY_SIZE(vp8_profiles));870		*level = 0;871		break;872	case HFI_VIDEO_CODEC_VP9:873		*profile = find_v4l2_id(hfi_pf, vp9_profiles, ARRAY_SIZE(vp9_profiles));874		*level = find_v4l2_id(hfi_lvl, vp9_levels, ARRAY_SIZE(vp9_levels));875		break;876	case HFI_VIDEO_CODEC_HEVC:877		*profile = find_v4l2_id(hfi_pf, hevc_profiles, ARRAY_SIZE(hevc_profiles));878		*level = find_v4l2_id(hfi_lvl, hevc_levels, ARRAY_SIZE(hevc_levels));879		break;880	default:881		break;882	}883}884 885static void886hfi_id_profile_level(u32 hfi_codec, u32 v4l2_pf, u32 v4l2_lvl, struct hfi_profile_level *pl)887{888	switch (hfi_codec) {889	case HFI_VIDEO_CODEC_H264:890		pl->profile = find_hfi_id(v4l2_pf, h264_profiles, ARRAY_SIZE(h264_profiles));891		pl->level = find_hfi_id(v4l2_lvl, h264_levels, ARRAY_SIZE(h264_levels));892		break;893	case HFI_VIDEO_CODEC_MPEG2:894		pl->profile = find_hfi_id(v4l2_pf, mpeg2_profiles, ARRAY_SIZE(mpeg2_profiles));895		pl->level = find_hfi_id(v4l2_lvl, mpeg2_levels, ARRAY_SIZE(mpeg2_levels));896		break;897	case HFI_VIDEO_CODEC_MPEG4:898		pl->profile = find_hfi_id(v4l2_pf, mpeg4_profiles, ARRAY_SIZE(mpeg4_profiles));899		pl->level = find_hfi_id(v4l2_lvl, mpeg4_levels, ARRAY_SIZE(mpeg4_levels));900		break;901	case HFI_VIDEO_CODEC_VP8:902		pl->profile = find_hfi_id(v4l2_pf, vp8_profiles, ARRAY_SIZE(vp8_profiles));903		pl->level = 0;904		break;905	case HFI_VIDEO_CODEC_VP9:906		pl->profile = find_hfi_id(v4l2_pf, vp9_profiles, ARRAY_SIZE(vp9_profiles));907		pl->level = find_hfi_id(v4l2_lvl, vp9_levels, ARRAY_SIZE(vp9_levels));908		break;909	case HFI_VIDEO_CODEC_HEVC:910		pl->profile = find_hfi_id(v4l2_pf, hevc_profiles, ARRAY_SIZE(hevc_profiles));911		pl->level = find_hfi_id(v4l2_lvl, hevc_levels, ARRAY_SIZE(hevc_levels));912		break;913	default:914		break;915	}916}917 918int venus_helper_get_profile_level(struct venus_inst *inst, u32 *profile, u32 *level)919{920	const u32 ptype = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT;921	union hfi_get_property hprop;922	int ret;923 924	ret = hfi_session_get_property(inst, ptype, &hprop);925	if (ret)926		return ret;927 928	v4l2_id_profile_level(inst->hfi_codec, &hprop.profile_level, profile, level);929 930	return 0;931}932EXPORT_SYMBOL_GPL(venus_helper_get_profile_level);933 934int venus_helper_set_profile_level(struct venus_inst *inst, u32 profile, u32 level)935{936	const u32 ptype = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT;937	struct hfi_profile_level pl;938 939	hfi_id_profile_level(inst->hfi_codec, profile, level, &pl);940 941	return hfi_session_set_property(inst, ptype, &pl);942}943EXPORT_SYMBOL_GPL(venus_helper_set_profile_level);944 945static u32 get_framesize_raw_nv12(u32 width, u32 height)946{947	u32 y_stride, uv_stride, y_plane;948	u32 y_sclines, uv_sclines, uv_plane;949	u32 size;950 951	y_stride = ALIGN(width, 128);952	uv_stride = ALIGN(width, 128);953	y_sclines = ALIGN(height, 32);954	uv_sclines = ALIGN(((height + 1) >> 1), 16);955 956	y_plane = y_stride * y_sclines;957	uv_plane = uv_stride * uv_sclines + SZ_4K;958	size = y_plane + uv_plane + SZ_8K;959 960	return ALIGN(size, SZ_4K);961}962 963static u32 get_framesize_raw_nv12_ubwc(u32 width, u32 height)964{965	u32 y_meta_stride, y_meta_plane;966	u32 y_stride, y_plane;967	u32 uv_meta_stride, uv_meta_plane;968	u32 uv_stride, uv_plane;969	u32 extradata = SZ_16K;970 971	y_meta_stride = ALIGN(DIV_ROUND_UP(width, 32), 64);972	y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(height, 8), 16);973	y_meta_plane = ALIGN(y_meta_plane, SZ_4K);974 975	y_stride = ALIGN(width, 128);976	y_plane = ALIGN(y_stride * ALIGN(height, 32), SZ_4K);977 978	uv_meta_stride = ALIGN(DIV_ROUND_UP(width / 2, 16), 64);979	uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP(height / 2, 8), 16);980	uv_meta_plane = ALIGN(uv_meta_plane, SZ_4K);981 982	uv_stride = ALIGN(width, 128);983	uv_plane = ALIGN(uv_stride * ALIGN(height / 2, 32), SZ_4K);984 985	return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane +986		     max(extradata, y_stride * 48), SZ_4K);987}988 989static u32 get_framesize_raw_p010(u32 width, u32 height)990{991	u32 y_plane, uv_plane, y_stride, uv_stride, y_sclines, uv_sclines;992 993	y_stride = ALIGN(width * 2, 128);994	uv_stride = ALIGN(width * 2, 128);995	y_sclines = ALIGN(height, 32);996	uv_sclines = ALIGN((height + 1) >> 1, 16);997	y_plane = y_stride * y_sclines;998	uv_plane = uv_stride * uv_sclines;999 1000	return ALIGN((y_plane + uv_plane), SZ_4K);1001}1002 1003static u32 get_framesize_raw_p010_ubwc(u32 width, u32 height)1004{1005	u32 y_stride, uv_stride, y_sclines, uv_sclines;1006	u32 y_ubwc_plane, uv_ubwc_plane;1007	u32 y_meta_stride, y_meta_scanlines;1008	u32 uv_meta_stride, uv_meta_scanlines;1009	u32 y_meta_plane, uv_meta_plane;1010	u32 size;1011 1012	y_stride = ALIGN(width * 2, 256);1013	uv_stride = ALIGN(width * 2, 256);1014	y_sclines = ALIGN(height, 16);1015	uv_sclines = ALIGN((height + 1) >> 1, 16);1016 1017	y_ubwc_plane = ALIGN(y_stride * y_sclines, SZ_4K);1018	uv_ubwc_plane = ALIGN(uv_stride * uv_sclines, SZ_4K);1019	y_meta_stride = ALIGN(DIV_ROUND_UP(width, 32), 64);1020	y_meta_scanlines = ALIGN(DIV_ROUND_UP(height, 4), 16);1021	y_meta_plane = ALIGN(y_meta_stride * y_meta_scanlines, SZ_4K);1022	uv_meta_stride = ALIGN(DIV_ROUND_UP((width + 1) >> 1, 16), 64);1023	uv_meta_scanlines = ALIGN(DIV_ROUND_UP((height + 1) >> 1, 4), 16);1024	uv_meta_plane = ALIGN(uv_meta_stride * uv_meta_scanlines, SZ_4K);1025 1026	size = y_ubwc_plane + uv_ubwc_plane + y_meta_plane + uv_meta_plane;1027 1028	return ALIGN(size, SZ_4K);1029}1030 1031static u32 get_framesize_raw_yuv420_tp10_ubwc(u32 width, u32 height)1032{1033	u32 y_stride, uv_stride, y_sclines, uv_sclines;1034	u32 y_ubwc_plane, uv_ubwc_plane;1035	u32 y_meta_stride, y_meta_scanlines;1036	u32 uv_meta_stride, uv_meta_scanlines;1037	u32 y_meta_plane, uv_meta_plane;1038	u32 extradata = SZ_16K;1039	u32 size;1040 1041	y_stride = ALIGN(width * 4 / 3, 256);1042	uv_stride = ALIGN(width * 4 / 3, 256);1043	y_sclines = ALIGN(height, 16);1044	uv_sclines = ALIGN((height + 1) >> 1, 16);1045 1046	y_ubwc_plane = ALIGN(y_stride * y_sclines, SZ_4K);1047	uv_ubwc_plane = ALIGN(uv_stride * uv_sclines, SZ_4K);1048	y_meta_stride = ALIGN(DIV_ROUND_UP(width, 48), 64);1049	y_meta_scanlines = ALIGN(DIV_ROUND_UP(height, 4), 16);1050	y_meta_plane = ALIGN(y_meta_stride * y_meta_scanlines, SZ_4K);1051	uv_meta_stride = ALIGN(DIV_ROUND_UP((width + 1) >> 1, 24), 64);1052	uv_meta_scanlines = ALIGN(DIV_ROUND_UP((height + 1) >> 1, 4), 16);1053	uv_meta_plane = ALIGN(uv_meta_stride * uv_meta_scanlines, SZ_4K);1054 1055	size = y_ubwc_plane + uv_ubwc_plane + y_meta_plane + uv_meta_plane;1056	size += max(extradata + SZ_8K, y_stride * 48);1057 1058	return ALIGN(size, SZ_4K);1059}1060 1061u32 venus_helper_get_framesz_raw(u32 hfi_fmt, u32 width, u32 height)1062{1063	switch (hfi_fmt) {1064	case HFI_COLOR_FORMAT_NV12:1065	case HFI_COLOR_FORMAT_NV21:1066		return get_framesize_raw_nv12(width, height);1067	case HFI_COLOR_FORMAT_NV12_UBWC:1068		return get_framesize_raw_nv12_ubwc(width, height);1069	case HFI_COLOR_FORMAT_P010:1070		return get_framesize_raw_p010(width, height);1071	case HFI_COLOR_FORMAT_P010_UBWC:1072		return get_framesize_raw_p010_ubwc(width, height);1073	case HFI_COLOR_FORMAT_YUV420_TP10_UBWC:1074		return get_framesize_raw_yuv420_tp10_ubwc(width, height);1075	default:1076		return 0;1077	}1078}1079EXPORT_SYMBOL_GPL(venus_helper_get_framesz_raw);1080 1081u32 venus_helper_get_framesz(u32 v4l2_fmt, u32 width, u32 height)1082{1083	u32 hfi_fmt, sz;1084	bool compressed;1085 1086	switch (v4l2_fmt) {1087	case V4L2_PIX_FMT_MPEG:1088	case V4L2_PIX_FMT_H264:1089	case V4L2_PIX_FMT_H264_NO_SC:1090	case V4L2_PIX_FMT_H264_MVC:1091	case V4L2_PIX_FMT_H263:1092	case V4L2_PIX_FMT_MPEG1:1093	case V4L2_PIX_FMT_MPEG2:1094	case V4L2_PIX_FMT_MPEG4:1095	case V4L2_PIX_FMT_XVID:1096	case V4L2_PIX_FMT_VC1_ANNEX_G:1097	case V4L2_PIX_FMT_VC1_ANNEX_L:1098	case V4L2_PIX_FMT_VP8:1099	case V4L2_PIX_FMT_VP9:1100	case V4L2_PIX_FMT_HEVC:1101		compressed = true;1102		break;1103	default:1104		compressed = false;1105		break;1106	}1107 1108	if (compressed) {1109		sz = ALIGN(height, 32) * ALIGN(width, 32) * 3 / 2 / 2;1110		if (width < 1280 || height < 720)1111			sz *= 8;1112		return ALIGN(sz, SZ_4K);1113	}1114 1115	hfi_fmt = to_hfi_raw_fmt(v4l2_fmt);1116	if (!hfi_fmt)1117		return 0;1118 1119	return venus_helper_get_framesz_raw(hfi_fmt, width, height);1120}1121EXPORT_SYMBOL_GPL(venus_helper_get_framesz);1122 1123int venus_helper_set_input_resolution(struct venus_inst *inst,1124				      unsigned int width, unsigned int height)1125{1126	u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE;1127	struct hfi_framesize fs;1128 1129	fs.buffer_type = HFI_BUFFER_INPUT;1130	fs.width = width;1131	fs.height = height;1132 1133	return hfi_session_set_property(inst, ptype, &fs);1134}1135EXPORT_SYMBOL_GPL(venus_helper_set_input_resolution);1136 1137int venus_helper_set_output_resolution(struct venus_inst *inst,1138				       unsigned int width, unsigned int height,1139				       u32 buftype)1140{1141	u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE;1142	struct hfi_framesize fs;1143 1144	fs.buffer_type = buftype;1145	fs.width = width;1146	fs.height = height;1147 1148	return hfi_session_set_property(inst, ptype, &fs);1149}1150EXPORT_SYMBOL_GPL(venus_helper_set_output_resolution);1151 1152static u32 venus_helper_get_work_mode(struct venus_inst *inst)1153{1154	u32 mode;1155	u32 num_mbs;1156 1157	mode = VIDC_WORK_MODE_2;1158	if (inst->session_type == VIDC_SESSION_TYPE_DEC) {1159		num_mbs = (ALIGN(inst->height, 16) * ALIGN(inst->width, 16)) / 256;1160		if (inst->hfi_codec == HFI_VIDEO_CODEC_MPEG2 ||1161		    inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE ||1162		    num_mbs <= NUM_MBS_720P)1163			mode = VIDC_WORK_MODE_1;1164	} else {1165		num_mbs = (ALIGN(inst->out_height, 16) * ALIGN(inst->out_width, 16)) / 256;1166		if (inst->hfi_codec == HFI_VIDEO_CODEC_VP8 &&1167		    num_mbs <= NUM_MBS_4K)1168			mode = VIDC_WORK_MODE_1;1169	}1170 1171	return mode;1172}1173 1174int venus_helper_set_work_mode(struct venus_inst *inst)1175{1176	const u32 ptype = HFI_PROPERTY_PARAM_WORK_MODE;1177	struct hfi_video_work_mode wm;1178	u32 mode;1179 1180	if (!IS_V4(inst->core) && !IS_V6(inst->core))1181		return 0;1182 1183	mode = venus_helper_get_work_mode(inst);1184	wm.video_work_mode = mode;1185	return hfi_session_set_property(inst, ptype, &wm);1186}1187EXPORT_SYMBOL_GPL(venus_helper_set_work_mode);1188 1189int venus_helper_set_format_constraints(struct venus_inst *inst)1190{1191	const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO;1192	struct hfi_uncompressed_plane_actual_constraints_info pconstraint;1193 1194	if (!IS_V6(inst->core))1195		return 0;1196 1197	if (inst->opb_fmt == HFI_COLOR_FORMAT_NV12_UBWC ||1198	    inst->opb_fmt == HFI_COLOR_FORMAT_YUV420_TP10_UBWC)1199		return 0;1200 1201	pconstraint.buffer_type = HFI_BUFFER_OUTPUT2;1202	pconstraint.num_planes = 2;1203	pconstraint.plane_format[0].stride_multiples = 128;1204	pconstraint.plane_format[0].max_stride = 8192;1205	pconstraint.plane_format[0].min_plane_buffer_height_multiple = 32;1206	pconstraint.plane_format[0].buffer_alignment = 256;1207 1208	pconstraint.plane_format[1].stride_multiples = 128;1209	pconstraint.plane_format[1].max_stride = 8192;1210	pconstraint.plane_format[1].min_plane_buffer_height_multiple = 16;1211	pconstraint.plane_format[1].buffer_alignment = 256;1212 1213	return hfi_session_set_property(inst, ptype, &pconstraint);1214}1215EXPORT_SYMBOL_GPL(venus_helper_set_format_constraints);1216 1217int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs,1218			      unsigned int output_bufs,1219			      unsigned int output2_bufs)1220{1221	u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL;1222	struct hfi_buffer_count_actual buf_count;1223	int ret;1224 1225	buf_count.type = HFI_BUFFER_INPUT;1226	buf_count.count_actual = input_bufs;1227 1228	ret = hfi_session_set_property(inst, ptype, &buf_count);1229	if (ret)1230		return ret;1231 1232	buf_count.type = HFI_BUFFER_OUTPUT;1233	buf_count.count_actual = output_bufs;1234 1235	ret = hfi_session_set_property(inst, ptype, &buf_count);1236	if (ret)1237		return ret;1238 1239	if (output2_bufs) {1240		buf_count.type = HFI_BUFFER_OUTPUT2;1241		buf_count.count_actual = output2_bufs;1242 1243		ret = hfi_session_set_property(inst, ptype, &buf_count);1244	}1245 1246	return ret;1247}1248EXPORT_SYMBOL_GPL(venus_helper_set_num_bufs);1249 1250int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format,1251				u32 buftype)1252{1253	const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT;1254	struct hfi_uncompressed_format_select fmt;1255 1256	fmt.buffer_type = buftype;1257	fmt.format = hfi_format;1258 1259	return hfi_session_set_property(inst, ptype, &fmt);1260}1261EXPORT_SYMBOL_GPL(venus_helper_set_raw_format);1262 1263int venus_helper_set_color_format(struct venus_inst *inst, u32 pixfmt)1264{1265	u32 hfi_format, buftype;1266 1267	if (inst->session_type == VIDC_SESSION_TYPE_DEC)1268		buftype = HFI_BUFFER_OUTPUT;1269	else if (inst->session_type == VIDC_SESSION_TYPE_ENC)1270		buftype = HFI_BUFFER_INPUT;1271	else1272		return -EINVAL;1273 1274	hfi_format = to_hfi_raw_fmt(pixfmt);1275	if (!hfi_format)1276		return -EINVAL;1277 1278	return venus_helper_set_raw_format(inst, hfi_format, buftype);1279}1280EXPORT_SYMBOL_GPL(venus_helper_set_color_format);1281 1282int venus_helper_set_multistream(struct venus_inst *inst, bool out_en,1283				 bool out2_en)1284{1285	struct hfi_multi_stream multi = {0};1286	u32 ptype = HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM;1287	int ret;1288 1289	multi.buffer_type = HFI_BUFFER_OUTPUT;1290	multi.enable = out_en;1291 1292	ret = hfi_session_set_property(inst, ptype, &multi);1293	if (ret)1294		return ret;1295 1296	multi.buffer_type = HFI_BUFFER_OUTPUT2;1297	multi.enable = out2_en;1298 1299	return hfi_session_set_property(inst, ptype, &multi);1300}1301EXPORT_SYMBOL_GPL(venus_helper_set_multistream);1302 1303int venus_helper_set_dyn_bufmode(struct venus_inst *inst)1304{1305	const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE;1306	struct hfi_buffer_alloc_mode mode;1307	int ret;1308 1309	if (!is_dynamic_bufmode(inst))1310		return 0;1311 1312	mode.type = HFI_BUFFER_OUTPUT;1313	mode.mode = HFI_BUFFER_MODE_DYNAMIC;1314 1315	ret = hfi_session_set_property(inst, ptype, &mode);1316	if (ret)1317		return ret;1318 1319	mode.type = HFI_BUFFER_OUTPUT2;1320 1321	return hfi_session_set_property(inst, ptype, &mode);1322}1323EXPORT_SYMBOL_GPL(venus_helper_set_dyn_bufmode);1324 1325int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype)1326{1327	const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL;1328	struct hfi_buffer_size_actual bufsz;1329 1330	bufsz.type = buftype;1331	bufsz.size = bufsize;1332 1333	return hfi_session_set_property(inst, ptype, &bufsz);1334}1335EXPORT_SYMBOL_GPL(venus_helper_set_bufsize);1336 1337unsigned int venus_helper_get_opb_size(struct venus_inst *inst)1338{1339	/* the encoder has only one output */1340	if (inst->session_type == VIDC_SESSION_TYPE_ENC)1341		return inst->output_buf_size;1342 1343	if (inst->opb_buftype == HFI_BUFFER_OUTPUT)1344		return inst->output_buf_size;1345	else if (inst->opb_buftype == HFI_BUFFER_OUTPUT2)1346		return inst->output2_buf_size;1347 1348	return 0;1349}1350EXPORT_SYMBOL_GPL(venus_helper_get_opb_size);1351 1352static void delayed_process_buf_func(struct work_struct *work)1353{1354	struct venus_buffer *buf, *n;1355	struct venus_inst *inst;1356	int ret;1357 1358	inst = container_of(work, struct venus_inst, delayed_process_work);1359 1360	mutex_lock(&inst->lock);1361 1362	if (!(inst->streamon_out & inst->streamon_cap))1363		goto unlock;1364 1365	list_for_each_entry_safe(buf, n, &inst->delayed_process, ref_list) {1366		if (buf->flags & HFI_BUFFERFLAG_READONLY)1367			continue;1368 1369		ret = session_process_buf(inst, &buf->vb);1370		if (ret)1371			return_buf_error(inst, &buf->vb);1372 1373		list_del_init(&buf->ref_list);1374	}1375unlock:1376	mutex_unlock(&inst->lock);1377}1378 1379void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx)1380{1381	struct venus_buffer *buf;1382 1383	list_for_each_entry(buf, &inst->registeredbufs, reg_list) {1384		if (buf->vb.vb2_buf.index == idx) {1385			buf->flags &= ~HFI_BUFFERFLAG_READONLY;1386			schedule_work(&inst->delayed_process_work);1387			break;1388		}1389	}1390}1391EXPORT_SYMBOL_GPL(venus_helper_release_buf_ref);1392 1393void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf)1394{1395	struct venus_buffer *buf = to_venus_buffer(vbuf);1396 1397	buf->flags |= HFI_BUFFERFLAG_READONLY;1398}1399EXPORT_SYMBOL_GPL(venus_helper_acquire_buf_ref);1400 1401static int is_buf_refed(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)1402{1403	struct venus_buffer *buf = to_venus_buffer(vbuf);1404 1405	if (buf->flags & HFI_BUFFERFLAG_READONLY) {1406		list_add_tail(&buf->ref_list, &inst->delayed_process);1407		schedule_work(&inst->delayed_process_work);1408		return 1;1409	}1410 1411	return 0;1412}1413 1414struct vb2_v4l2_buffer *1415venus_helper_find_buf(struct venus_inst *inst, unsigned int type, u32 idx)1416{1417	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;1418 1419	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)1420		return v4l2_m2m_src_buf_remove_by_idx(m2m_ctx, idx);1421	else1422		return v4l2_m2m_dst_buf_remove_by_idx(m2m_ctx, idx);1423}1424EXPORT_SYMBOL_GPL(venus_helper_find_buf);1425 1426void venus_helper_change_dpb_owner(struct venus_inst *inst,1427				   struct vb2_v4l2_buffer *vbuf, unsigned int type,1428				   unsigned int buf_type, u32 tag)1429{1430	struct intbuf *dpb_buf;1431 1432	if (!V4L2_TYPE_IS_CAPTURE(type) ||1433	    buf_type != inst->dpb_buftype)1434		return;1435 1436	list_for_each_entry(dpb_buf, &inst->dpbbufs, list)1437		if (dpb_buf->dpb_out_tag == tag) {1438			dpb_buf->owned_by = DRIVER;1439			break;1440		}1441}1442EXPORT_SYMBOL_GPL(venus_helper_change_dpb_owner);1443 1444int venus_helper_vb2_buf_init(struct vb2_buffer *vb)1445{1446	struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);1447	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);1448	struct venus_buffer *buf = to_venus_buffer(vbuf);1449 1450	buf->size = vb2_plane_size(vb, 0);1451	buf->dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);1452 1453	if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)1454		list_add_tail(&buf->reg_list, &inst->registeredbufs);1455 1456	return 0;1457}1458EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_init);1459 1460int venus_helper_vb2_buf_prepare(struct vb2_buffer *vb)1461{1462	struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);1463	unsigned int out_buf_size = venus_helper_get_opb_size(inst);1464	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);1465 1466	if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {1467		if (vbuf->field == V4L2_FIELD_ANY)1468			vbuf->field = V4L2_FIELD_NONE;1469		if (vbuf->field != V4L2_FIELD_NONE) {1470			dev_err(inst->core->dev, "%s field isn't supported\n",1471				__func__);1472			return -EINVAL;1473		}1474	}1475 1476	if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&1477	    vb2_plane_size(vb, 0) < out_buf_size)1478		return -EINVAL;1479	if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&1480	    vb2_plane_size(vb, 0) < inst->input_buf_size)1481		return -EINVAL;1482 1483	return 0;1484}1485EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_prepare);1486 1487static void cache_payload(struct venus_inst *inst, struct vb2_buffer *vb)1488{1489	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);1490	unsigned int idx = vbuf->vb2_buf.index;1491 1492	if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)1493		inst->payloads[idx] = vb2_get_plane_payload(vb, 0);1494}1495 1496void venus_helper_vb2_buf_queue(struct vb2_buffer *vb)1497{1498	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);1499	struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);1500	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;1501	int ret;1502 1503	v4l2_m2m_buf_queue(m2m_ctx, vbuf);1504 1505	/* Skip processing queued capture buffers after LAST flag */1506	if (inst->session_type == VIDC_SESSION_TYPE_DEC &&1507	    V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) &&1508	    inst->codec_state == VENUS_DEC_STATE_DRC)1509		return;1510 1511	cache_payload(inst, vb);1512 1513	if (inst->session_type == VIDC_SESSION_TYPE_ENC &&1514	    !(inst->streamon_out && inst->streamon_cap))1515		return;1516 1517	if (vb2_start_streaming_called(vb->vb2_queue)) {1518		ret = is_buf_refed(inst, vbuf);1519		if (ret)1520			return;1521 1522		ret = session_process_buf(inst, vbuf);1523		if (ret)1524			return_buf_error(inst, vbuf);1525	}1526}1527EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_queue);1528 1529void venus_helper_buffers_done(struct venus_inst *inst, unsigned int type,1530			       enum vb2_buffer_state state)1531{1532	struct vb2_v4l2_buffer *buf;1533 1534	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {1535		while ((buf = v4l2_m2m_src_buf_remove(inst->m2m_ctx)))1536			v4l2_m2m_buf_done(buf, state);1537	} else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {1538		while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx)))1539			v4l2_m2m_buf_done(buf, state);1540	}1541}1542EXPORT_SYMBOL_GPL(venus_helper_buffers_done);1543 1544void venus_helper_vb2_stop_streaming(struct vb2_queue *q)1545{1546	struct venus_inst *inst = vb2_get_drv_priv(q);1547	struct venus_core *core = inst->core;1548	int ret;1549 1550	mutex_lock(&inst->lock);1551 1552	if (inst->streamon_out & inst->streamon_cap) {1553		ret = hfi_session_stop(inst);1554		ret |= hfi_session_unload_res(inst);1555		ret |= venus_helper_unregister_bufs(inst);1556		ret |= venus_helper_intbufs_free(inst);1557		ret |= hfi_session_deinit(inst);1558 1559		if (inst->session_error || test_bit(0, &core->sys_error))1560			ret = -EIO;1561 1562		if (ret)1563			hfi_session_abort(inst);1564 1565		venus_helper_free_dpb_bufs(inst);1566 1567		venus_pm_load_scale(inst);1568		INIT_LIST_HEAD(&inst->registeredbufs);1569	}1570 1571	venus_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,1572				  VB2_BUF_STATE_ERROR);1573	venus_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,1574				  VB2_BUF_STATE_ERROR);1575 1576	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)1577		inst->streamon_out = 0;1578	else1579		inst->streamon_cap = 0;1580 1581	venus_pm_release_core(inst);1582 1583	inst->session_error = 0;1584 1585	mutex_unlock(&inst->lock);1586}1587EXPORT_SYMBOL_GPL(venus_helper_vb2_stop_streaming);1588 1589void venus_helper_vb2_queue_error(struct venus_inst *inst)1590{1591	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;1592	struct vb2_queue *q;1593 1594	q = v4l2_m2m_get_src_vq(m2m_ctx);1595	vb2_queue_error(q);1596	q = v4l2_m2m_get_dst_vq(m2m_ctx);1597	vb2_queue_error(q);1598}1599EXPORT_SYMBOL_GPL(venus_helper_vb2_queue_error);1600 1601int venus_helper_process_initial_cap_bufs(struct venus_inst *inst)1602{1603	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;1604	struct v4l2_m2m_buffer *buf, *n;1605	int ret;1606 1607	v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) {1608		ret = session_process_buf(inst, &buf->vb);1609		if (ret) {1610			return_buf_error(inst, &buf->vb);1611			return ret;1612		}1613	}1614 1615	return 0;1616}1617EXPORT_SYMBOL_GPL(venus_helper_process_initial_cap_bufs);1618 1619int venus_helper_process_initial_out_bufs(struct venus_inst *inst)1620{1621	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;1622	struct v4l2_m2m_buffer *buf, *n;1623	int ret;1624 1625	v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) {1626		ret = session_process_buf(inst, &buf->vb);1627		if (ret) {1628			return_buf_error(inst, &buf->vb);1629			return ret;1630		}1631	}1632 1633	return 0;1634}1635EXPORT_SYMBOL_GPL(venus_helper_process_initial_out_bufs);1636 1637int venus_helper_vb2_start_streaming(struct venus_inst *inst)1638{1639	int ret;1640 1641	ret = venus_helper_intbufs_alloc(inst);1642	if (ret)1643		return ret;1644 1645	ret = session_register_bufs(inst);1646	if (ret)1647		goto err_bufs_free;1648 1649	venus_pm_load_scale(inst);1650 1651	ret = hfi_session_load_res(inst);1652	if (ret)1653		goto err_unreg_bufs;1654 1655	ret = hfi_session_start(inst);1656	if (ret)1657		goto err_unload_res;1658 1659	return 0;1660 1661err_unload_res:1662	hfi_session_unload_res(inst);1663err_unreg_bufs:1664	venus_helper_unregister_bufs(inst);1665err_bufs_free:1666	venus_helper_intbufs_free(inst);1667	return ret;1668}1669EXPORT_SYMBOL_GPL(venus_helper_vb2_start_streaming);1670 1671void venus_helper_m2m_device_run(void *priv)1672{1673	struct venus_inst *inst = priv;1674	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;1675	struct v4l2_m2m_buffer *buf, *n;1676	int ret;1677 1678	mutex_lock(&inst->lock);1679 1680	v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) {1681		ret = session_process_buf(inst, &buf->vb);1682		if (ret)1683			return_buf_error(inst, &buf->vb);1684	}1685 1686	v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) {1687		ret = session_process_buf(inst, &buf->vb);1688		if (ret)1689			return_buf_error(inst, &buf->vb);1690	}1691 1692	mutex_unlock(&inst->lock);1693}1694EXPORT_SYMBOL_GPL(venus_helper_m2m_device_run);1695 1696void venus_helper_m2m_job_abort(void *priv)1697{1698	struct venus_inst *inst = priv;1699 1700	v4l2_m2m_job_finish(inst->m2m_dev, inst->m2m_ctx);1701}1702EXPORT_SYMBOL_GPL(venus_helper_m2m_job_abort);1703 1704int venus_helper_session_init(struct venus_inst *inst)1705{1706	enum hfi_version version = inst->core->res->hfi_version;1707	u32 session_type = inst->session_type;1708	u32 codec;1709	int ret;1710 1711	codec = inst->session_type == VIDC_SESSION_TYPE_DEC ?1712			inst->fmt_out->pixfmt : inst->fmt_cap->pixfmt;1713 1714	ret = hfi_session_init(inst, codec);1715	if (ret)1716		return ret;1717 1718	inst->clk_data.vpp_freq = hfi_platform_get_codec_vpp_freq(version, codec,1719								  session_type);1720	inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(version, codec,1721								  session_type);1722	inst->clk_data.low_power_freq = hfi_platform_get_codec_lp_freq(version, codec,1723								       session_type);1724 1725	return 0;1726}1727EXPORT_SYMBOL_GPL(venus_helper_session_init);1728 1729void venus_helper_init_instance(struct venus_inst *inst)1730{1731	if (inst->session_type == VIDC_SESSION_TYPE_DEC) {1732		INIT_LIST_HEAD(&inst->delayed_process);1733		INIT_WORK(&inst->delayed_process_work,1734			  delayed_process_buf_func);1735	}1736}1737EXPORT_SYMBOL_GPL(venus_helper_init_instance);1738 1739static bool find_fmt_from_caps(struct hfi_plat_caps *caps, u32 buftype, u32 fmt)1740{1741	unsigned int i;1742 1743	for (i = 0; i < caps->num_fmts; i++) {1744		if (caps->fmts[i].buftype == buftype &&1745		    caps->fmts[i].fmt == fmt)1746			return true;1747	}1748 1749	return false;1750}1751 1752int venus_helper_get_out_fmts(struct venus_inst *inst, u32 v4l2_fmt,1753			      u32 *out_fmt, u32 *out2_fmt, bool ubwc)1754{1755	struct venus_core *core = inst->core;1756	struct hfi_plat_caps *caps;1757	u32 ubwc_fmt, fmt = to_hfi_raw_fmt(v4l2_fmt);1758	bool found, found_ubwc;1759 1760	*out_fmt = *out2_fmt = 0;1761 1762	if (!fmt)1763		return -EINVAL;1764 1765	caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);1766	if (!caps)1767		return -EINVAL;1768 1769	if (inst->bit_depth == VIDC_BITDEPTH_10 && inst->session_type == VIDC_SESSION_TYPE_DEC) {1770		found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,1771						HFI_COLOR_FORMAT_YUV420_TP10_UBWC);1772		found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);1773		if (found_ubwc && found) {1774			/*1775			 * Hard-code DPB buffers to be 10bit UBWC1776			 * until V4L2 is able to expose compressed/tiled1777			 * formats to applications.1778			 */1779			*out_fmt = HFI_COLOR_FORMAT_YUV420_TP10_UBWC;1780			*out2_fmt = fmt;1781			return 0;1782		}1783	}1784 1785	if (ubwc) {1786		ubwc_fmt = fmt | HFI_COLOR_FORMAT_UBWC_BASE;1787		found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,1788						ubwc_fmt);1789		found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);1790 1791		if (found_ubwc && found) {1792			*out_fmt = ubwc_fmt;1793			*out2_fmt = fmt;1794			return 0;1795		}1796	}1797 1798	found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, fmt);1799	if (found) {1800		*out_fmt = fmt;1801		*out2_fmt = 0;1802		return 0;1803	}1804 1805	found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);1806	if (found) {1807		*out_fmt = 0;1808		*out2_fmt = fmt;1809		return 0;1810	}1811 1812	return -EINVAL;1813}1814EXPORT_SYMBOL_GPL(venus_helper_get_out_fmts);1815 1816bool venus_helper_check_format(struct venus_inst *inst, u32 v4l2_pixfmt)1817{1818	struct venus_core *core = inst->core;1819	u32 fmt = to_hfi_raw_fmt(v4l2_pixfmt);1820	struct hfi_plat_caps *caps;1821	bool found;1822 1823	if (!fmt)1824		return false;1825 1826	caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);1827	if (!caps)1828		return false;1829 1830	found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, fmt);1831	if (found)1832		goto done;1833 1834	found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);1835done:1836	return found;1837}1838EXPORT_SYMBOL_GPL(venus_helper_check_format);1839 1840int venus_helper_set_stride(struct venus_inst *inst,1841			    unsigned int width, unsigned int height)1842{1843	const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO;1844 1845	struct hfi_uncompressed_plane_actual_info plane_actual_info;1846 1847	plane_actual_info.buffer_type = HFI_BUFFER_INPUT;1848	plane_actual_info.num_planes = 2;1849	plane_actual_info.plane_format[0].actual_stride = width;1850	plane_actual_info.plane_format[0].actual_plane_buffer_height = height;1851	plane_actual_info.plane_format[1].actual_stride = width;1852	plane_actual_info.plane_format[1].actual_plane_buffer_height = height / 2;1853 1854	return hfi_session_set_property(inst, ptype, &plane_actual_info);1855}1856EXPORT_SYMBOL_GPL(venus_helper_set_stride);1857