162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. 462306a36Sopenharmony_ci * Copyright (C) 2017 Linaro Ltd. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#include <linux/idr.h> 762306a36Sopenharmony_ci#include <linux/list.h> 862306a36Sopenharmony_ci#include <linux/mutex.h> 962306a36Sopenharmony_ci#include <linux/slab.h> 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <media/videobuf2-dma-contig.h> 1262306a36Sopenharmony_ci#include <media/v4l2-mem2mem.h> 1362306a36Sopenharmony_ci#include <asm/div64.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "core.h" 1662306a36Sopenharmony_ci#include "helpers.h" 1762306a36Sopenharmony_ci#include "hfi_helper.h" 1862306a36Sopenharmony_ci#include "pm_helpers.h" 1962306a36Sopenharmony_ci#include "hfi_platform.h" 2062306a36Sopenharmony_ci#include "hfi_parser.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define NUM_MBS_720P (((ALIGN(1280, 16)) >> 4) * ((ALIGN(736, 16)) >> 4)) 2362306a36Sopenharmony_ci#define NUM_MBS_4K (((ALIGN(4096, 16)) >> 4) * ((ALIGN(2304, 16)) >> 4)) 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cienum dpb_buf_owner { 2662306a36Sopenharmony_ci DRIVER, 2762306a36Sopenharmony_ci FIRMWARE, 2862306a36Sopenharmony_ci}; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistruct intbuf { 3162306a36Sopenharmony_ci struct list_head list; 3262306a36Sopenharmony_ci u32 type; 3362306a36Sopenharmony_ci size_t size; 3462306a36Sopenharmony_ci void *va; 3562306a36Sopenharmony_ci dma_addr_t da; 3662306a36Sopenharmony_ci unsigned long attrs; 3762306a36Sopenharmony_ci enum dpb_buf_owner owned_by; 3862306a36Sopenharmony_ci u32 dpb_out_tag; 3962306a36Sopenharmony_ci}; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cibool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci struct venus_core *core = inst->core; 4462306a36Sopenharmony_ci u32 session_type = inst->session_type; 4562306a36Sopenharmony_ci u32 codec; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci switch (v4l2_pixfmt) { 4862306a36Sopenharmony_ci case V4L2_PIX_FMT_H264: 4962306a36Sopenharmony_ci codec = HFI_VIDEO_CODEC_H264; 5062306a36Sopenharmony_ci break; 5162306a36Sopenharmony_ci case V4L2_PIX_FMT_H263: 5262306a36Sopenharmony_ci codec = HFI_VIDEO_CODEC_H263; 5362306a36Sopenharmony_ci break; 5462306a36Sopenharmony_ci case V4L2_PIX_FMT_MPEG1: 5562306a36Sopenharmony_ci codec = HFI_VIDEO_CODEC_MPEG1; 5662306a36Sopenharmony_ci break; 5762306a36Sopenharmony_ci case V4L2_PIX_FMT_MPEG2: 5862306a36Sopenharmony_ci codec = HFI_VIDEO_CODEC_MPEG2; 5962306a36Sopenharmony_ci break; 6062306a36Sopenharmony_ci case V4L2_PIX_FMT_MPEG4: 6162306a36Sopenharmony_ci codec = HFI_VIDEO_CODEC_MPEG4; 6262306a36Sopenharmony_ci break; 6362306a36Sopenharmony_ci case V4L2_PIX_FMT_VC1_ANNEX_G: 6462306a36Sopenharmony_ci case V4L2_PIX_FMT_VC1_ANNEX_L: 6562306a36Sopenharmony_ci codec = HFI_VIDEO_CODEC_VC1; 6662306a36Sopenharmony_ci break; 6762306a36Sopenharmony_ci case V4L2_PIX_FMT_VP8: 6862306a36Sopenharmony_ci codec = HFI_VIDEO_CODEC_VP8; 6962306a36Sopenharmony_ci break; 7062306a36Sopenharmony_ci case V4L2_PIX_FMT_VP9: 7162306a36Sopenharmony_ci codec = HFI_VIDEO_CODEC_VP9; 7262306a36Sopenharmony_ci break; 7362306a36Sopenharmony_ci case V4L2_PIX_FMT_XVID: 7462306a36Sopenharmony_ci codec = HFI_VIDEO_CODEC_DIVX; 7562306a36Sopenharmony_ci break; 7662306a36Sopenharmony_ci case V4L2_PIX_FMT_HEVC: 7762306a36Sopenharmony_ci codec = HFI_VIDEO_CODEC_HEVC; 7862306a36Sopenharmony_ci break; 7962306a36Sopenharmony_ci default: 8062306a36Sopenharmony_ci return false; 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci if (session_type == VIDC_SESSION_TYPE_ENC && core->enc_codecs & codec) 8462306a36Sopenharmony_ci return true; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci if (session_type == VIDC_SESSION_TYPE_DEC && core->dec_codecs & codec) 8762306a36Sopenharmony_ci return true; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci return false; 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_check_codec); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic void free_dpb_buf(struct venus_inst *inst, struct intbuf *buf) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci ida_free(&inst->dpb_ids, buf->dpb_out_tag); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci list_del_init(&buf->list); 9862306a36Sopenharmony_ci dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da, 9962306a36Sopenharmony_ci buf->attrs); 10062306a36Sopenharmony_ci kfree(buf); 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ciint venus_helper_queue_dpb_bufs(struct venus_inst *inst) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci struct intbuf *buf, *next; 10662306a36Sopenharmony_ci unsigned int dpb_size = 0; 10762306a36Sopenharmony_ci int ret = 0; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if (inst->dpb_buftype == HFI_BUFFER_OUTPUT) 11062306a36Sopenharmony_ci dpb_size = inst->output_buf_size; 11162306a36Sopenharmony_ci else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2) 11262306a36Sopenharmony_ci dpb_size = inst->output2_buf_size; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci list_for_each_entry_safe(buf, next, &inst->dpbbufs, list) { 11562306a36Sopenharmony_ci struct hfi_frame_data fdata; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci memset(&fdata, 0, sizeof(fdata)); 11862306a36Sopenharmony_ci fdata.alloc_len = buf->size; 11962306a36Sopenharmony_ci fdata.device_addr = buf->da; 12062306a36Sopenharmony_ci fdata.buffer_type = buf->type; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci if (buf->owned_by == FIRMWARE) 12362306a36Sopenharmony_ci continue; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci /* free buffer from previous sequence which was released later */ 12662306a36Sopenharmony_ci if (dpb_size > buf->size) { 12762306a36Sopenharmony_ci free_dpb_buf(inst, buf); 12862306a36Sopenharmony_ci continue; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci fdata.clnt_data = buf->dpb_out_tag; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci ret = hfi_session_process_buf(inst, &fdata); 13462306a36Sopenharmony_ci if (ret) 13562306a36Sopenharmony_ci goto fail; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci buf->owned_by = FIRMWARE; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cifail: 14162306a36Sopenharmony_ci return ret; 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_queue_dpb_bufs); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ciint venus_helper_free_dpb_bufs(struct venus_inst *inst) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci struct intbuf *buf, *n; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci list_for_each_entry_safe(buf, n, &inst->dpbbufs, list) { 15062306a36Sopenharmony_ci if (buf->owned_by == FIRMWARE) 15162306a36Sopenharmony_ci continue; 15262306a36Sopenharmony_ci free_dpb_buf(inst, buf); 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci if (list_empty(&inst->dpbbufs)) 15662306a36Sopenharmony_ci INIT_LIST_HEAD(&inst->dpbbufs); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci return 0; 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_free_dpb_bufs); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ciint venus_helper_alloc_dpb_bufs(struct venus_inst *inst) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci struct venus_core *core = inst->core; 16562306a36Sopenharmony_ci struct device *dev = core->dev; 16662306a36Sopenharmony_ci enum hfi_version ver = core->res->hfi_version; 16762306a36Sopenharmony_ci struct hfi_buffer_requirements bufreq; 16862306a36Sopenharmony_ci u32 buftype = inst->dpb_buftype; 16962306a36Sopenharmony_ci unsigned int dpb_size = 0; 17062306a36Sopenharmony_ci struct intbuf *buf; 17162306a36Sopenharmony_ci unsigned int i; 17262306a36Sopenharmony_ci u32 count; 17362306a36Sopenharmony_ci int ret; 17462306a36Sopenharmony_ci int id; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci /* no need to allocate dpb buffers */ 17762306a36Sopenharmony_ci if (!inst->dpb_fmt) 17862306a36Sopenharmony_ci return 0; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci if (inst->dpb_buftype == HFI_BUFFER_OUTPUT) 18162306a36Sopenharmony_ci dpb_size = inst->output_buf_size; 18262306a36Sopenharmony_ci else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2) 18362306a36Sopenharmony_ci dpb_size = inst->output2_buf_size; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci if (!dpb_size) 18662306a36Sopenharmony_ci return 0; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci ret = venus_helper_get_bufreq(inst, buftype, &bufreq); 18962306a36Sopenharmony_ci if (ret) 19062306a36Sopenharmony_ci return ret; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci count = hfi_bufreq_get_count_min(&bufreq, ver); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci for (i = 0; i < count; i++) { 19562306a36Sopenharmony_ci buf = kzalloc(sizeof(*buf), GFP_KERNEL); 19662306a36Sopenharmony_ci if (!buf) { 19762306a36Sopenharmony_ci ret = -ENOMEM; 19862306a36Sopenharmony_ci goto fail; 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci buf->type = buftype; 20262306a36Sopenharmony_ci buf->size = dpb_size; 20362306a36Sopenharmony_ci buf->attrs = DMA_ATTR_WRITE_COMBINE | 20462306a36Sopenharmony_ci DMA_ATTR_NO_KERNEL_MAPPING; 20562306a36Sopenharmony_ci buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL, 20662306a36Sopenharmony_ci buf->attrs); 20762306a36Sopenharmony_ci if (!buf->va) { 20862306a36Sopenharmony_ci ret = -ENOMEM; 20962306a36Sopenharmony_ci goto fail; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci buf->owned_by = DRIVER; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci id = ida_alloc_min(&inst->dpb_ids, VB2_MAX_FRAME, GFP_KERNEL); 21462306a36Sopenharmony_ci if (id < 0) { 21562306a36Sopenharmony_ci ret = id; 21662306a36Sopenharmony_ci goto fail; 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci buf->dpb_out_tag = id; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci list_add_tail(&buf->list, &inst->dpbbufs); 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci return 0; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cifail: 22762306a36Sopenharmony_ci kfree(buf); 22862306a36Sopenharmony_ci venus_helper_free_dpb_bufs(inst); 22962306a36Sopenharmony_ci return ret; 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_alloc_dpb_bufs); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cistatic int intbufs_set_buffer(struct venus_inst *inst, u32 type) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci struct venus_core *core = inst->core; 23662306a36Sopenharmony_ci struct device *dev = core->dev; 23762306a36Sopenharmony_ci struct hfi_buffer_requirements bufreq; 23862306a36Sopenharmony_ci struct hfi_buffer_desc bd; 23962306a36Sopenharmony_ci struct intbuf *buf; 24062306a36Sopenharmony_ci unsigned int i; 24162306a36Sopenharmony_ci int ret; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci ret = venus_helper_get_bufreq(inst, type, &bufreq); 24462306a36Sopenharmony_ci if (ret) 24562306a36Sopenharmony_ci return 0; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci if (!bufreq.size) 24862306a36Sopenharmony_ci return 0; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci for (i = 0; i < bufreq.count_actual; i++) { 25162306a36Sopenharmony_ci buf = kzalloc(sizeof(*buf), GFP_KERNEL); 25262306a36Sopenharmony_ci if (!buf) { 25362306a36Sopenharmony_ci ret = -ENOMEM; 25462306a36Sopenharmony_ci goto fail; 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci buf->type = bufreq.type; 25862306a36Sopenharmony_ci buf->size = bufreq.size; 25962306a36Sopenharmony_ci buf->attrs = DMA_ATTR_WRITE_COMBINE | 26062306a36Sopenharmony_ci DMA_ATTR_NO_KERNEL_MAPPING; 26162306a36Sopenharmony_ci buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL, 26262306a36Sopenharmony_ci buf->attrs); 26362306a36Sopenharmony_ci if (!buf->va) { 26462306a36Sopenharmony_ci ret = -ENOMEM; 26562306a36Sopenharmony_ci goto fail; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci memset(&bd, 0, sizeof(bd)); 26962306a36Sopenharmony_ci bd.buffer_size = buf->size; 27062306a36Sopenharmony_ci bd.buffer_type = buf->type; 27162306a36Sopenharmony_ci bd.num_buffers = 1; 27262306a36Sopenharmony_ci bd.device_addr = buf->da; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci ret = hfi_session_set_buffers(inst, &bd); 27562306a36Sopenharmony_ci if (ret) { 27662306a36Sopenharmony_ci dev_err(dev, "set session buffers failed\n"); 27762306a36Sopenharmony_ci goto dma_free; 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci list_add_tail(&buf->list, &inst->internalbufs); 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci return 0; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_cidma_free: 28662306a36Sopenharmony_ci dma_free_attrs(dev, buf->size, buf->va, buf->da, buf->attrs); 28762306a36Sopenharmony_cifail: 28862306a36Sopenharmony_ci kfree(buf); 28962306a36Sopenharmony_ci return ret; 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic int intbufs_unset_buffers(struct venus_inst *inst) 29362306a36Sopenharmony_ci{ 29462306a36Sopenharmony_ci struct hfi_buffer_desc bd = {0}; 29562306a36Sopenharmony_ci struct intbuf *buf, *n; 29662306a36Sopenharmony_ci int ret = 0; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci list_for_each_entry_safe(buf, n, &inst->internalbufs, list) { 29962306a36Sopenharmony_ci bd.buffer_size = buf->size; 30062306a36Sopenharmony_ci bd.buffer_type = buf->type; 30162306a36Sopenharmony_ci bd.num_buffers = 1; 30262306a36Sopenharmony_ci bd.device_addr = buf->da; 30362306a36Sopenharmony_ci bd.response_required = true; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci ret = hfi_session_unset_buffers(inst, &bd); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci list_del_init(&buf->list); 30862306a36Sopenharmony_ci dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da, 30962306a36Sopenharmony_ci buf->attrs); 31062306a36Sopenharmony_ci kfree(buf); 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci return ret; 31462306a36Sopenharmony_ci} 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic const unsigned int intbuf_types_1xx[] = { 31762306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_1XX), 31862306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_1XX), 31962306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_1XX), 32062306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_PERSIST, 32162306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_PERSIST_1, 32262306a36Sopenharmony_ci}; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic const unsigned int intbuf_types_4xx[] = { 32562306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_4XX), 32662306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_4XX), 32762306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_4XX), 32862306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_PERSIST, 32962306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_PERSIST_1, 33062306a36Sopenharmony_ci}; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic const unsigned int intbuf_types_6xx[] = { 33362306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_6XX), 33462306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_6XX), 33562306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_6XX), 33662306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_PERSIST, 33762306a36Sopenharmony_ci HFI_BUFFER_INTERNAL_PERSIST_1, 33862306a36Sopenharmony_ci}; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ciint venus_helper_intbufs_alloc(struct venus_inst *inst) 34162306a36Sopenharmony_ci{ 34262306a36Sopenharmony_ci const unsigned int *intbuf; 34362306a36Sopenharmony_ci size_t arr_sz, i; 34462306a36Sopenharmony_ci int ret; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci if (IS_V6(inst->core)) { 34762306a36Sopenharmony_ci arr_sz = ARRAY_SIZE(intbuf_types_6xx); 34862306a36Sopenharmony_ci intbuf = intbuf_types_6xx; 34962306a36Sopenharmony_ci } else if (IS_V4(inst->core)) { 35062306a36Sopenharmony_ci arr_sz = ARRAY_SIZE(intbuf_types_4xx); 35162306a36Sopenharmony_ci intbuf = intbuf_types_4xx; 35262306a36Sopenharmony_ci } else { 35362306a36Sopenharmony_ci arr_sz = ARRAY_SIZE(intbuf_types_1xx); 35462306a36Sopenharmony_ci intbuf = intbuf_types_1xx; 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci for (i = 0; i < arr_sz; i++) { 35862306a36Sopenharmony_ci ret = intbufs_set_buffer(inst, intbuf[i]); 35962306a36Sopenharmony_ci if (ret) 36062306a36Sopenharmony_ci goto error; 36162306a36Sopenharmony_ci } 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci return 0; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cierror: 36662306a36Sopenharmony_ci intbufs_unset_buffers(inst); 36762306a36Sopenharmony_ci return ret; 36862306a36Sopenharmony_ci} 36962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_intbufs_alloc); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ciint venus_helper_intbufs_free(struct venus_inst *inst) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci return intbufs_unset_buffers(inst); 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_intbufs_free); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ciint venus_helper_intbufs_realloc(struct venus_inst *inst) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci enum hfi_version ver = inst->core->res->hfi_version; 38062306a36Sopenharmony_ci struct hfi_buffer_desc bd; 38162306a36Sopenharmony_ci struct intbuf *buf, *n; 38262306a36Sopenharmony_ci int ret; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci list_for_each_entry_safe(buf, n, &inst->internalbufs, list) { 38562306a36Sopenharmony_ci if (buf->type == HFI_BUFFER_INTERNAL_PERSIST || 38662306a36Sopenharmony_ci buf->type == HFI_BUFFER_INTERNAL_PERSIST_1) 38762306a36Sopenharmony_ci continue; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci memset(&bd, 0, sizeof(bd)); 39062306a36Sopenharmony_ci bd.buffer_size = buf->size; 39162306a36Sopenharmony_ci bd.buffer_type = buf->type; 39262306a36Sopenharmony_ci bd.num_buffers = 1; 39362306a36Sopenharmony_ci bd.device_addr = buf->da; 39462306a36Sopenharmony_ci bd.response_required = true; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci ret = hfi_session_unset_buffers(inst, &bd); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da, 39962306a36Sopenharmony_ci buf->attrs); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci list_del_init(&buf->list); 40262306a36Sopenharmony_ci kfree(buf); 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH(ver)); 40662306a36Sopenharmony_ci if (ret) 40762306a36Sopenharmony_ci goto err; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH_1(ver)); 41062306a36Sopenharmony_ci if (ret) 41162306a36Sopenharmony_ci goto err; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH_2(ver)); 41462306a36Sopenharmony_ci if (ret) 41562306a36Sopenharmony_ci goto err; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci return 0; 41862306a36Sopenharmony_cierr: 41962306a36Sopenharmony_ci return ret; 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_intbufs_realloc); 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistatic void fill_buffer_desc(const struct venus_buffer *buf, 42462306a36Sopenharmony_ci struct hfi_buffer_desc *bd, bool response) 42562306a36Sopenharmony_ci{ 42662306a36Sopenharmony_ci memset(bd, 0, sizeof(*bd)); 42762306a36Sopenharmony_ci bd->buffer_type = HFI_BUFFER_OUTPUT; 42862306a36Sopenharmony_ci bd->buffer_size = buf->size; 42962306a36Sopenharmony_ci bd->num_buffers = 1; 43062306a36Sopenharmony_ci bd->device_addr = buf->dma_addr; 43162306a36Sopenharmony_ci bd->response_required = response; 43262306a36Sopenharmony_ci} 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_cistatic void return_buf_error(struct venus_inst *inst, 43562306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 44062306a36Sopenharmony_ci v4l2_m2m_src_buf_remove_by_buf(m2m_ctx, vbuf); 44162306a36Sopenharmony_ci else 44262306a36Sopenharmony_ci v4l2_m2m_dst_buf_remove_by_buf(m2m_ctx, vbuf); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); 44562306a36Sopenharmony_ci} 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_cistatic void 44862306a36Sopenharmony_ciput_ts_metadata(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) 44962306a36Sopenharmony_ci{ 45062306a36Sopenharmony_ci struct vb2_buffer *vb = &vbuf->vb2_buf; 45162306a36Sopenharmony_ci unsigned int i; 45262306a36Sopenharmony_ci int slot = -1; 45362306a36Sopenharmony_ci u64 ts_us = vb->timestamp; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(inst->tss); i++) { 45662306a36Sopenharmony_ci if (!inst->tss[i].used) { 45762306a36Sopenharmony_ci slot = i; 45862306a36Sopenharmony_ci break; 45962306a36Sopenharmony_ci } 46062306a36Sopenharmony_ci } 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci if (slot == -1) { 46362306a36Sopenharmony_ci dev_dbg(inst->core->dev, VDBGL "no free slot\n"); 46462306a36Sopenharmony_ci return; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci do_div(ts_us, NSEC_PER_USEC); 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci inst->tss[slot].used = true; 47062306a36Sopenharmony_ci inst->tss[slot].flags = vbuf->flags; 47162306a36Sopenharmony_ci inst->tss[slot].tc = vbuf->timecode; 47262306a36Sopenharmony_ci inst->tss[slot].ts_us = ts_us; 47362306a36Sopenharmony_ci inst->tss[slot].ts_ns = vb->timestamp; 47462306a36Sopenharmony_ci} 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_civoid venus_helper_get_ts_metadata(struct venus_inst *inst, u64 timestamp_us, 47762306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf) 47862306a36Sopenharmony_ci{ 47962306a36Sopenharmony_ci struct vb2_buffer *vb = &vbuf->vb2_buf; 48062306a36Sopenharmony_ci unsigned int i; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(inst->tss); ++i) { 48362306a36Sopenharmony_ci if (!inst->tss[i].used) 48462306a36Sopenharmony_ci continue; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci if (inst->tss[i].ts_us != timestamp_us) 48762306a36Sopenharmony_ci continue; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci inst->tss[i].used = false; 49062306a36Sopenharmony_ci vbuf->flags |= inst->tss[i].flags; 49162306a36Sopenharmony_ci vbuf->timecode = inst->tss[i].tc; 49262306a36Sopenharmony_ci vb->timestamp = inst->tss[i].ts_ns; 49362306a36Sopenharmony_ci break; 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_get_ts_metadata); 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_cistatic int 49962306a36Sopenharmony_cisession_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci struct venus_buffer *buf = to_venus_buffer(vbuf); 50262306a36Sopenharmony_ci struct vb2_buffer *vb = &vbuf->vb2_buf; 50362306a36Sopenharmony_ci unsigned int type = vb->type; 50462306a36Sopenharmony_ci struct hfi_frame_data fdata; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci memset(&fdata, 0, sizeof(fdata)); 50762306a36Sopenharmony_ci fdata.alloc_len = buf->size; 50862306a36Sopenharmony_ci fdata.device_addr = buf->dma_addr; 50962306a36Sopenharmony_ci fdata.timestamp = vb->timestamp; 51062306a36Sopenharmony_ci do_div(fdata.timestamp, NSEC_PER_USEC); 51162306a36Sopenharmony_ci fdata.flags = 0; 51262306a36Sopenharmony_ci fdata.clnt_data = vbuf->vb2_buf.index; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 51562306a36Sopenharmony_ci fdata.buffer_type = HFI_BUFFER_INPUT; 51662306a36Sopenharmony_ci fdata.filled_len = vb2_get_plane_payload(vb, 0); 51762306a36Sopenharmony_ci fdata.offset = vb->planes[0].data_offset; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci if (vbuf->flags & V4L2_BUF_FLAG_LAST || !fdata.filled_len) 52062306a36Sopenharmony_ci fdata.flags |= HFI_BUFFERFLAG_EOS; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci if (inst->session_type == VIDC_SESSION_TYPE_DEC) 52362306a36Sopenharmony_ci put_ts_metadata(inst, vbuf); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci venus_pm_load_scale(inst); 52662306a36Sopenharmony_ci } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 52762306a36Sopenharmony_ci if (inst->session_type == VIDC_SESSION_TYPE_ENC) 52862306a36Sopenharmony_ci fdata.buffer_type = HFI_BUFFER_OUTPUT; 52962306a36Sopenharmony_ci else 53062306a36Sopenharmony_ci fdata.buffer_type = inst->opb_buftype; 53162306a36Sopenharmony_ci fdata.filled_len = 0; 53262306a36Sopenharmony_ci fdata.offset = 0; 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci return hfi_session_process_buf(inst, &fdata); 53662306a36Sopenharmony_ci} 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_cistatic bool is_dynamic_bufmode(struct venus_inst *inst) 53962306a36Sopenharmony_ci{ 54062306a36Sopenharmony_ci struct venus_core *core = inst->core; 54162306a36Sopenharmony_ci struct hfi_plat_caps *caps; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci /* 54462306a36Sopenharmony_ci * v4 doesn't send BUFFER_ALLOC_MODE_SUPPORTED property and supports 54562306a36Sopenharmony_ci * dynamic buffer mode by default for HFI_BUFFER_OUTPUT/OUTPUT2. 54662306a36Sopenharmony_ci */ 54762306a36Sopenharmony_ci if (IS_V4(core) || IS_V6(core)) 54862306a36Sopenharmony_ci return true; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type); 55162306a36Sopenharmony_ci if (!caps) 55262306a36Sopenharmony_ci return false; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci return caps->cap_bufs_mode_dynamic; 55562306a36Sopenharmony_ci} 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ciint venus_helper_unregister_bufs(struct venus_inst *inst) 55862306a36Sopenharmony_ci{ 55962306a36Sopenharmony_ci struct venus_buffer *buf, *n; 56062306a36Sopenharmony_ci struct hfi_buffer_desc bd; 56162306a36Sopenharmony_ci int ret = 0; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci if (is_dynamic_bufmode(inst)) 56462306a36Sopenharmony_ci return 0; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci list_for_each_entry_safe(buf, n, &inst->registeredbufs, reg_list) { 56762306a36Sopenharmony_ci fill_buffer_desc(buf, &bd, true); 56862306a36Sopenharmony_ci ret = hfi_session_unset_buffers(inst, &bd); 56962306a36Sopenharmony_ci list_del_init(&buf->reg_list); 57062306a36Sopenharmony_ci } 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci return ret; 57362306a36Sopenharmony_ci} 57462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_unregister_bufs); 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_cistatic int session_register_bufs(struct venus_inst *inst) 57762306a36Sopenharmony_ci{ 57862306a36Sopenharmony_ci struct venus_core *core = inst->core; 57962306a36Sopenharmony_ci struct device *dev = core->dev; 58062306a36Sopenharmony_ci struct hfi_buffer_desc bd; 58162306a36Sopenharmony_ci struct venus_buffer *buf; 58262306a36Sopenharmony_ci int ret = 0; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci if (is_dynamic_bufmode(inst)) 58562306a36Sopenharmony_ci return 0; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci list_for_each_entry(buf, &inst->registeredbufs, reg_list) { 58862306a36Sopenharmony_ci fill_buffer_desc(buf, &bd, false); 58962306a36Sopenharmony_ci ret = hfi_session_set_buffers(inst, &bd); 59062306a36Sopenharmony_ci if (ret) { 59162306a36Sopenharmony_ci dev_err(dev, "%s: set buffer failed\n", __func__); 59262306a36Sopenharmony_ci break; 59362306a36Sopenharmony_ci } 59462306a36Sopenharmony_ci } 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci return ret; 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_cistatic u32 to_hfi_raw_fmt(u32 v4l2_fmt) 60062306a36Sopenharmony_ci{ 60162306a36Sopenharmony_ci switch (v4l2_fmt) { 60262306a36Sopenharmony_ci case V4L2_PIX_FMT_NV12: 60362306a36Sopenharmony_ci return HFI_COLOR_FORMAT_NV12; 60462306a36Sopenharmony_ci case V4L2_PIX_FMT_NV21: 60562306a36Sopenharmony_ci return HFI_COLOR_FORMAT_NV21; 60662306a36Sopenharmony_ci case V4L2_PIX_FMT_QC08C: 60762306a36Sopenharmony_ci return HFI_COLOR_FORMAT_NV12_UBWC; 60862306a36Sopenharmony_ci case V4L2_PIX_FMT_QC10C: 60962306a36Sopenharmony_ci return HFI_COLOR_FORMAT_YUV420_TP10_UBWC; 61062306a36Sopenharmony_ci case V4L2_PIX_FMT_P010: 61162306a36Sopenharmony_ci return HFI_COLOR_FORMAT_P010; 61262306a36Sopenharmony_ci default: 61362306a36Sopenharmony_ci break; 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci return 0; 61762306a36Sopenharmony_ci} 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_cistatic int platform_get_bufreq(struct venus_inst *inst, u32 buftype, 62062306a36Sopenharmony_ci struct hfi_buffer_requirements *req) 62162306a36Sopenharmony_ci{ 62262306a36Sopenharmony_ci enum hfi_version version = inst->core->res->hfi_version; 62362306a36Sopenharmony_ci const struct hfi_platform *hfi_plat; 62462306a36Sopenharmony_ci struct hfi_plat_buffers_params params; 62562306a36Sopenharmony_ci bool is_dec = inst->session_type == VIDC_SESSION_TYPE_DEC; 62662306a36Sopenharmony_ci struct venc_controls *enc_ctr = &inst->controls.enc; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci hfi_plat = hfi_platform_get(version); 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci if (!hfi_plat || !hfi_plat->bufreq) 63162306a36Sopenharmony_ci return -EINVAL; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci params.version = version; 63462306a36Sopenharmony_ci params.num_vpp_pipes = inst->core->res->num_vpp_pipes; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci if (is_dec) { 63762306a36Sopenharmony_ci params.width = inst->width; 63862306a36Sopenharmony_ci params.height = inst->height; 63962306a36Sopenharmony_ci params.out_width = inst->out_width; 64062306a36Sopenharmony_ci params.out_height = inst->out_height; 64162306a36Sopenharmony_ci params.codec = inst->fmt_out->pixfmt; 64262306a36Sopenharmony_ci params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_cap->pixfmt); 64362306a36Sopenharmony_ci params.dec.max_mbs_per_frame = mbs_per_frame_max(inst); 64462306a36Sopenharmony_ci params.dec.buffer_size_limit = 0; 64562306a36Sopenharmony_ci params.dec.is_secondary_output = 64662306a36Sopenharmony_ci inst->opb_buftype == HFI_BUFFER_OUTPUT2; 64762306a36Sopenharmony_ci if (params.dec.is_secondary_output) 64862306a36Sopenharmony_ci params.hfi_dpb_color_fmt = inst->dpb_fmt; 64962306a36Sopenharmony_ci params.dec.is_interlaced = 65062306a36Sopenharmony_ci inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE; 65162306a36Sopenharmony_ci } else { 65262306a36Sopenharmony_ci params.width = inst->out_width; 65362306a36Sopenharmony_ci params.height = inst->out_height; 65462306a36Sopenharmony_ci params.codec = inst->fmt_cap->pixfmt; 65562306a36Sopenharmony_ci params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_out->pixfmt); 65662306a36Sopenharmony_ci params.enc.work_mode = VIDC_WORK_MODE_2; 65762306a36Sopenharmony_ci params.enc.rc_type = HFI_RATE_CONTROL_OFF; 65862306a36Sopenharmony_ci if (enc_ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) 65962306a36Sopenharmony_ci params.enc.rc_type = HFI_RATE_CONTROL_CQ; 66062306a36Sopenharmony_ci params.enc.num_b_frames = enc_ctr->num_b_frames; 66162306a36Sopenharmony_ci params.enc.is_tenbit = inst->bit_depth == VIDC_BITDEPTH_10; 66262306a36Sopenharmony_ci } 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci return hfi_plat->bufreq(¶ms, inst->session_type, buftype, req); 66562306a36Sopenharmony_ci} 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ciint venus_helper_get_bufreq(struct venus_inst *inst, u32 type, 66862306a36Sopenharmony_ci struct hfi_buffer_requirements *req) 66962306a36Sopenharmony_ci{ 67062306a36Sopenharmony_ci u32 ptype = HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS; 67162306a36Sopenharmony_ci enum hfi_version ver = inst->core->res->hfi_version; 67262306a36Sopenharmony_ci union hfi_get_property hprop; 67362306a36Sopenharmony_ci unsigned int i; 67462306a36Sopenharmony_ci int ret; 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci if (type == HFI_BUFFER_OUTPUT || type == HFI_BUFFER_OUTPUT2) 67962306a36Sopenharmony_ci hfi_bufreq_set_count_min(req, ver, inst->fw_min_cnt); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci ret = platform_get_bufreq(inst, type, req); 68262306a36Sopenharmony_ci if (!ret) { 68362306a36Sopenharmony_ci if (type == HFI_BUFFER_OUTPUT || type == HFI_BUFFER_OUTPUT2) 68462306a36Sopenharmony_ci inst->fw_min_cnt = hfi_bufreq_get_count_min(req, ver); 68562306a36Sopenharmony_ci return 0; 68662306a36Sopenharmony_ci } 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci ret = hfi_session_get_property(inst, ptype, &hprop); 68962306a36Sopenharmony_ci if (ret) 69062306a36Sopenharmony_ci return ret; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci ret = -EINVAL; 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci for (i = 0; i < HFI_BUFFER_TYPE_MAX; i++) { 69562306a36Sopenharmony_ci if (hprop.bufreq[i].type != type) 69662306a36Sopenharmony_ci continue; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci memcpy(req, &hprop.bufreq[i], sizeof(*req)); 69962306a36Sopenharmony_ci ret = 0; 70062306a36Sopenharmony_ci break; 70162306a36Sopenharmony_ci } 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci return ret; 70462306a36Sopenharmony_ci} 70562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_get_bufreq); 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_cistruct id_mapping { 70862306a36Sopenharmony_ci u32 hfi_id; 70962306a36Sopenharmony_ci u32 v4l2_id; 71062306a36Sopenharmony_ci}; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_cistatic const struct id_mapping mpeg4_profiles[] = { 71362306a36Sopenharmony_ci { HFI_MPEG4_PROFILE_SIMPLE, V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE }, 71462306a36Sopenharmony_ci { HFI_MPEG4_PROFILE_ADVANCEDSIMPLE, V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE }, 71562306a36Sopenharmony_ci}; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_cistatic const struct id_mapping mpeg4_levels[] = { 71862306a36Sopenharmony_ci { HFI_MPEG4_LEVEL_0, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0 }, 71962306a36Sopenharmony_ci { HFI_MPEG4_LEVEL_0b, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B }, 72062306a36Sopenharmony_ci { HFI_MPEG4_LEVEL_1, V4L2_MPEG_VIDEO_MPEG4_LEVEL_1 }, 72162306a36Sopenharmony_ci { HFI_MPEG4_LEVEL_2, V4L2_MPEG_VIDEO_MPEG4_LEVEL_2 }, 72262306a36Sopenharmony_ci { HFI_MPEG4_LEVEL_3, V4L2_MPEG_VIDEO_MPEG4_LEVEL_3 }, 72362306a36Sopenharmony_ci { HFI_MPEG4_LEVEL_4, V4L2_MPEG_VIDEO_MPEG4_LEVEL_4 }, 72462306a36Sopenharmony_ci { HFI_MPEG4_LEVEL_5, V4L2_MPEG_VIDEO_MPEG4_LEVEL_5 }, 72562306a36Sopenharmony_ci}; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_cistatic const struct id_mapping mpeg2_profiles[] = { 72862306a36Sopenharmony_ci { HFI_MPEG2_PROFILE_SIMPLE, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SIMPLE }, 72962306a36Sopenharmony_ci { HFI_MPEG2_PROFILE_MAIN, V4L2_MPEG_VIDEO_MPEG2_PROFILE_MAIN }, 73062306a36Sopenharmony_ci { HFI_MPEG2_PROFILE_SNR, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SNR_SCALABLE }, 73162306a36Sopenharmony_ci { HFI_MPEG2_PROFILE_SPATIAL, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SPATIALLY_SCALABLE }, 73262306a36Sopenharmony_ci { HFI_MPEG2_PROFILE_HIGH, V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH }, 73362306a36Sopenharmony_ci}; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_cistatic const struct id_mapping mpeg2_levels[] = { 73662306a36Sopenharmony_ci { HFI_MPEG2_LEVEL_LL, V4L2_MPEG_VIDEO_MPEG2_LEVEL_LOW }, 73762306a36Sopenharmony_ci { HFI_MPEG2_LEVEL_ML, V4L2_MPEG_VIDEO_MPEG2_LEVEL_MAIN }, 73862306a36Sopenharmony_ci { HFI_MPEG2_LEVEL_H14, V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH_1440 }, 73962306a36Sopenharmony_ci { HFI_MPEG2_LEVEL_HL, V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH }, 74062306a36Sopenharmony_ci}; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_cistatic const struct id_mapping h264_profiles[] = { 74362306a36Sopenharmony_ci { HFI_H264_PROFILE_BASELINE, V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE }, 74462306a36Sopenharmony_ci { HFI_H264_PROFILE_MAIN, V4L2_MPEG_VIDEO_H264_PROFILE_MAIN }, 74562306a36Sopenharmony_ci { HFI_H264_PROFILE_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_HIGH }, 74662306a36Sopenharmony_ci { HFI_H264_PROFILE_STEREO_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH }, 74762306a36Sopenharmony_ci { HFI_H264_PROFILE_MULTIVIEW_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH }, 74862306a36Sopenharmony_ci { HFI_H264_PROFILE_CONSTRAINED_BASE, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE }, 74962306a36Sopenharmony_ci { HFI_H264_PROFILE_CONSTRAINED_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH }, 75062306a36Sopenharmony_ci}; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_cistatic const struct id_mapping h264_levels[] = { 75362306a36Sopenharmony_ci { HFI_H264_LEVEL_1, V4L2_MPEG_VIDEO_H264_LEVEL_1_0 }, 75462306a36Sopenharmony_ci { HFI_H264_LEVEL_1b, V4L2_MPEG_VIDEO_H264_LEVEL_1B }, 75562306a36Sopenharmony_ci { HFI_H264_LEVEL_11, V4L2_MPEG_VIDEO_H264_LEVEL_1_1 }, 75662306a36Sopenharmony_ci { HFI_H264_LEVEL_12, V4L2_MPEG_VIDEO_H264_LEVEL_1_2 }, 75762306a36Sopenharmony_ci { HFI_H264_LEVEL_13, V4L2_MPEG_VIDEO_H264_LEVEL_1_3 }, 75862306a36Sopenharmony_ci { HFI_H264_LEVEL_2, V4L2_MPEG_VIDEO_H264_LEVEL_2_0 }, 75962306a36Sopenharmony_ci { HFI_H264_LEVEL_21, V4L2_MPEG_VIDEO_H264_LEVEL_2_1 }, 76062306a36Sopenharmony_ci { HFI_H264_LEVEL_22, V4L2_MPEG_VIDEO_H264_LEVEL_2_2 }, 76162306a36Sopenharmony_ci { HFI_H264_LEVEL_3, V4L2_MPEG_VIDEO_H264_LEVEL_3_0 }, 76262306a36Sopenharmony_ci { HFI_H264_LEVEL_31, V4L2_MPEG_VIDEO_H264_LEVEL_3_1 }, 76362306a36Sopenharmony_ci { HFI_H264_LEVEL_32, V4L2_MPEG_VIDEO_H264_LEVEL_3_2 }, 76462306a36Sopenharmony_ci { HFI_H264_LEVEL_4, V4L2_MPEG_VIDEO_H264_LEVEL_4_0 }, 76562306a36Sopenharmony_ci { HFI_H264_LEVEL_41, V4L2_MPEG_VIDEO_H264_LEVEL_4_1 }, 76662306a36Sopenharmony_ci { HFI_H264_LEVEL_42, V4L2_MPEG_VIDEO_H264_LEVEL_4_2 }, 76762306a36Sopenharmony_ci { HFI_H264_LEVEL_5, V4L2_MPEG_VIDEO_H264_LEVEL_5_0 }, 76862306a36Sopenharmony_ci { HFI_H264_LEVEL_51, V4L2_MPEG_VIDEO_H264_LEVEL_5_1 }, 76962306a36Sopenharmony_ci { HFI_H264_LEVEL_52, V4L2_MPEG_VIDEO_H264_LEVEL_5_1 }, 77062306a36Sopenharmony_ci}; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_cistatic const struct id_mapping hevc_profiles[] = { 77362306a36Sopenharmony_ci { HFI_HEVC_PROFILE_MAIN, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN }, 77462306a36Sopenharmony_ci { HFI_HEVC_PROFILE_MAIN_STILL_PIC, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE }, 77562306a36Sopenharmony_ci { HFI_HEVC_PROFILE_MAIN10, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10 }, 77662306a36Sopenharmony_ci}; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_cistatic const struct id_mapping hevc_levels[] = { 77962306a36Sopenharmony_ci { HFI_HEVC_LEVEL_1, V4L2_MPEG_VIDEO_HEVC_LEVEL_1 }, 78062306a36Sopenharmony_ci { HFI_HEVC_LEVEL_2, V4L2_MPEG_VIDEO_HEVC_LEVEL_2 }, 78162306a36Sopenharmony_ci { HFI_HEVC_LEVEL_21, V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1 }, 78262306a36Sopenharmony_ci { HFI_HEVC_LEVEL_3, V4L2_MPEG_VIDEO_HEVC_LEVEL_3 }, 78362306a36Sopenharmony_ci { HFI_HEVC_LEVEL_31, V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1 }, 78462306a36Sopenharmony_ci { HFI_HEVC_LEVEL_4, V4L2_MPEG_VIDEO_HEVC_LEVEL_4 }, 78562306a36Sopenharmony_ci { HFI_HEVC_LEVEL_41, V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1 }, 78662306a36Sopenharmony_ci { HFI_HEVC_LEVEL_5, V4L2_MPEG_VIDEO_HEVC_LEVEL_5 }, 78762306a36Sopenharmony_ci { HFI_HEVC_LEVEL_51, V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1 }, 78862306a36Sopenharmony_ci { HFI_HEVC_LEVEL_52, V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2 }, 78962306a36Sopenharmony_ci { HFI_HEVC_LEVEL_6, V4L2_MPEG_VIDEO_HEVC_LEVEL_6 }, 79062306a36Sopenharmony_ci { HFI_HEVC_LEVEL_61, V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1 }, 79162306a36Sopenharmony_ci { HFI_HEVC_LEVEL_62, V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2 }, 79262306a36Sopenharmony_ci}; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_cistatic const struct id_mapping vp8_profiles[] = { 79562306a36Sopenharmony_ci { HFI_VPX_PROFILE_VERSION_0, V4L2_MPEG_VIDEO_VP8_PROFILE_0 }, 79662306a36Sopenharmony_ci { HFI_VPX_PROFILE_VERSION_1, V4L2_MPEG_VIDEO_VP8_PROFILE_1 }, 79762306a36Sopenharmony_ci { HFI_VPX_PROFILE_VERSION_2, V4L2_MPEG_VIDEO_VP8_PROFILE_2 }, 79862306a36Sopenharmony_ci { HFI_VPX_PROFILE_VERSION_3, V4L2_MPEG_VIDEO_VP8_PROFILE_3 }, 79962306a36Sopenharmony_ci}; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_cistatic const struct id_mapping vp9_profiles[] = { 80262306a36Sopenharmony_ci { HFI_VP9_PROFILE_P0, V4L2_MPEG_VIDEO_VP9_PROFILE_0 }, 80362306a36Sopenharmony_ci { HFI_VP9_PROFILE_P2_10B, V4L2_MPEG_VIDEO_VP9_PROFILE_2 }, 80462306a36Sopenharmony_ci}; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_cistatic const struct id_mapping vp9_levels[] = { 80762306a36Sopenharmony_ci { HFI_VP9_LEVEL_1, V4L2_MPEG_VIDEO_VP9_LEVEL_1_0 }, 80862306a36Sopenharmony_ci { HFI_VP9_LEVEL_11, V4L2_MPEG_VIDEO_VP9_LEVEL_1_1 }, 80962306a36Sopenharmony_ci { HFI_VP9_LEVEL_2, V4L2_MPEG_VIDEO_VP9_LEVEL_2_0}, 81062306a36Sopenharmony_ci { HFI_VP9_LEVEL_21, V4L2_MPEG_VIDEO_VP9_LEVEL_2_1 }, 81162306a36Sopenharmony_ci { HFI_VP9_LEVEL_3, V4L2_MPEG_VIDEO_VP9_LEVEL_3_0}, 81262306a36Sopenharmony_ci { HFI_VP9_LEVEL_31, V4L2_MPEG_VIDEO_VP9_LEVEL_3_1 }, 81362306a36Sopenharmony_ci { HFI_VP9_LEVEL_4, V4L2_MPEG_VIDEO_VP9_LEVEL_4_0 }, 81462306a36Sopenharmony_ci { HFI_VP9_LEVEL_41, V4L2_MPEG_VIDEO_VP9_LEVEL_4_1 }, 81562306a36Sopenharmony_ci { HFI_VP9_LEVEL_5, V4L2_MPEG_VIDEO_VP9_LEVEL_5_0 }, 81662306a36Sopenharmony_ci { HFI_VP9_LEVEL_51, V4L2_MPEG_VIDEO_VP9_LEVEL_5_1 }, 81762306a36Sopenharmony_ci { HFI_VP9_LEVEL_6, V4L2_MPEG_VIDEO_VP9_LEVEL_6_0 }, 81862306a36Sopenharmony_ci { HFI_VP9_LEVEL_61, V4L2_MPEG_VIDEO_VP9_LEVEL_6_1 }, 81962306a36Sopenharmony_ci}; 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_cistatic u32 find_v4l2_id(u32 hfi_id, const struct id_mapping *array, unsigned int array_sz) 82262306a36Sopenharmony_ci{ 82362306a36Sopenharmony_ci unsigned int i; 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci if (!array || !array_sz) 82662306a36Sopenharmony_ci return 0; 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci for (i = 0; i < array_sz; i++) 82962306a36Sopenharmony_ci if (hfi_id == array[i].hfi_id) 83062306a36Sopenharmony_ci return array[i].v4l2_id; 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci return 0; 83362306a36Sopenharmony_ci} 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_cistatic u32 find_hfi_id(u32 v4l2_id, const struct id_mapping *array, unsigned int array_sz) 83662306a36Sopenharmony_ci{ 83762306a36Sopenharmony_ci unsigned int i; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci if (!array || !array_sz) 84062306a36Sopenharmony_ci return 0; 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci for (i = 0; i < array_sz; i++) 84362306a36Sopenharmony_ci if (v4l2_id == array[i].v4l2_id) 84462306a36Sopenharmony_ci return array[i].hfi_id; 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci return 0; 84762306a36Sopenharmony_ci} 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_cistatic void 85062306a36Sopenharmony_civ4l2_id_profile_level(u32 hfi_codec, struct hfi_profile_level *pl, u32 *profile, u32 *level) 85162306a36Sopenharmony_ci{ 85262306a36Sopenharmony_ci u32 hfi_pf = pl->profile; 85362306a36Sopenharmony_ci u32 hfi_lvl = pl->level; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci switch (hfi_codec) { 85662306a36Sopenharmony_ci case HFI_VIDEO_CODEC_H264: 85762306a36Sopenharmony_ci *profile = find_v4l2_id(hfi_pf, h264_profiles, ARRAY_SIZE(h264_profiles)); 85862306a36Sopenharmony_ci *level = find_v4l2_id(hfi_lvl, h264_levels, ARRAY_SIZE(h264_levels)); 85962306a36Sopenharmony_ci break; 86062306a36Sopenharmony_ci case HFI_VIDEO_CODEC_MPEG2: 86162306a36Sopenharmony_ci *profile = find_v4l2_id(hfi_pf, mpeg2_profiles, ARRAY_SIZE(mpeg2_profiles)); 86262306a36Sopenharmony_ci *level = find_v4l2_id(hfi_lvl, mpeg2_levels, ARRAY_SIZE(mpeg2_levels)); 86362306a36Sopenharmony_ci break; 86462306a36Sopenharmony_ci case HFI_VIDEO_CODEC_MPEG4: 86562306a36Sopenharmony_ci *profile = find_v4l2_id(hfi_pf, mpeg4_profiles, ARRAY_SIZE(mpeg4_profiles)); 86662306a36Sopenharmony_ci *level = find_v4l2_id(hfi_lvl, mpeg4_levels, ARRAY_SIZE(mpeg4_levels)); 86762306a36Sopenharmony_ci break; 86862306a36Sopenharmony_ci case HFI_VIDEO_CODEC_VP8: 86962306a36Sopenharmony_ci *profile = find_v4l2_id(hfi_pf, vp8_profiles, ARRAY_SIZE(vp8_profiles)); 87062306a36Sopenharmony_ci *level = 0; 87162306a36Sopenharmony_ci break; 87262306a36Sopenharmony_ci case HFI_VIDEO_CODEC_VP9: 87362306a36Sopenharmony_ci *profile = find_v4l2_id(hfi_pf, vp9_profiles, ARRAY_SIZE(vp9_profiles)); 87462306a36Sopenharmony_ci *level = find_v4l2_id(hfi_lvl, vp9_levels, ARRAY_SIZE(vp9_levels)); 87562306a36Sopenharmony_ci break; 87662306a36Sopenharmony_ci case HFI_VIDEO_CODEC_HEVC: 87762306a36Sopenharmony_ci *profile = find_v4l2_id(hfi_pf, hevc_profiles, ARRAY_SIZE(hevc_profiles)); 87862306a36Sopenharmony_ci *level = find_v4l2_id(hfi_lvl, hevc_levels, ARRAY_SIZE(hevc_levels)); 87962306a36Sopenharmony_ci break; 88062306a36Sopenharmony_ci default: 88162306a36Sopenharmony_ci break; 88262306a36Sopenharmony_ci } 88362306a36Sopenharmony_ci} 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_cistatic void 88662306a36Sopenharmony_cihfi_id_profile_level(u32 hfi_codec, u32 v4l2_pf, u32 v4l2_lvl, struct hfi_profile_level *pl) 88762306a36Sopenharmony_ci{ 88862306a36Sopenharmony_ci switch (hfi_codec) { 88962306a36Sopenharmony_ci case HFI_VIDEO_CODEC_H264: 89062306a36Sopenharmony_ci pl->profile = find_hfi_id(v4l2_pf, h264_profiles, ARRAY_SIZE(h264_profiles)); 89162306a36Sopenharmony_ci pl->level = find_hfi_id(v4l2_lvl, h264_levels, ARRAY_SIZE(h264_levels)); 89262306a36Sopenharmony_ci break; 89362306a36Sopenharmony_ci case HFI_VIDEO_CODEC_MPEG2: 89462306a36Sopenharmony_ci pl->profile = find_hfi_id(v4l2_pf, mpeg2_profiles, ARRAY_SIZE(mpeg2_profiles)); 89562306a36Sopenharmony_ci pl->level = find_hfi_id(v4l2_lvl, mpeg2_levels, ARRAY_SIZE(mpeg2_levels)); 89662306a36Sopenharmony_ci break; 89762306a36Sopenharmony_ci case HFI_VIDEO_CODEC_MPEG4: 89862306a36Sopenharmony_ci pl->profile = find_hfi_id(v4l2_pf, mpeg4_profiles, ARRAY_SIZE(mpeg4_profiles)); 89962306a36Sopenharmony_ci pl->level = find_hfi_id(v4l2_lvl, mpeg4_levels, ARRAY_SIZE(mpeg4_levels)); 90062306a36Sopenharmony_ci break; 90162306a36Sopenharmony_ci case HFI_VIDEO_CODEC_VP8: 90262306a36Sopenharmony_ci pl->profile = find_hfi_id(v4l2_pf, vp8_profiles, ARRAY_SIZE(vp8_profiles)); 90362306a36Sopenharmony_ci pl->level = 0; 90462306a36Sopenharmony_ci break; 90562306a36Sopenharmony_ci case HFI_VIDEO_CODEC_VP9: 90662306a36Sopenharmony_ci pl->profile = find_hfi_id(v4l2_pf, vp9_profiles, ARRAY_SIZE(vp9_profiles)); 90762306a36Sopenharmony_ci pl->level = find_hfi_id(v4l2_lvl, vp9_levels, ARRAY_SIZE(vp9_levels)); 90862306a36Sopenharmony_ci break; 90962306a36Sopenharmony_ci case HFI_VIDEO_CODEC_HEVC: 91062306a36Sopenharmony_ci pl->profile = find_hfi_id(v4l2_pf, hevc_profiles, ARRAY_SIZE(hevc_profiles)); 91162306a36Sopenharmony_ci pl->level = find_hfi_id(v4l2_lvl, hevc_levels, ARRAY_SIZE(hevc_levels)); 91262306a36Sopenharmony_ci break; 91362306a36Sopenharmony_ci default: 91462306a36Sopenharmony_ci break; 91562306a36Sopenharmony_ci } 91662306a36Sopenharmony_ci} 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ciint venus_helper_get_profile_level(struct venus_inst *inst, u32 *profile, u32 *level) 91962306a36Sopenharmony_ci{ 92062306a36Sopenharmony_ci const u32 ptype = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT; 92162306a36Sopenharmony_ci union hfi_get_property hprop; 92262306a36Sopenharmony_ci int ret; 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci ret = hfi_session_get_property(inst, ptype, &hprop); 92562306a36Sopenharmony_ci if (ret) 92662306a36Sopenharmony_ci return ret; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci v4l2_id_profile_level(inst->hfi_codec, &hprop.profile_level, profile, level); 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci return 0; 93162306a36Sopenharmony_ci} 93262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_get_profile_level); 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ciint venus_helper_set_profile_level(struct venus_inst *inst, u32 profile, u32 level) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci const u32 ptype = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT; 93762306a36Sopenharmony_ci struct hfi_profile_level pl; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci hfi_id_profile_level(inst->hfi_codec, profile, level, &pl); 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci return hfi_session_set_property(inst, ptype, &pl); 94262306a36Sopenharmony_ci} 94362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_set_profile_level); 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_cistatic u32 get_framesize_raw_nv12(u32 width, u32 height) 94662306a36Sopenharmony_ci{ 94762306a36Sopenharmony_ci u32 y_stride, uv_stride, y_plane; 94862306a36Sopenharmony_ci u32 y_sclines, uv_sclines, uv_plane; 94962306a36Sopenharmony_ci u32 size; 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_ci y_stride = ALIGN(width, 128); 95262306a36Sopenharmony_ci uv_stride = ALIGN(width, 128); 95362306a36Sopenharmony_ci y_sclines = ALIGN(height, 32); 95462306a36Sopenharmony_ci uv_sclines = ALIGN(((height + 1) >> 1), 16); 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci y_plane = y_stride * y_sclines; 95762306a36Sopenharmony_ci uv_plane = uv_stride * uv_sclines + SZ_4K; 95862306a36Sopenharmony_ci size = y_plane + uv_plane + SZ_8K; 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci return ALIGN(size, SZ_4K); 96162306a36Sopenharmony_ci} 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_cistatic u32 get_framesize_raw_nv12_ubwc(u32 width, u32 height) 96462306a36Sopenharmony_ci{ 96562306a36Sopenharmony_ci u32 y_meta_stride, y_meta_plane; 96662306a36Sopenharmony_ci u32 y_stride, y_plane; 96762306a36Sopenharmony_ci u32 uv_meta_stride, uv_meta_plane; 96862306a36Sopenharmony_ci u32 uv_stride, uv_plane; 96962306a36Sopenharmony_ci u32 extradata = SZ_16K; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci y_meta_stride = ALIGN(DIV_ROUND_UP(width, 32), 64); 97262306a36Sopenharmony_ci y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(height, 8), 16); 97362306a36Sopenharmony_ci y_meta_plane = ALIGN(y_meta_plane, SZ_4K); 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci y_stride = ALIGN(width, 128); 97662306a36Sopenharmony_ci y_plane = ALIGN(y_stride * ALIGN(height, 32), SZ_4K); 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci uv_meta_stride = ALIGN(DIV_ROUND_UP(width / 2, 16), 64); 97962306a36Sopenharmony_ci uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP(height / 2, 8), 16); 98062306a36Sopenharmony_ci uv_meta_plane = ALIGN(uv_meta_plane, SZ_4K); 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci uv_stride = ALIGN(width, 128); 98362306a36Sopenharmony_ci uv_plane = ALIGN(uv_stride * ALIGN(height / 2, 32), SZ_4K); 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane + 98662306a36Sopenharmony_ci max(extradata, y_stride * 48), SZ_4K); 98762306a36Sopenharmony_ci} 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_cistatic u32 get_framesize_raw_p010(u32 width, u32 height) 99062306a36Sopenharmony_ci{ 99162306a36Sopenharmony_ci u32 y_plane, uv_plane, y_stride, uv_stride, y_sclines, uv_sclines; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci y_stride = ALIGN(width * 2, 128); 99462306a36Sopenharmony_ci uv_stride = ALIGN(width * 2, 128); 99562306a36Sopenharmony_ci y_sclines = ALIGN(height, 32); 99662306a36Sopenharmony_ci uv_sclines = ALIGN((height + 1) >> 1, 16); 99762306a36Sopenharmony_ci y_plane = y_stride * y_sclines; 99862306a36Sopenharmony_ci uv_plane = uv_stride * uv_sclines; 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci return ALIGN((y_plane + uv_plane), SZ_4K); 100162306a36Sopenharmony_ci} 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_cistatic u32 get_framesize_raw_p010_ubwc(u32 width, u32 height) 100462306a36Sopenharmony_ci{ 100562306a36Sopenharmony_ci u32 y_stride, uv_stride, y_sclines, uv_sclines; 100662306a36Sopenharmony_ci u32 y_ubwc_plane, uv_ubwc_plane; 100762306a36Sopenharmony_ci u32 y_meta_stride, y_meta_scanlines; 100862306a36Sopenharmony_ci u32 uv_meta_stride, uv_meta_scanlines; 100962306a36Sopenharmony_ci u32 y_meta_plane, uv_meta_plane; 101062306a36Sopenharmony_ci u32 size; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci y_stride = ALIGN(width * 2, 256); 101362306a36Sopenharmony_ci uv_stride = ALIGN(width * 2, 256); 101462306a36Sopenharmony_ci y_sclines = ALIGN(height, 16); 101562306a36Sopenharmony_ci uv_sclines = ALIGN((height + 1) >> 1, 16); 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci y_ubwc_plane = ALIGN(y_stride * y_sclines, SZ_4K); 101862306a36Sopenharmony_ci uv_ubwc_plane = ALIGN(uv_stride * uv_sclines, SZ_4K); 101962306a36Sopenharmony_ci y_meta_stride = ALIGN(DIV_ROUND_UP(width, 32), 64); 102062306a36Sopenharmony_ci y_meta_scanlines = ALIGN(DIV_ROUND_UP(height, 4), 16); 102162306a36Sopenharmony_ci y_meta_plane = ALIGN(y_meta_stride * y_meta_scanlines, SZ_4K); 102262306a36Sopenharmony_ci uv_meta_stride = ALIGN(DIV_ROUND_UP((width + 1) >> 1, 16), 64); 102362306a36Sopenharmony_ci uv_meta_scanlines = ALIGN(DIV_ROUND_UP((height + 1) >> 1, 4), 16); 102462306a36Sopenharmony_ci uv_meta_plane = ALIGN(uv_meta_stride * uv_meta_scanlines, SZ_4K); 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci size = y_ubwc_plane + uv_ubwc_plane + y_meta_plane + uv_meta_plane; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci return ALIGN(size, SZ_4K); 102962306a36Sopenharmony_ci} 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_cistatic u32 get_framesize_raw_yuv420_tp10_ubwc(u32 width, u32 height) 103262306a36Sopenharmony_ci{ 103362306a36Sopenharmony_ci u32 y_stride, uv_stride, y_sclines, uv_sclines; 103462306a36Sopenharmony_ci u32 y_ubwc_plane, uv_ubwc_plane; 103562306a36Sopenharmony_ci u32 y_meta_stride, y_meta_scanlines; 103662306a36Sopenharmony_ci u32 uv_meta_stride, uv_meta_scanlines; 103762306a36Sopenharmony_ci u32 y_meta_plane, uv_meta_plane; 103862306a36Sopenharmony_ci u32 extradata = SZ_16K; 103962306a36Sopenharmony_ci u32 size; 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci y_stride = ALIGN(width * 4 / 3, 256); 104262306a36Sopenharmony_ci uv_stride = ALIGN(width * 4 / 3, 256); 104362306a36Sopenharmony_ci y_sclines = ALIGN(height, 16); 104462306a36Sopenharmony_ci uv_sclines = ALIGN((height + 1) >> 1, 16); 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci y_ubwc_plane = ALIGN(y_stride * y_sclines, SZ_4K); 104762306a36Sopenharmony_ci uv_ubwc_plane = ALIGN(uv_stride * uv_sclines, SZ_4K); 104862306a36Sopenharmony_ci y_meta_stride = ALIGN(DIV_ROUND_UP(width, 48), 64); 104962306a36Sopenharmony_ci y_meta_scanlines = ALIGN(DIV_ROUND_UP(height, 4), 16); 105062306a36Sopenharmony_ci y_meta_plane = ALIGN(y_meta_stride * y_meta_scanlines, SZ_4K); 105162306a36Sopenharmony_ci uv_meta_stride = ALIGN(DIV_ROUND_UP((width + 1) >> 1, 24), 64); 105262306a36Sopenharmony_ci uv_meta_scanlines = ALIGN(DIV_ROUND_UP((height + 1) >> 1, 4), 16); 105362306a36Sopenharmony_ci uv_meta_plane = ALIGN(uv_meta_stride * uv_meta_scanlines, SZ_4K); 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci size = y_ubwc_plane + uv_ubwc_plane + y_meta_plane + uv_meta_plane; 105662306a36Sopenharmony_ci size += max(extradata + SZ_8K, y_stride * 48); 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci return ALIGN(size, SZ_4K); 105962306a36Sopenharmony_ci} 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ciu32 venus_helper_get_framesz_raw(u32 hfi_fmt, u32 width, u32 height) 106262306a36Sopenharmony_ci{ 106362306a36Sopenharmony_ci switch (hfi_fmt) { 106462306a36Sopenharmony_ci case HFI_COLOR_FORMAT_NV12: 106562306a36Sopenharmony_ci case HFI_COLOR_FORMAT_NV21: 106662306a36Sopenharmony_ci return get_framesize_raw_nv12(width, height); 106762306a36Sopenharmony_ci case HFI_COLOR_FORMAT_NV12_UBWC: 106862306a36Sopenharmony_ci return get_framesize_raw_nv12_ubwc(width, height); 106962306a36Sopenharmony_ci case HFI_COLOR_FORMAT_P010: 107062306a36Sopenharmony_ci return get_framesize_raw_p010(width, height); 107162306a36Sopenharmony_ci case HFI_COLOR_FORMAT_P010_UBWC: 107262306a36Sopenharmony_ci return get_framesize_raw_p010_ubwc(width, height); 107362306a36Sopenharmony_ci case HFI_COLOR_FORMAT_YUV420_TP10_UBWC: 107462306a36Sopenharmony_ci return get_framesize_raw_yuv420_tp10_ubwc(width, height); 107562306a36Sopenharmony_ci default: 107662306a36Sopenharmony_ci return 0; 107762306a36Sopenharmony_ci } 107862306a36Sopenharmony_ci} 107962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_get_framesz_raw); 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ciu32 venus_helper_get_framesz(u32 v4l2_fmt, u32 width, u32 height) 108262306a36Sopenharmony_ci{ 108362306a36Sopenharmony_ci u32 hfi_fmt, sz; 108462306a36Sopenharmony_ci bool compressed; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci switch (v4l2_fmt) { 108762306a36Sopenharmony_ci case V4L2_PIX_FMT_MPEG: 108862306a36Sopenharmony_ci case V4L2_PIX_FMT_H264: 108962306a36Sopenharmony_ci case V4L2_PIX_FMT_H264_NO_SC: 109062306a36Sopenharmony_ci case V4L2_PIX_FMT_H264_MVC: 109162306a36Sopenharmony_ci case V4L2_PIX_FMT_H263: 109262306a36Sopenharmony_ci case V4L2_PIX_FMT_MPEG1: 109362306a36Sopenharmony_ci case V4L2_PIX_FMT_MPEG2: 109462306a36Sopenharmony_ci case V4L2_PIX_FMT_MPEG4: 109562306a36Sopenharmony_ci case V4L2_PIX_FMT_XVID: 109662306a36Sopenharmony_ci case V4L2_PIX_FMT_VC1_ANNEX_G: 109762306a36Sopenharmony_ci case V4L2_PIX_FMT_VC1_ANNEX_L: 109862306a36Sopenharmony_ci case V4L2_PIX_FMT_VP8: 109962306a36Sopenharmony_ci case V4L2_PIX_FMT_VP9: 110062306a36Sopenharmony_ci case V4L2_PIX_FMT_HEVC: 110162306a36Sopenharmony_ci compressed = true; 110262306a36Sopenharmony_ci break; 110362306a36Sopenharmony_ci default: 110462306a36Sopenharmony_ci compressed = false; 110562306a36Sopenharmony_ci break; 110662306a36Sopenharmony_ci } 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci if (compressed) { 110962306a36Sopenharmony_ci sz = ALIGN(height, 32) * ALIGN(width, 32) * 3 / 2 / 2; 111062306a36Sopenharmony_ci if (width < 1280 || height < 720) 111162306a36Sopenharmony_ci sz *= 8; 111262306a36Sopenharmony_ci return ALIGN(sz, SZ_4K); 111362306a36Sopenharmony_ci } 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci hfi_fmt = to_hfi_raw_fmt(v4l2_fmt); 111662306a36Sopenharmony_ci if (!hfi_fmt) 111762306a36Sopenharmony_ci return 0; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci return venus_helper_get_framesz_raw(hfi_fmt, width, height); 112062306a36Sopenharmony_ci} 112162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_get_framesz); 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ciint venus_helper_set_input_resolution(struct venus_inst *inst, 112462306a36Sopenharmony_ci unsigned int width, unsigned int height) 112562306a36Sopenharmony_ci{ 112662306a36Sopenharmony_ci u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE; 112762306a36Sopenharmony_ci struct hfi_framesize fs; 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci fs.buffer_type = HFI_BUFFER_INPUT; 113062306a36Sopenharmony_ci fs.width = width; 113162306a36Sopenharmony_ci fs.height = height; 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci return hfi_session_set_property(inst, ptype, &fs); 113462306a36Sopenharmony_ci} 113562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_set_input_resolution); 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ciint venus_helper_set_output_resolution(struct venus_inst *inst, 113862306a36Sopenharmony_ci unsigned int width, unsigned int height, 113962306a36Sopenharmony_ci u32 buftype) 114062306a36Sopenharmony_ci{ 114162306a36Sopenharmony_ci u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE; 114262306a36Sopenharmony_ci struct hfi_framesize fs; 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci fs.buffer_type = buftype; 114562306a36Sopenharmony_ci fs.width = width; 114662306a36Sopenharmony_ci fs.height = height; 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci return hfi_session_set_property(inst, ptype, &fs); 114962306a36Sopenharmony_ci} 115062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_set_output_resolution); 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_cistatic u32 venus_helper_get_work_mode(struct venus_inst *inst) 115362306a36Sopenharmony_ci{ 115462306a36Sopenharmony_ci u32 mode; 115562306a36Sopenharmony_ci u32 num_mbs; 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci mode = VIDC_WORK_MODE_2; 115862306a36Sopenharmony_ci if (inst->session_type == VIDC_SESSION_TYPE_DEC) { 115962306a36Sopenharmony_ci num_mbs = (ALIGN(inst->height, 16) * ALIGN(inst->width, 16)) / 256; 116062306a36Sopenharmony_ci if (inst->hfi_codec == HFI_VIDEO_CODEC_MPEG2 || 116162306a36Sopenharmony_ci inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE || 116262306a36Sopenharmony_ci num_mbs <= NUM_MBS_720P) 116362306a36Sopenharmony_ci mode = VIDC_WORK_MODE_1; 116462306a36Sopenharmony_ci } else { 116562306a36Sopenharmony_ci num_mbs = (ALIGN(inst->out_height, 16) * ALIGN(inst->out_width, 16)) / 256; 116662306a36Sopenharmony_ci if (inst->hfi_codec == HFI_VIDEO_CODEC_VP8 && 116762306a36Sopenharmony_ci num_mbs <= NUM_MBS_4K) 116862306a36Sopenharmony_ci mode = VIDC_WORK_MODE_1; 116962306a36Sopenharmony_ci } 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci return mode; 117262306a36Sopenharmony_ci} 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ciint venus_helper_set_work_mode(struct venus_inst *inst) 117562306a36Sopenharmony_ci{ 117662306a36Sopenharmony_ci const u32 ptype = HFI_PROPERTY_PARAM_WORK_MODE; 117762306a36Sopenharmony_ci struct hfi_video_work_mode wm; 117862306a36Sopenharmony_ci u32 mode; 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci if (!IS_V4(inst->core) && !IS_V6(inst->core)) 118162306a36Sopenharmony_ci return 0; 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci mode = venus_helper_get_work_mode(inst); 118462306a36Sopenharmony_ci wm.video_work_mode = mode; 118562306a36Sopenharmony_ci return hfi_session_set_property(inst, ptype, &wm); 118662306a36Sopenharmony_ci} 118762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_set_work_mode); 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ciint venus_helper_set_format_constraints(struct venus_inst *inst) 119062306a36Sopenharmony_ci{ 119162306a36Sopenharmony_ci const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO; 119262306a36Sopenharmony_ci struct hfi_uncompressed_plane_actual_constraints_info pconstraint; 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci if (!IS_V6(inst->core)) 119562306a36Sopenharmony_ci return 0; 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci if (inst->opb_fmt == HFI_COLOR_FORMAT_NV12_UBWC || 119862306a36Sopenharmony_ci inst->opb_fmt == HFI_COLOR_FORMAT_YUV420_TP10_UBWC) 119962306a36Sopenharmony_ci return 0; 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci pconstraint.buffer_type = HFI_BUFFER_OUTPUT2; 120262306a36Sopenharmony_ci pconstraint.num_planes = 2; 120362306a36Sopenharmony_ci pconstraint.plane_format[0].stride_multiples = 128; 120462306a36Sopenharmony_ci pconstraint.plane_format[0].max_stride = 8192; 120562306a36Sopenharmony_ci pconstraint.plane_format[0].min_plane_buffer_height_multiple = 32; 120662306a36Sopenharmony_ci pconstraint.plane_format[0].buffer_alignment = 256; 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci pconstraint.plane_format[1].stride_multiples = 128; 120962306a36Sopenharmony_ci pconstraint.plane_format[1].max_stride = 8192; 121062306a36Sopenharmony_ci pconstraint.plane_format[1].min_plane_buffer_height_multiple = 16; 121162306a36Sopenharmony_ci pconstraint.plane_format[1].buffer_alignment = 256; 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci return hfi_session_set_property(inst, ptype, &pconstraint); 121462306a36Sopenharmony_ci} 121562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_set_format_constraints); 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ciint venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, 121862306a36Sopenharmony_ci unsigned int output_bufs, 121962306a36Sopenharmony_ci unsigned int output2_bufs) 122062306a36Sopenharmony_ci{ 122162306a36Sopenharmony_ci u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL; 122262306a36Sopenharmony_ci struct hfi_buffer_count_actual buf_count; 122362306a36Sopenharmony_ci int ret; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci buf_count.type = HFI_BUFFER_INPUT; 122662306a36Sopenharmony_ci buf_count.count_actual = input_bufs; 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci ret = hfi_session_set_property(inst, ptype, &buf_count); 122962306a36Sopenharmony_ci if (ret) 123062306a36Sopenharmony_ci return ret; 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci buf_count.type = HFI_BUFFER_OUTPUT; 123362306a36Sopenharmony_ci buf_count.count_actual = output_bufs; 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci ret = hfi_session_set_property(inst, ptype, &buf_count); 123662306a36Sopenharmony_ci if (ret) 123762306a36Sopenharmony_ci return ret; 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci if (output2_bufs) { 124062306a36Sopenharmony_ci buf_count.type = HFI_BUFFER_OUTPUT2; 124162306a36Sopenharmony_ci buf_count.count_actual = output2_bufs; 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ci ret = hfi_session_set_property(inst, ptype, &buf_count); 124462306a36Sopenharmony_ci } 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci return ret; 124762306a36Sopenharmony_ci} 124862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_set_num_bufs); 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ciint venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format, 125162306a36Sopenharmony_ci u32 buftype) 125262306a36Sopenharmony_ci{ 125362306a36Sopenharmony_ci const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT; 125462306a36Sopenharmony_ci struct hfi_uncompressed_format_select fmt; 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci fmt.buffer_type = buftype; 125762306a36Sopenharmony_ci fmt.format = hfi_format; 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci return hfi_session_set_property(inst, ptype, &fmt); 126062306a36Sopenharmony_ci} 126162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_set_raw_format); 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ciint venus_helper_set_color_format(struct venus_inst *inst, u32 pixfmt) 126462306a36Sopenharmony_ci{ 126562306a36Sopenharmony_ci u32 hfi_format, buftype; 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci if (inst->session_type == VIDC_SESSION_TYPE_DEC) 126862306a36Sopenharmony_ci buftype = HFI_BUFFER_OUTPUT; 126962306a36Sopenharmony_ci else if (inst->session_type == VIDC_SESSION_TYPE_ENC) 127062306a36Sopenharmony_ci buftype = HFI_BUFFER_INPUT; 127162306a36Sopenharmony_ci else 127262306a36Sopenharmony_ci return -EINVAL; 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci hfi_format = to_hfi_raw_fmt(pixfmt); 127562306a36Sopenharmony_ci if (!hfi_format) 127662306a36Sopenharmony_ci return -EINVAL; 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci return venus_helper_set_raw_format(inst, hfi_format, buftype); 127962306a36Sopenharmony_ci} 128062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_set_color_format); 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ciint venus_helper_set_multistream(struct venus_inst *inst, bool out_en, 128362306a36Sopenharmony_ci bool out2_en) 128462306a36Sopenharmony_ci{ 128562306a36Sopenharmony_ci struct hfi_multi_stream multi = {0}; 128662306a36Sopenharmony_ci u32 ptype = HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM; 128762306a36Sopenharmony_ci int ret; 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci multi.buffer_type = HFI_BUFFER_OUTPUT; 129062306a36Sopenharmony_ci multi.enable = out_en; 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci ret = hfi_session_set_property(inst, ptype, &multi); 129362306a36Sopenharmony_ci if (ret) 129462306a36Sopenharmony_ci return ret; 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci multi.buffer_type = HFI_BUFFER_OUTPUT2; 129762306a36Sopenharmony_ci multi.enable = out2_en; 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci return hfi_session_set_property(inst, ptype, &multi); 130062306a36Sopenharmony_ci} 130162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_set_multistream); 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ciint venus_helper_set_dyn_bufmode(struct venus_inst *inst) 130462306a36Sopenharmony_ci{ 130562306a36Sopenharmony_ci const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE; 130662306a36Sopenharmony_ci struct hfi_buffer_alloc_mode mode; 130762306a36Sopenharmony_ci int ret; 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci if (!is_dynamic_bufmode(inst)) 131062306a36Sopenharmony_ci return 0; 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci mode.type = HFI_BUFFER_OUTPUT; 131362306a36Sopenharmony_ci mode.mode = HFI_BUFFER_MODE_DYNAMIC; 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci ret = hfi_session_set_property(inst, ptype, &mode); 131662306a36Sopenharmony_ci if (ret) 131762306a36Sopenharmony_ci return ret; 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci mode.type = HFI_BUFFER_OUTPUT2; 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci return hfi_session_set_property(inst, ptype, &mode); 132262306a36Sopenharmony_ci} 132362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_set_dyn_bufmode); 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ciint venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype) 132662306a36Sopenharmony_ci{ 132762306a36Sopenharmony_ci const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL; 132862306a36Sopenharmony_ci struct hfi_buffer_size_actual bufsz; 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci bufsz.type = buftype; 133162306a36Sopenharmony_ci bufsz.size = bufsize; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci return hfi_session_set_property(inst, ptype, &bufsz); 133462306a36Sopenharmony_ci} 133562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_set_bufsize); 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_ciunsigned int venus_helper_get_opb_size(struct venus_inst *inst) 133862306a36Sopenharmony_ci{ 133962306a36Sopenharmony_ci /* the encoder has only one output */ 134062306a36Sopenharmony_ci if (inst->session_type == VIDC_SESSION_TYPE_ENC) 134162306a36Sopenharmony_ci return inst->output_buf_size; 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci if (inst->opb_buftype == HFI_BUFFER_OUTPUT) 134462306a36Sopenharmony_ci return inst->output_buf_size; 134562306a36Sopenharmony_ci else if (inst->opb_buftype == HFI_BUFFER_OUTPUT2) 134662306a36Sopenharmony_ci return inst->output2_buf_size; 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci return 0; 134962306a36Sopenharmony_ci} 135062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_get_opb_size); 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_cistatic void delayed_process_buf_func(struct work_struct *work) 135362306a36Sopenharmony_ci{ 135462306a36Sopenharmony_ci struct venus_buffer *buf, *n; 135562306a36Sopenharmony_ci struct venus_inst *inst; 135662306a36Sopenharmony_ci int ret; 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci inst = container_of(work, struct venus_inst, delayed_process_work); 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci mutex_lock(&inst->lock); 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci if (!(inst->streamon_out & inst->streamon_cap)) 136362306a36Sopenharmony_ci goto unlock; 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci list_for_each_entry_safe(buf, n, &inst->delayed_process, ref_list) { 136662306a36Sopenharmony_ci if (buf->flags & HFI_BUFFERFLAG_READONLY) 136762306a36Sopenharmony_ci continue; 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci ret = session_process_buf(inst, &buf->vb); 137062306a36Sopenharmony_ci if (ret) 137162306a36Sopenharmony_ci return_buf_error(inst, &buf->vb); 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci list_del_init(&buf->ref_list); 137462306a36Sopenharmony_ci } 137562306a36Sopenharmony_ciunlock: 137662306a36Sopenharmony_ci mutex_unlock(&inst->lock); 137762306a36Sopenharmony_ci} 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_civoid venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx) 138062306a36Sopenharmony_ci{ 138162306a36Sopenharmony_ci struct venus_buffer *buf; 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci list_for_each_entry(buf, &inst->registeredbufs, reg_list) { 138462306a36Sopenharmony_ci if (buf->vb.vb2_buf.index == idx) { 138562306a36Sopenharmony_ci buf->flags &= ~HFI_BUFFERFLAG_READONLY; 138662306a36Sopenharmony_ci schedule_work(&inst->delayed_process_work); 138762306a36Sopenharmony_ci break; 138862306a36Sopenharmony_ci } 138962306a36Sopenharmony_ci } 139062306a36Sopenharmony_ci} 139162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_release_buf_ref); 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_civoid venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf) 139462306a36Sopenharmony_ci{ 139562306a36Sopenharmony_ci struct venus_buffer *buf = to_venus_buffer(vbuf); 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci buf->flags |= HFI_BUFFERFLAG_READONLY; 139862306a36Sopenharmony_ci} 139962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_acquire_buf_ref); 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_cistatic int is_buf_refed(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) 140262306a36Sopenharmony_ci{ 140362306a36Sopenharmony_ci struct venus_buffer *buf = to_venus_buffer(vbuf); 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci if (buf->flags & HFI_BUFFERFLAG_READONLY) { 140662306a36Sopenharmony_ci list_add_tail(&buf->ref_list, &inst->delayed_process); 140762306a36Sopenharmony_ci schedule_work(&inst->delayed_process_work); 140862306a36Sopenharmony_ci return 1; 140962306a36Sopenharmony_ci } 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_ci return 0; 141262306a36Sopenharmony_ci} 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_cistruct vb2_v4l2_buffer * 141562306a36Sopenharmony_civenus_helper_find_buf(struct venus_inst *inst, unsigned int type, u32 idx) 141662306a36Sopenharmony_ci{ 141762306a36Sopenharmony_ci struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 142062306a36Sopenharmony_ci return v4l2_m2m_src_buf_remove_by_idx(m2m_ctx, idx); 142162306a36Sopenharmony_ci else 142262306a36Sopenharmony_ci return v4l2_m2m_dst_buf_remove_by_idx(m2m_ctx, idx); 142362306a36Sopenharmony_ci} 142462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_find_buf); 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_civoid venus_helper_change_dpb_owner(struct venus_inst *inst, 142762306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf, unsigned int type, 142862306a36Sopenharmony_ci unsigned int buf_type, u32 tag) 142962306a36Sopenharmony_ci{ 143062306a36Sopenharmony_ci struct intbuf *dpb_buf; 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci if (!V4L2_TYPE_IS_CAPTURE(type) || 143362306a36Sopenharmony_ci buf_type != inst->dpb_buftype) 143462306a36Sopenharmony_ci return; 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci list_for_each_entry(dpb_buf, &inst->dpbbufs, list) 143762306a36Sopenharmony_ci if (dpb_buf->dpb_out_tag == tag) { 143862306a36Sopenharmony_ci dpb_buf->owned_by = DRIVER; 143962306a36Sopenharmony_ci break; 144062306a36Sopenharmony_ci } 144162306a36Sopenharmony_ci} 144262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_change_dpb_owner); 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ciint venus_helper_vb2_buf_init(struct vb2_buffer *vb) 144562306a36Sopenharmony_ci{ 144662306a36Sopenharmony_ci struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 144762306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 144862306a36Sopenharmony_ci struct venus_buffer *buf = to_venus_buffer(vbuf); 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci buf->size = vb2_plane_size(vb, 0); 145162306a36Sopenharmony_ci buf->dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 145462306a36Sopenharmony_ci list_add_tail(&buf->reg_list, &inst->registeredbufs); 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci return 0; 145762306a36Sopenharmony_ci} 145862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_vb2_buf_init); 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ciint venus_helper_vb2_buf_prepare(struct vb2_buffer *vb) 146162306a36Sopenharmony_ci{ 146262306a36Sopenharmony_ci struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 146362306a36Sopenharmony_ci unsigned int out_buf_size = venus_helper_get_opb_size(inst); 146462306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { 146762306a36Sopenharmony_ci if (vbuf->field == V4L2_FIELD_ANY) 146862306a36Sopenharmony_ci vbuf->field = V4L2_FIELD_NONE; 146962306a36Sopenharmony_ci if (vbuf->field != V4L2_FIELD_NONE) { 147062306a36Sopenharmony_ci dev_err(inst->core->dev, "%s field isn't supported\n", 147162306a36Sopenharmony_ci __func__); 147262306a36Sopenharmony_ci return -EINVAL; 147362306a36Sopenharmony_ci } 147462306a36Sopenharmony_ci } 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 147762306a36Sopenharmony_ci vb2_plane_size(vb, 0) < out_buf_size) 147862306a36Sopenharmony_ci return -EINVAL; 147962306a36Sopenharmony_ci if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && 148062306a36Sopenharmony_ci vb2_plane_size(vb, 0) < inst->input_buf_size) 148162306a36Sopenharmony_ci return -EINVAL; 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci return 0; 148462306a36Sopenharmony_ci} 148562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_vb2_buf_prepare); 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_cistatic void cache_payload(struct venus_inst *inst, struct vb2_buffer *vb) 148862306a36Sopenharmony_ci{ 148962306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 149062306a36Sopenharmony_ci unsigned int idx = vbuf->vb2_buf.index; 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 149362306a36Sopenharmony_ci inst->payloads[idx] = vb2_get_plane_payload(vb, 0); 149462306a36Sopenharmony_ci} 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_civoid venus_helper_vb2_buf_queue(struct vb2_buffer *vb) 149762306a36Sopenharmony_ci{ 149862306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 149962306a36Sopenharmony_ci struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 150062306a36Sopenharmony_ci struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 150162306a36Sopenharmony_ci int ret; 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci v4l2_m2m_buf_queue(m2m_ctx, vbuf); 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci /* Skip processing queued capture buffers after LAST flag */ 150662306a36Sopenharmony_ci if (inst->session_type == VIDC_SESSION_TYPE_DEC && 150762306a36Sopenharmony_ci V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) && 150862306a36Sopenharmony_ci inst->codec_state == VENUS_DEC_STATE_DRC) 150962306a36Sopenharmony_ci return; 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci cache_payload(inst, vb); 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci if (inst->session_type == VIDC_SESSION_TYPE_ENC && 151462306a36Sopenharmony_ci !(inst->streamon_out && inst->streamon_cap)) 151562306a36Sopenharmony_ci return; 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci if (vb2_start_streaming_called(vb->vb2_queue)) { 151862306a36Sopenharmony_ci ret = is_buf_refed(inst, vbuf); 151962306a36Sopenharmony_ci if (ret) 152062306a36Sopenharmony_ci return; 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci ret = session_process_buf(inst, vbuf); 152362306a36Sopenharmony_ci if (ret) 152462306a36Sopenharmony_ci return_buf_error(inst, vbuf); 152562306a36Sopenharmony_ci } 152662306a36Sopenharmony_ci} 152762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_vb2_buf_queue); 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_civoid venus_helper_buffers_done(struct venus_inst *inst, unsigned int type, 153062306a36Sopenharmony_ci enum vb2_buffer_state state) 153162306a36Sopenharmony_ci{ 153262306a36Sopenharmony_ci struct vb2_v4l2_buffer *buf; 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_ci if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 153562306a36Sopenharmony_ci while ((buf = v4l2_m2m_src_buf_remove(inst->m2m_ctx))) 153662306a36Sopenharmony_ci v4l2_m2m_buf_done(buf, state); 153762306a36Sopenharmony_ci } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 153862306a36Sopenharmony_ci while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx))) 153962306a36Sopenharmony_ci v4l2_m2m_buf_done(buf, state); 154062306a36Sopenharmony_ci } 154162306a36Sopenharmony_ci} 154262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_buffers_done); 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_civoid venus_helper_vb2_stop_streaming(struct vb2_queue *q) 154562306a36Sopenharmony_ci{ 154662306a36Sopenharmony_ci struct venus_inst *inst = vb2_get_drv_priv(q); 154762306a36Sopenharmony_ci struct venus_core *core = inst->core; 154862306a36Sopenharmony_ci int ret; 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci mutex_lock(&inst->lock); 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci if (inst->streamon_out & inst->streamon_cap) { 155362306a36Sopenharmony_ci ret = hfi_session_stop(inst); 155462306a36Sopenharmony_ci ret |= hfi_session_unload_res(inst); 155562306a36Sopenharmony_ci ret |= venus_helper_unregister_bufs(inst); 155662306a36Sopenharmony_ci ret |= venus_helper_intbufs_free(inst); 155762306a36Sopenharmony_ci ret |= hfi_session_deinit(inst); 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci if (inst->session_error || test_bit(0, &core->sys_error)) 156062306a36Sopenharmony_ci ret = -EIO; 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci if (ret) 156362306a36Sopenharmony_ci hfi_session_abort(inst); 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci venus_helper_free_dpb_bufs(inst); 156662306a36Sopenharmony_ci 156762306a36Sopenharmony_ci venus_pm_load_scale(inst); 156862306a36Sopenharmony_ci INIT_LIST_HEAD(&inst->registeredbufs); 156962306a36Sopenharmony_ci } 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci venus_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 157262306a36Sopenharmony_ci VB2_BUF_STATE_ERROR); 157362306a36Sopenharmony_ci venus_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 157462306a36Sopenharmony_ci VB2_BUF_STATE_ERROR); 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 157762306a36Sopenharmony_ci inst->streamon_out = 0; 157862306a36Sopenharmony_ci else 157962306a36Sopenharmony_ci inst->streamon_cap = 0; 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ci venus_pm_release_core(inst); 158262306a36Sopenharmony_ci 158362306a36Sopenharmony_ci inst->session_error = 0; 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci mutex_unlock(&inst->lock); 158662306a36Sopenharmony_ci} 158762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_vb2_stop_streaming); 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_civoid venus_helper_vb2_queue_error(struct venus_inst *inst) 159062306a36Sopenharmony_ci{ 159162306a36Sopenharmony_ci struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 159262306a36Sopenharmony_ci struct vb2_queue *q; 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci q = v4l2_m2m_get_src_vq(m2m_ctx); 159562306a36Sopenharmony_ci vb2_queue_error(q); 159662306a36Sopenharmony_ci q = v4l2_m2m_get_dst_vq(m2m_ctx); 159762306a36Sopenharmony_ci vb2_queue_error(q); 159862306a36Sopenharmony_ci} 159962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_vb2_queue_error); 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ciint venus_helper_process_initial_cap_bufs(struct venus_inst *inst) 160262306a36Sopenharmony_ci{ 160362306a36Sopenharmony_ci struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 160462306a36Sopenharmony_ci struct v4l2_m2m_buffer *buf, *n; 160562306a36Sopenharmony_ci int ret; 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) { 160862306a36Sopenharmony_ci ret = session_process_buf(inst, &buf->vb); 160962306a36Sopenharmony_ci if (ret) { 161062306a36Sopenharmony_ci return_buf_error(inst, &buf->vb); 161162306a36Sopenharmony_ci return ret; 161262306a36Sopenharmony_ci } 161362306a36Sopenharmony_ci } 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci return 0; 161662306a36Sopenharmony_ci} 161762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_process_initial_cap_bufs); 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ciint venus_helper_process_initial_out_bufs(struct venus_inst *inst) 162062306a36Sopenharmony_ci{ 162162306a36Sopenharmony_ci struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 162262306a36Sopenharmony_ci struct v4l2_m2m_buffer *buf, *n; 162362306a36Sopenharmony_ci int ret; 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_ci v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) { 162662306a36Sopenharmony_ci ret = session_process_buf(inst, &buf->vb); 162762306a36Sopenharmony_ci if (ret) { 162862306a36Sopenharmony_ci return_buf_error(inst, &buf->vb); 162962306a36Sopenharmony_ci return ret; 163062306a36Sopenharmony_ci } 163162306a36Sopenharmony_ci } 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci return 0; 163462306a36Sopenharmony_ci} 163562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_process_initial_out_bufs); 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ciint venus_helper_vb2_start_streaming(struct venus_inst *inst) 163862306a36Sopenharmony_ci{ 163962306a36Sopenharmony_ci int ret; 164062306a36Sopenharmony_ci 164162306a36Sopenharmony_ci ret = venus_helper_intbufs_alloc(inst); 164262306a36Sopenharmony_ci if (ret) 164362306a36Sopenharmony_ci return ret; 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci ret = session_register_bufs(inst); 164662306a36Sopenharmony_ci if (ret) 164762306a36Sopenharmony_ci goto err_bufs_free; 164862306a36Sopenharmony_ci 164962306a36Sopenharmony_ci venus_pm_load_scale(inst); 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci ret = hfi_session_load_res(inst); 165262306a36Sopenharmony_ci if (ret) 165362306a36Sopenharmony_ci goto err_unreg_bufs; 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_ci ret = hfi_session_start(inst); 165662306a36Sopenharmony_ci if (ret) 165762306a36Sopenharmony_ci goto err_unload_res; 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci return 0; 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_cierr_unload_res: 166262306a36Sopenharmony_ci hfi_session_unload_res(inst); 166362306a36Sopenharmony_cierr_unreg_bufs: 166462306a36Sopenharmony_ci venus_helper_unregister_bufs(inst); 166562306a36Sopenharmony_cierr_bufs_free: 166662306a36Sopenharmony_ci venus_helper_intbufs_free(inst); 166762306a36Sopenharmony_ci return ret; 166862306a36Sopenharmony_ci} 166962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_vb2_start_streaming); 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_civoid venus_helper_m2m_device_run(void *priv) 167262306a36Sopenharmony_ci{ 167362306a36Sopenharmony_ci struct venus_inst *inst = priv; 167462306a36Sopenharmony_ci struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 167562306a36Sopenharmony_ci struct v4l2_m2m_buffer *buf, *n; 167662306a36Sopenharmony_ci int ret; 167762306a36Sopenharmony_ci 167862306a36Sopenharmony_ci mutex_lock(&inst->lock); 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_ci v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) { 168162306a36Sopenharmony_ci ret = session_process_buf(inst, &buf->vb); 168262306a36Sopenharmony_ci if (ret) 168362306a36Sopenharmony_ci return_buf_error(inst, &buf->vb); 168462306a36Sopenharmony_ci } 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_ci v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) { 168762306a36Sopenharmony_ci ret = session_process_buf(inst, &buf->vb); 168862306a36Sopenharmony_ci if (ret) 168962306a36Sopenharmony_ci return_buf_error(inst, &buf->vb); 169062306a36Sopenharmony_ci } 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci mutex_unlock(&inst->lock); 169362306a36Sopenharmony_ci} 169462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_m2m_device_run); 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_civoid venus_helper_m2m_job_abort(void *priv) 169762306a36Sopenharmony_ci{ 169862306a36Sopenharmony_ci struct venus_inst *inst = priv; 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci v4l2_m2m_job_finish(inst->m2m_dev, inst->m2m_ctx); 170162306a36Sopenharmony_ci} 170262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_m2m_job_abort); 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ciint venus_helper_session_init(struct venus_inst *inst) 170562306a36Sopenharmony_ci{ 170662306a36Sopenharmony_ci enum hfi_version version = inst->core->res->hfi_version; 170762306a36Sopenharmony_ci u32 session_type = inst->session_type; 170862306a36Sopenharmony_ci u32 codec; 170962306a36Sopenharmony_ci int ret; 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci codec = inst->session_type == VIDC_SESSION_TYPE_DEC ? 171262306a36Sopenharmony_ci inst->fmt_out->pixfmt : inst->fmt_cap->pixfmt; 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_ci ret = hfi_session_init(inst, codec); 171562306a36Sopenharmony_ci if (ret) 171662306a36Sopenharmony_ci return ret; 171762306a36Sopenharmony_ci 171862306a36Sopenharmony_ci inst->clk_data.vpp_freq = hfi_platform_get_codec_vpp_freq(version, codec, 171962306a36Sopenharmony_ci session_type); 172062306a36Sopenharmony_ci inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(version, codec, 172162306a36Sopenharmony_ci session_type); 172262306a36Sopenharmony_ci inst->clk_data.low_power_freq = hfi_platform_get_codec_lp_freq(version, codec, 172362306a36Sopenharmony_ci session_type); 172462306a36Sopenharmony_ci 172562306a36Sopenharmony_ci return 0; 172662306a36Sopenharmony_ci} 172762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_session_init); 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_civoid venus_helper_init_instance(struct venus_inst *inst) 173062306a36Sopenharmony_ci{ 173162306a36Sopenharmony_ci if (inst->session_type == VIDC_SESSION_TYPE_DEC) { 173262306a36Sopenharmony_ci INIT_LIST_HEAD(&inst->delayed_process); 173362306a36Sopenharmony_ci INIT_WORK(&inst->delayed_process_work, 173462306a36Sopenharmony_ci delayed_process_buf_func); 173562306a36Sopenharmony_ci } 173662306a36Sopenharmony_ci} 173762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_init_instance); 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_cistatic bool find_fmt_from_caps(struct hfi_plat_caps *caps, u32 buftype, u32 fmt) 174062306a36Sopenharmony_ci{ 174162306a36Sopenharmony_ci unsigned int i; 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci for (i = 0; i < caps->num_fmts; i++) { 174462306a36Sopenharmony_ci if (caps->fmts[i].buftype == buftype && 174562306a36Sopenharmony_ci caps->fmts[i].fmt == fmt) 174662306a36Sopenharmony_ci return true; 174762306a36Sopenharmony_ci } 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_ci return false; 175062306a36Sopenharmony_ci} 175162306a36Sopenharmony_ci 175262306a36Sopenharmony_ciint venus_helper_get_out_fmts(struct venus_inst *inst, u32 v4l2_fmt, 175362306a36Sopenharmony_ci u32 *out_fmt, u32 *out2_fmt, bool ubwc) 175462306a36Sopenharmony_ci{ 175562306a36Sopenharmony_ci struct venus_core *core = inst->core; 175662306a36Sopenharmony_ci struct hfi_plat_caps *caps; 175762306a36Sopenharmony_ci u32 ubwc_fmt, fmt = to_hfi_raw_fmt(v4l2_fmt); 175862306a36Sopenharmony_ci bool found, found_ubwc; 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci *out_fmt = *out2_fmt = 0; 176162306a36Sopenharmony_ci 176262306a36Sopenharmony_ci if (!fmt) 176362306a36Sopenharmony_ci return -EINVAL; 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type); 176662306a36Sopenharmony_ci if (!caps) 176762306a36Sopenharmony_ci return -EINVAL; 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci if (inst->bit_depth == VIDC_BITDEPTH_10 && inst->session_type == VIDC_SESSION_TYPE_DEC) { 177062306a36Sopenharmony_ci found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, 177162306a36Sopenharmony_ci HFI_COLOR_FORMAT_YUV420_TP10_UBWC); 177262306a36Sopenharmony_ci found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt); 177362306a36Sopenharmony_ci if (found_ubwc && found) { 177462306a36Sopenharmony_ci /* 177562306a36Sopenharmony_ci * Hard-code DPB buffers to be 10bit UBWC 177662306a36Sopenharmony_ci * until V4L2 is able to expose compressed/tiled 177762306a36Sopenharmony_ci * formats to applications. 177862306a36Sopenharmony_ci */ 177962306a36Sopenharmony_ci *out_fmt = HFI_COLOR_FORMAT_YUV420_TP10_UBWC; 178062306a36Sopenharmony_ci *out2_fmt = fmt; 178162306a36Sopenharmony_ci return 0; 178262306a36Sopenharmony_ci } 178362306a36Sopenharmony_ci } 178462306a36Sopenharmony_ci 178562306a36Sopenharmony_ci if (ubwc) { 178662306a36Sopenharmony_ci ubwc_fmt = fmt | HFI_COLOR_FORMAT_UBWC_BASE; 178762306a36Sopenharmony_ci found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, 178862306a36Sopenharmony_ci ubwc_fmt); 178962306a36Sopenharmony_ci found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt); 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_ci if (found_ubwc && found) { 179262306a36Sopenharmony_ci *out_fmt = ubwc_fmt; 179362306a36Sopenharmony_ci *out2_fmt = fmt; 179462306a36Sopenharmony_ci return 0; 179562306a36Sopenharmony_ci } 179662306a36Sopenharmony_ci } 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_ci found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, fmt); 179962306a36Sopenharmony_ci if (found) { 180062306a36Sopenharmony_ci *out_fmt = fmt; 180162306a36Sopenharmony_ci *out2_fmt = 0; 180262306a36Sopenharmony_ci return 0; 180362306a36Sopenharmony_ci } 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_ci found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt); 180662306a36Sopenharmony_ci if (found) { 180762306a36Sopenharmony_ci *out_fmt = 0; 180862306a36Sopenharmony_ci *out2_fmt = fmt; 180962306a36Sopenharmony_ci return 0; 181062306a36Sopenharmony_ci } 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci return -EINVAL; 181362306a36Sopenharmony_ci} 181462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_get_out_fmts); 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_cibool venus_helper_check_format(struct venus_inst *inst, u32 v4l2_pixfmt) 181762306a36Sopenharmony_ci{ 181862306a36Sopenharmony_ci struct venus_core *core = inst->core; 181962306a36Sopenharmony_ci u32 fmt = to_hfi_raw_fmt(v4l2_pixfmt); 182062306a36Sopenharmony_ci struct hfi_plat_caps *caps; 182162306a36Sopenharmony_ci bool found; 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci if (!fmt) 182462306a36Sopenharmony_ci return false; 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type); 182762306a36Sopenharmony_ci if (!caps) 182862306a36Sopenharmony_ci return false; 182962306a36Sopenharmony_ci 183062306a36Sopenharmony_ci found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, fmt); 183162306a36Sopenharmony_ci if (found) 183262306a36Sopenharmony_ci goto done; 183362306a36Sopenharmony_ci 183462306a36Sopenharmony_ci found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt); 183562306a36Sopenharmony_cidone: 183662306a36Sopenharmony_ci return found; 183762306a36Sopenharmony_ci} 183862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_check_format); 183962306a36Sopenharmony_ci 184062306a36Sopenharmony_ciint venus_helper_set_stride(struct venus_inst *inst, 184162306a36Sopenharmony_ci unsigned int width, unsigned int height) 184262306a36Sopenharmony_ci{ 184362306a36Sopenharmony_ci const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO; 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci struct hfi_uncompressed_plane_actual_info plane_actual_info; 184662306a36Sopenharmony_ci 184762306a36Sopenharmony_ci plane_actual_info.buffer_type = HFI_BUFFER_INPUT; 184862306a36Sopenharmony_ci plane_actual_info.num_planes = 2; 184962306a36Sopenharmony_ci plane_actual_info.plane_format[0].actual_stride = width; 185062306a36Sopenharmony_ci plane_actual_info.plane_format[0].actual_plane_buffer_height = height; 185162306a36Sopenharmony_ci plane_actual_info.plane_format[1].actual_stride = width; 185262306a36Sopenharmony_ci plane_actual_info.plane_format[1].actual_plane_buffer_height = height / 2; 185362306a36Sopenharmony_ci 185462306a36Sopenharmony_ci return hfi_session_set_property(inst, ptype, &plane_actual_info); 185562306a36Sopenharmony_ci} 185662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(venus_helper_set_stride); 1857