cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

helpers.c (49366B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      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_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	else
    442		v4l2_m2m_dst_buf_remove_by_buf(m2m_ctx, vbuf);
    443
    444	v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
    445}
    446
    447static void
    448put_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 int
    499session_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	int ret;
    506
    507	memset(&fdata, 0, sizeof(fdata));
    508	fdata.alloc_len = buf->size;
    509	fdata.device_addr = buf->dma_addr;
    510	fdata.timestamp = vb->timestamp;
    511	do_div(fdata.timestamp, NSEC_PER_USEC);
    512	fdata.flags = 0;
    513	fdata.clnt_data = vbuf->vb2_buf.index;
    514
    515	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
    516		fdata.buffer_type = HFI_BUFFER_INPUT;
    517		fdata.filled_len = vb2_get_plane_payload(vb, 0);
    518		fdata.offset = vb->planes[0].data_offset;
    519
    520		if (vbuf->flags & V4L2_BUF_FLAG_LAST || !fdata.filled_len)
    521			fdata.flags |= HFI_BUFFERFLAG_EOS;
    522
    523		if (inst->session_type == VIDC_SESSION_TYPE_DEC)
    524			put_ts_metadata(inst, vbuf);
    525
    526		venus_pm_load_scale(inst);
    527	} else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
    528		if (inst->session_type == VIDC_SESSION_TYPE_ENC)
    529			fdata.buffer_type = HFI_BUFFER_OUTPUT;
    530		else
    531			fdata.buffer_type = inst->opb_buftype;
    532		fdata.filled_len = 0;
    533		fdata.offset = 0;
    534	}
    535
    536	ret = hfi_session_process_buf(inst, &fdata);
    537	if (ret)
    538		return ret;
    539
    540	return 0;
    541}
    542
    543static bool is_dynamic_bufmode(struct venus_inst *inst)
    544{
    545	struct venus_core *core = inst->core;
    546	struct hfi_plat_caps *caps;
    547
    548	/*
    549	 * v4 doesn't send BUFFER_ALLOC_MODE_SUPPORTED property and supports
    550	 * dynamic buffer mode by default for HFI_BUFFER_OUTPUT/OUTPUT2.
    551	 */
    552	if (IS_V4(core) || IS_V6(core))
    553		return true;
    554
    555	caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);
    556	if (!caps)
    557		return false;
    558
    559	return caps->cap_bufs_mode_dynamic;
    560}
    561
    562int venus_helper_unregister_bufs(struct venus_inst *inst)
    563{
    564	struct venus_buffer *buf, *n;
    565	struct hfi_buffer_desc bd;
    566	int ret = 0;
    567
    568	if (is_dynamic_bufmode(inst))
    569		return 0;
    570
    571	list_for_each_entry_safe(buf, n, &inst->registeredbufs, reg_list) {
    572		fill_buffer_desc(buf, &bd, true);
    573		ret = hfi_session_unset_buffers(inst, &bd);
    574		list_del_init(&buf->reg_list);
    575	}
    576
    577	return ret;
    578}
    579EXPORT_SYMBOL_GPL(venus_helper_unregister_bufs);
    580
    581static int session_register_bufs(struct venus_inst *inst)
    582{
    583	struct venus_core *core = inst->core;
    584	struct device *dev = core->dev;
    585	struct hfi_buffer_desc bd;
    586	struct venus_buffer *buf;
    587	int ret = 0;
    588
    589	if (is_dynamic_bufmode(inst))
    590		return 0;
    591
    592	list_for_each_entry(buf, &inst->registeredbufs, reg_list) {
    593		fill_buffer_desc(buf, &bd, false);
    594		ret = hfi_session_set_buffers(inst, &bd);
    595		if (ret) {
    596			dev_err(dev, "%s: set buffer failed\n", __func__);
    597			break;
    598		}
    599	}
    600
    601	return ret;
    602}
    603
    604static u32 to_hfi_raw_fmt(u32 v4l2_fmt)
    605{
    606	switch (v4l2_fmt) {
    607	case V4L2_PIX_FMT_NV12:
    608		return HFI_COLOR_FORMAT_NV12;
    609	case V4L2_PIX_FMT_NV21:
    610		return HFI_COLOR_FORMAT_NV21;
    611	case V4L2_PIX_FMT_QC08C:
    612		return HFI_COLOR_FORMAT_NV12_UBWC;
    613	case V4L2_PIX_FMT_QC10C:
    614		return HFI_COLOR_FORMAT_YUV420_TP10_UBWC;
    615	default:
    616		break;
    617	}
    618
    619	return 0;
    620}
    621
    622static int platform_get_bufreq(struct venus_inst *inst, u32 buftype,
    623			       struct hfi_buffer_requirements *req)
    624{
    625	enum hfi_version version = inst->core->res->hfi_version;
    626	const struct hfi_platform *hfi_plat;
    627	struct hfi_plat_buffers_params params;
    628	bool is_dec = inst->session_type == VIDC_SESSION_TYPE_DEC;
    629	struct venc_controls *enc_ctr = &inst->controls.enc;
    630
    631	hfi_plat = hfi_platform_get(version);
    632
    633	if (!hfi_plat || !hfi_plat->bufreq)
    634		return -EINVAL;
    635
    636	params.version = version;
    637	params.num_vpp_pipes = inst->core->res->num_vpp_pipes;
    638
    639	if (is_dec) {
    640		params.width = inst->width;
    641		params.height = inst->height;
    642		params.codec = inst->fmt_out->pixfmt;
    643		params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_cap->pixfmt);
    644		params.dec.max_mbs_per_frame = mbs_per_frame_max(inst);
    645		params.dec.buffer_size_limit = 0;
    646		params.dec.is_secondary_output =
    647			inst->opb_buftype == HFI_BUFFER_OUTPUT2;
    648		params.dec.is_interlaced =
    649			inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE;
    650	} else {
    651		params.width = inst->out_width;
    652		params.height = inst->out_height;
    653		params.codec = inst->fmt_cap->pixfmt;
    654		params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_out->pixfmt);
    655		params.enc.work_mode = VIDC_WORK_MODE_2;
    656		params.enc.rc_type = HFI_RATE_CONTROL_OFF;
    657		if (enc_ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
    658			params.enc.rc_type = HFI_RATE_CONTROL_CQ;
    659		params.enc.num_b_frames = enc_ctr->num_b_frames;
    660		params.enc.is_tenbit = inst->bit_depth == VIDC_BITDEPTH_10;
    661	}
    662
    663	return hfi_plat->bufreq(&params, inst->session_type, buftype, req);
    664}
    665
    666int venus_helper_get_bufreq(struct venus_inst *inst, u32 type,
    667			    struct hfi_buffer_requirements *req)
    668{
    669	u32 ptype = HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS;
    670	union hfi_get_property hprop;
    671	unsigned int i;
    672	int ret;
    673
    674	if (req)
    675		memset(req, 0, sizeof(*req));
    676
    677	if (type == HFI_BUFFER_OUTPUT || type == HFI_BUFFER_OUTPUT2)
    678		req->count_min = inst->fw_min_cnt;
    679
    680	ret = platform_get_bufreq(inst, type, req);
    681	if (!ret) {
    682		if (type == HFI_BUFFER_OUTPUT || type == HFI_BUFFER_OUTPUT2)
    683			inst->fw_min_cnt = req->count_min;
    684		return 0;
    685	}
    686
    687	ret = hfi_session_get_property(inst, ptype, &hprop);
    688	if (ret)
    689		return ret;
    690
    691	ret = -EINVAL;
    692
    693	for (i = 0; i < HFI_BUFFER_TYPE_MAX; i++) {
    694		if (hprop.bufreq[i].type != type)
    695			continue;
    696
    697		if (req)
    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 void
    850v4l2_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 void
    886hfi_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, 256);
    994	uv_stride = ALIGN(width * 2, 256);
    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(ALIGN(width, 192) * 4 / 3, 256);
   1042	uv_stride = ALIGN(ALIGN(width, 192) * 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	else
   1272		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	else
   1422		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	else
   1579		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 (ubwc) {
   1770		ubwc_fmt = fmt | HFI_COLOR_FORMAT_UBWC_BASE;
   1771		found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,
   1772						ubwc_fmt);
   1773		found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);
   1774
   1775		if (found_ubwc && found) {
   1776			*out_fmt = ubwc_fmt;
   1777			*out2_fmt = fmt;
   1778			return 0;
   1779		}
   1780	}
   1781
   1782	found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, fmt);
   1783	if (found) {
   1784		*out_fmt = fmt;
   1785		*out2_fmt = 0;
   1786		return 0;
   1787	}
   1788
   1789	found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);
   1790	if (found) {
   1791		*out_fmt = 0;
   1792		*out2_fmt = fmt;
   1793		return 0;
   1794	}
   1795
   1796	return -EINVAL;
   1797}
   1798EXPORT_SYMBOL_GPL(venus_helper_get_out_fmts);
   1799
   1800bool venus_helper_check_format(struct venus_inst *inst, u32 v4l2_pixfmt)
   1801{
   1802	struct venus_core *core = inst->core;
   1803	u32 fmt = to_hfi_raw_fmt(v4l2_pixfmt);
   1804	struct hfi_plat_caps *caps;
   1805	u32 buftype;
   1806
   1807	if (!fmt)
   1808		return false;
   1809
   1810	caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);
   1811	if (!caps)
   1812		return false;
   1813
   1814	if (inst->session_type == VIDC_SESSION_TYPE_DEC)
   1815		buftype = HFI_BUFFER_OUTPUT2;
   1816	else
   1817		buftype = HFI_BUFFER_OUTPUT;
   1818
   1819	return find_fmt_from_caps(caps, buftype, fmt);
   1820}
   1821EXPORT_SYMBOL_GPL(venus_helper_check_format);
   1822
   1823int venus_helper_set_stride(struct venus_inst *inst,
   1824			    unsigned int width, unsigned int height)
   1825{
   1826	const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO;
   1827
   1828	struct hfi_uncompressed_plane_actual_info plane_actual_info;
   1829
   1830	plane_actual_info.buffer_type = HFI_BUFFER_INPUT;
   1831	plane_actual_info.num_planes = 2;
   1832	plane_actual_info.plane_format[0].actual_stride = width;
   1833	plane_actual_info.plane_format[0].actual_plane_buffer_height = height;
   1834	plane_actual_info.plane_format[1].actual_stride = width;
   1835	plane_actual_info.plane_format[1].actual_plane_buffer_height = height / 2;
   1836
   1837	return hfi_session_set_property(inst, ptype, &plane_actual_info);
   1838}
   1839EXPORT_SYMBOL_GPL(venus_helper_set_stride);