197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2af2c3834SStanimir Varbanov /* 3af2c3834SStanimir Varbanov * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. 4af2c3834SStanimir Varbanov * Copyright (C) 2017 Linaro Ltd. 5af2c3834SStanimir Varbanov */ 640d87aafSMansur Alisha Shaik #include <linux/idr.h> 7af2c3834SStanimir Varbanov #include <linux/list.h> 8af2c3834SStanimir Varbanov #include <linux/mutex.h> 9af2c3834SStanimir Varbanov #include <linux/slab.h> 102c2dc2fdSStanimir Varbanov #include <linux/kernel.h> 11cc82fd69SAlexandre Courbot #include <media/videobuf2-dma-contig.h> 12af2c3834SStanimir Varbanov #include <media/v4l2-mem2mem.h> 13af2c3834SStanimir Varbanov #include <asm/div64.h> 14af2c3834SStanimir Varbanov 15af2c3834SStanimir Varbanov #include "core.h" 16af2c3834SStanimir Varbanov #include "helpers.h" 17af2c3834SStanimir Varbanov #include "hfi_helper.h" 187482a983SStanimir Varbanov #include "pm_helpers.h" 19aa603389SStanimir Varbanov #include "hfi_platform.h" 207371093fSStanimir Varbanov #include "hfi_parser.h" 21af2c3834SStanimir Varbanov 22fa622c3dSDikshita Agarwal #define NUM_MBS_720P (((ALIGN(1280, 16)) >> 4) * ((ALIGN(736, 16)) >> 4)) 23fa622c3dSDikshita Agarwal #define NUM_MBS_4K (((ALIGN(4096, 16)) >> 4) * ((ALIGN(2304, 16)) >> 4)) 241ad17595SDikshita Agarwal 2540d87aafSMansur Alisha Shaik enum dpb_buf_owner { 2640d87aafSMansur Alisha Shaik DRIVER, 2740d87aafSMansur Alisha Shaik FIRMWARE, 2840d87aafSMansur Alisha Shaik }; 2940d87aafSMansur Alisha Shaik 30af2c3834SStanimir Varbanov struct intbuf { 31af2c3834SStanimir Varbanov struct list_head list; 32af2c3834SStanimir Varbanov u32 type; 33af2c3834SStanimir Varbanov size_t size; 34af2c3834SStanimir Varbanov void *va; 35af2c3834SStanimir Varbanov dma_addr_t da; 36af2c3834SStanimir Varbanov unsigned long attrs; 3740d87aafSMansur Alisha Shaik enum dpb_buf_owner owned_by; 3840d87aafSMansur Alisha Shaik u32 dpb_out_tag; 39af2c3834SStanimir Varbanov }; 40af2c3834SStanimir Varbanov 41d8db57c2SStanimir Varbanov bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt) 42d8db57c2SStanimir Varbanov { 43d8db57c2SStanimir Varbanov struct venus_core *core = inst->core; 44d8db57c2SStanimir Varbanov u32 session_type = inst->session_type; 45d8db57c2SStanimir Varbanov u32 codec; 46d8db57c2SStanimir Varbanov 47d8db57c2SStanimir Varbanov switch (v4l2_pixfmt) { 48d8db57c2SStanimir Varbanov case V4L2_PIX_FMT_H264: 49d8db57c2SStanimir Varbanov codec = HFI_VIDEO_CODEC_H264; 50d8db57c2SStanimir Varbanov break; 51d8db57c2SStanimir Varbanov case V4L2_PIX_FMT_H263: 52d8db57c2SStanimir Varbanov codec = HFI_VIDEO_CODEC_H263; 53d8db57c2SStanimir Varbanov break; 54d8db57c2SStanimir Varbanov case V4L2_PIX_FMT_MPEG1: 55d8db57c2SStanimir Varbanov codec = HFI_VIDEO_CODEC_MPEG1; 56d8db57c2SStanimir Varbanov break; 57d8db57c2SStanimir Varbanov case V4L2_PIX_FMT_MPEG2: 58d8db57c2SStanimir Varbanov codec = HFI_VIDEO_CODEC_MPEG2; 59d8db57c2SStanimir Varbanov break; 60d8db57c2SStanimir Varbanov case V4L2_PIX_FMT_MPEG4: 61d8db57c2SStanimir Varbanov codec = HFI_VIDEO_CODEC_MPEG4; 62d8db57c2SStanimir Varbanov break; 63d8db57c2SStanimir Varbanov case V4L2_PIX_FMT_VC1_ANNEX_G: 64d8db57c2SStanimir Varbanov case V4L2_PIX_FMT_VC1_ANNEX_L: 65d8db57c2SStanimir Varbanov codec = HFI_VIDEO_CODEC_VC1; 66d8db57c2SStanimir Varbanov break; 67d8db57c2SStanimir Varbanov case V4L2_PIX_FMT_VP8: 68d8db57c2SStanimir Varbanov codec = HFI_VIDEO_CODEC_VP8; 69d8db57c2SStanimir Varbanov break; 70d8db57c2SStanimir Varbanov case V4L2_PIX_FMT_VP9: 71d8db57c2SStanimir Varbanov codec = HFI_VIDEO_CODEC_VP9; 72d8db57c2SStanimir Varbanov break; 73d8db57c2SStanimir Varbanov case V4L2_PIX_FMT_XVID: 74d8db57c2SStanimir Varbanov codec = HFI_VIDEO_CODEC_DIVX; 75d8db57c2SStanimir Varbanov break; 761fb9a605SStanimir Varbanov case V4L2_PIX_FMT_HEVC: 771fb9a605SStanimir Varbanov codec = HFI_VIDEO_CODEC_HEVC; 781fb9a605SStanimir Varbanov break; 79d8db57c2SStanimir Varbanov default: 80d8db57c2SStanimir Varbanov return false; 81d8db57c2SStanimir Varbanov } 82d8db57c2SStanimir Varbanov 83d8db57c2SStanimir Varbanov if (session_type == VIDC_SESSION_TYPE_ENC && core->enc_codecs & codec) 84d8db57c2SStanimir Varbanov return true; 85d8db57c2SStanimir Varbanov 86d8db57c2SStanimir Varbanov if (session_type == VIDC_SESSION_TYPE_DEC && core->dec_codecs & codec) 87d8db57c2SStanimir Varbanov return true; 88d8db57c2SStanimir Varbanov 89d8db57c2SStanimir Varbanov return false; 90d8db57c2SStanimir Varbanov } 91d8db57c2SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_check_codec); 92d8db57c2SStanimir Varbanov 93*73664f10SVikash Garodia static void free_dpb_buf(struct venus_inst *inst, struct intbuf *buf) 94*73664f10SVikash Garodia { 95*73664f10SVikash Garodia ida_free(&inst->dpb_ids, buf->dpb_out_tag); 96*73664f10SVikash Garodia 97*73664f10SVikash Garodia list_del_init(&buf->list); 98*73664f10SVikash Garodia dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da, 99*73664f10SVikash Garodia buf->attrs); 100*73664f10SVikash Garodia kfree(buf); 101*73664f10SVikash Garodia } 102*73664f10SVikash Garodia 1031e485ee5SStanimir Varbanov int venus_helper_queue_dpb_bufs(struct venus_inst *inst) 104f012b23dSStanimir Varbanov { 105*73664f10SVikash Garodia struct intbuf *buf, *next; 106*73664f10SVikash Garodia unsigned int dpb_size = 0; 107f012b23dSStanimir Varbanov int ret = 0; 108f012b23dSStanimir Varbanov 109*73664f10SVikash Garodia if (inst->dpb_buftype == HFI_BUFFER_OUTPUT) 110*73664f10SVikash Garodia dpb_size = inst->output_buf_size; 111*73664f10SVikash Garodia else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2) 112*73664f10SVikash Garodia dpb_size = inst->output2_buf_size; 113*73664f10SVikash Garodia 114*73664f10SVikash Garodia list_for_each_entry_safe(buf, next, &inst->dpbbufs, list) { 115f012b23dSStanimir Varbanov struct hfi_frame_data fdata; 116f012b23dSStanimir Varbanov 117f012b23dSStanimir Varbanov memset(&fdata, 0, sizeof(fdata)); 118f012b23dSStanimir Varbanov fdata.alloc_len = buf->size; 119f012b23dSStanimir Varbanov fdata.device_addr = buf->da; 120f012b23dSStanimir Varbanov fdata.buffer_type = buf->type; 121f012b23dSStanimir Varbanov 12240d87aafSMansur Alisha Shaik if (buf->owned_by == FIRMWARE) 12340d87aafSMansur Alisha Shaik continue; 12440d87aafSMansur Alisha Shaik 125*73664f10SVikash Garodia /* free buffer from previous sequence which was released later */ 126*73664f10SVikash Garodia if (dpb_size > buf->size) { 127*73664f10SVikash Garodia free_dpb_buf(inst, buf); 128*73664f10SVikash Garodia continue; 129*73664f10SVikash Garodia } 130*73664f10SVikash Garodia 13140d87aafSMansur Alisha Shaik fdata.clnt_data = buf->dpb_out_tag; 13240d87aafSMansur Alisha Shaik 133f012b23dSStanimir Varbanov ret = hfi_session_process_buf(inst, &fdata); 134f012b23dSStanimir Varbanov if (ret) 135f012b23dSStanimir Varbanov goto fail; 13640d87aafSMansur Alisha Shaik 13740d87aafSMansur Alisha Shaik buf->owned_by = FIRMWARE; 138f012b23dSStanimir Varbanov } 139f012b23dSStanimir Varbanov 140f012b23dSStanimir Varbanov fail: 141f012b23dSStanimir Varbanov return ret; 142f012b23dSStanimir Varbanov } 1431e485ee5SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_queue_dpb_bufs); 144f012b23dSStanimir Varbanov 145f012b23dSStanimir Varbanov int venus_helper_free_dpb_bufs(struct venus_inst *inst) 146f012b23dSStanimir Varbanov { 147f012b23dSStanimir Varbanov struct intbuf *buf, *n; 148f012b23dSStanimir Varbanov 149f012b23dSStanimir Varbanov list_for_each_entry_safe(buf, n, &inst->dpbbufs, list) { 15040d87aafSMansur Alisha Shaik if (buf->owned_by == FIRMWARE) 15140d87aafSMansur Alisha Shaik continue; 152*73664f10SVikash Garodia free_dpb_buf(inst, buf); 153f012b23dSStanimir Varbanov } 154f012b23dSStanimir Varbanov 15540d87aafSMansur Alisha Shaik if (list_empty(&inst->dpbbufs)) 156f012b23dSStanimir Varbanov INIT_LIST_HEAD(&inst->dpbbufs); 157f012b23dSStanimir Varbanov 158f012b23dSStanimir Varbanov return 0; 159f012b23dSStanimir Varbanov } 160f012b23dSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_free_dpb_bufs); 161f012b23dSStanimir Varbanov 162f012b23dSStanimir Varbanov int venus_helper_alloc_dpb_bufs(struct venus_inst *inst) 163f012b23dSStanimir Varbanov { 164f012b23dSStanimir Varbanov struct venus_core *core = inst->core; 165f012b23dSStanimir Varbanov struct device *dev = core->dev; 166f012b23dSStanimir Varbanov enum hfi_version ver = core->res->hfi_version; 167f012b23dSStanimir Varbanov struct hfi_buffer_requirements bufreq; 168f012b23dSStanimir Varbanov u32 buftype = inst->dpb_buftype; 169f012b23dSStanimir Varbanov unsigned int dpb_size = 0; 170f012b23dSStanimir Varbanov struct intbuf *buf; 171f012b23dSStanimir Varbanov unsigned int i; 172f012b23dSStanimir Varbanov u32 count; 173f012b23dSStanimir Varbanov int ret; 17440d87aafSMansur Alisha Shaik int id; 175f012b23dSStanimir Varbanov 176f012b23dSStanimir Varbanov /* no need to allocate dpb buffers */ 177f012b23dSStanimir Varbanov if (!inst->dpb_fmt) 178f012b23dSStanimir Varbanov return 0; 179f012b23dSStanimir Varbanov 180f012b23dSStanimir Varbanov if (inst->dpb_buftype == HFI_BUFFER_OUTPUT) 181f012b23dSStanimir Varbanov dpb_size = inst->output_buf_size; 182f012b23dSStanimir Varbanov else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2) 183f012b23dSStanimir Varbanov dpb_size = inst->output2_buf_size; 184f012b23dSStanimir Varbanov 185f012b23dSStanimir Varbanov if (!dpb_size) 186f012b23dSStanimir Varbanov return 0; 187f012b23dSStanimir Varbanov 188f012b23dSStanimir Varbanov ret = venus_helper_get_bufreq(inst, buftype, &bufreq); 189f012b23dSStanimir Varbanov if (ret) 190f012b23dSStanimir Varbanov return ret; 191f012b23dSStanimir Varbanov 192f012b23dSStanimir Varbanov count = HFI_BUFREQ_COUNT_MIN(&bufreq, ver); 193f012b23dSStanimir Varbanov 194f012b23dSStanimir Varbanov for (i = 0; i < count; i++) { 195f012b23dSStanimir Varbanov buf = kzalloc(sizeof(*buf), GFP_KERNEL); 196f012b23dSStanimir Varbanov if (!buf) { 197f012b23dSStanimir Varbanov ret = -ENOMEM; 198f012b23dSStanimir Varbanov goto fail; 199f012b23dSStanimir Varbanov } 200f012b23dSStanimir Varbanov 201f012b23dSStanimir Varbanov buf->type = buftype; 202f012b23dSStanimir Varbanov buf->size = dpb_size; 203f012b23dSStanimir Varbanov buf->attrs = DMA_ATTR_WRITE_COMBINE | 204f012b23dSStanimir Varbanov DMA_ATTR_NO_KERNEL_MAPPING; 205f012b23dSStanimir Varbanov buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL, 206f012b23dSStanimir Varbanov buf->attrs); 207f012b23dSStanimir Varbanov if (!buf->va) { 208f012b23dSStanimir Varbanov ret = -ENOMEM; 209f012b23dSStanimir Varbanov goto fail; 210f012b23dSStanimir Varbanov } 21140d87aafSMansur Alisha Shaik buf->owned_by = DRIVER; 21240d87aafSMansur Alisha Shaik 21340d87aafSMansur Alisha Shaik id = ida_alloc_min(&inst->dpb_ids, VB2_MAX_FRAME, GFP_KERNEL); 21440d87aafSMansur Alisha Shaik if (id < 0) { 21540d87aafSMansur Alisha Shaik ret = id; 21640d87aafSMansur Alisha Shaik goto fail; 21740d87aafSMansur Alisha Shaik } 21840d87aafSMansur Alisha Shaik 21940d87aafSMansur Alisha Shaik buf->dpb_out_tag = id; 220f012b23dSStanimir Varbanov 221f012b23dSStanimir Varbanov list_add_tail(&buf->list, &inst->dpbbufs); 222f012b23dSStanimir Varbanov } 223f012b23dSStanimir Varbanov 224f012b23dSStanimir Varbanov return 0; 225f012b23dSStanimir Varbanov 226f012b23dSStanimir Varbanov fail: 2278403fdd7SAmeer Hamza kfree(buf); 228f012b23dSStanimir Varbanov venus_helper_free_dpb_bufs(inst); 229f012b23dSStanimir Varbanov return ret; 230f012b23dSStanimir Varbanov } 231f012b23dSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_alloc_dpb_bufs); 232f012b23dSStanimir Varbanov 233af2c3834SStanimir Varbanov static int intbufs_set_buffer(struct venus_inst *inst, u32 type) 234af2c3834SStanimir Varbanov { 235af2c3834SStanimir Varbanov struct venus_core *core = inst->core; 236af2c3834SStanimir Varbanov struct device *dev = core->dev; 237af2c3834SStanimir Varbanov struct hfi_buffer_requirements bufreq; 238af2c3834SStanimir Varbanov struct hfi_buffer_desc bd; 239af2c3834SStanimir Varbanov struct intbuf *buf; 240af2c3834SStanimir Varbanov unsigned int i; 241af2c3834SStanimir Varbanov int ret; 242af2c3834SStanimir Varbanov 243af2c3834SStanimir Varbanov ret = venus_helper_get_bufreq(inst, type, &bufreq); 244af2c3834SStanimir Varbanov if (ret) 245af2c3834SStanimir Varbanov return 0; 246af2c3834SStanimir Varbanov 247af2c3834SStanimir Varbanov if (!bufreq.size) 248af2c3834SStanimir Varbanov return 0; 249af2c3834SStanimir Varbanov 250af2c3834SStanimir Varbanov for (i = 0; i < bufreq.count_actual; i++) { 251af2c3834SStanimir Varbanov buf = kzalloc(sizeof(*buf), GFP_KERNEL); 252af2c3834SStanimir Varbanov if (!buf) { 253af2c3834SStanimir Varbanov ret = -ENOMEM; 254af2c3834SStanimir Varbanov goto fail; 255af2c3834SStanimir Varbanov } 256af2c3834SStanimir Varbanov 257af2c3834SStanimir Varbanov buf->type = bufreq.type; 258af2c3834SStanimir Varbanov buf->size = bufreq.size; 259af2c3834SStanimir Varbanov buf->attrs = DMA_ATTR_WRITE_COMBINE | 260af2c3834SStanimir Varbanov DMA_ATTR_NO_KERNEL_MAPPING; 261af2c3834SStanimir Varbanov buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL, 262af2c3834SStanimir Varbanov buf->attrs); 263af2c3834SStanimir Varbanov if (!buf->va) { 264af2c3834SStanimir Varbanov ret = -ENOMEM; 265af2c3834SStanimir Varbanov goto fail; 266af2c3834SStanimir Varbanov } 267af2c3834SStanimir Varbanov 268af2c3834SStanimir Varbanov memset(&bd, 0, sizeof(bd)); 269af2c3834SStanimir Varbanov bd.buffer_size = buf->size; 270af2c3834SStanimir Varbanov bd.buffer_type = buf->type; 271af2c3834SStanimir Varbanov bd.num_buffers = 1; 272af2c3834SStanimir Varbanov bd.device_addr = buf->da; 273af2c3834SStanimir Varbanov 274af2c3834SStanimir Varbanov ret = hfi_session_set_buffers(inst, &bd); 275af2c3834SStanimir Varbanov if (ret) { 276af2c3834SStanimir Varbanov dev_err(dev, "set session buffers failed\n"); 277af2c3834SStanimir Varbanov goto dma_free; 278af2c3834SStanimir Varbanov } 279af2c3834SStanimir Varbanov 280af2c3834SStanimir Varbanov list_add_tail(&buf->list, &inst->internalbufs); 281af2c3834SStanimir Varbanov } 282af2c3834SStanimir Varbanov 283af2c3834SStanimir Varbanov return 0; 284af2c3834SStanimir Varbanov 285af2c3834SStanimir Varbanov dma_free: 286af2c3834SStanimir Varbanov dma_free_attrs(dev, buf->size, buf->va, buf->da, buf->attrs); 287af2c3834SStanimir Varbanov fail: 288af2c3834SStanimir Varbanov kfree(buf); 289af2c3834SStanimir Varbanov return ret; 290af2c3834SStanimir Varbanov } 291af2c3834SStanimir Varbanov 292af2c3834SStanimir Varbanov static int intbufs_unset_buffers(struct venus_inst *inst) 293af2c3834SStanimir Varbanov { 294af2c3834SStanimir Varbanov struct hfi_buffer_desc bd = {0}; 295af2c3834SStanimir Varbanov struct intbuf *buf, *n; 296af2c3834SStanimir Varbanov int ret = 0; 297af2c3834SStanimir Varbanov 298af2c3834SStanimir Varbanov list_for_each_entry_safe(buf, n, &inst->internalbufs, list) { 299af2c3834SStanimir Varbanov bd.buffer_size = buf->size; 300af2c3834SStanimir Varbanov bd.buffer_type = buf->type; 301af2c3834SStanimir Varbanov bd.num_buffers = 1; 302af2c3834SStanimir Varbanov bd.device_addr = buf->da; 303af2c3834SStanimir Varbanov bd.response_required = true; 304af2c3834SStanimir Varbanov 305af2c3834SStanimir Varbanov ret = hfi_session_unset_buffers(inst, &bd); 306af2c3834SStanimir Varbanov 307af2c3834SStanimir Varbanov list_del_init(&buf->list); 308af2c3834SStanimir Varbanov dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da, 309af2c3834SStanimir Varbanov buf->attrs); 310af2c3834SStanimir Varbanov kfree(buf); 311af2c3834SStanimir Varbanov } 312af2c3834SStanimir Varbanov 313af2c3834SStanimir Varbanov return ret; 314af2c3834SStanimir Varbanov } 315af2c3834SStanimir Varbanov 316f04997bdSStanimir Varbanov static const unsigned int intbuf_types_1xx[] = { 317f04997bdSStanimir Varbanov HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_1XX), 318f04997bdSStanimir Varbanov HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_1XX), 319f04997bdSStanimir Varbanov HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_1XX), 320f04997bdSStanimir Varbanov HFI_BUFFER_INTERNAL_PERSIST, 321f04997bdSStanimir Varbanov HFI_BUFFER_INTERNAL_PERSIST_1, 322f04997bdSStanimir Varbanov }; 323f04997bdSStanimir Varbanov 324f04997bdSStanimir Varbanov static const unsigned int intbuf_types_4xx[] = { 325f04997bdSStanimir Varbanov HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_4XX), 326f04997bdSStanimir Varbanov HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_4XX), 327f04997bdSStanimir Varbanov HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_4XX), 328af2c3834SStanimir Varbanov HFI_BUFFER_INTERNAL_PERSIST, 329af2c3834SStanimir Varbanov HFI_BUFFER_INTERNAL_PERSIST_1, 330af2c3834SStanimir Varbanov }; 331af2c3834SStanimir Varbanov 332c934d9d4SDikshita Agarwal static const unsigned int intbuf_types_6xx[] = { 333c934d9d4SDikshita Agarwal HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_6XX), 334c934d9d4SDikshita Agarwal HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_6XX), 335c934d9d4SDikshita Agarwal HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_6XX), 336c934d9d4SDikshita Agarwal HFI_BUFFER_INTERNAL_PERSIST, 337c934d9d4SDikshita Agarwal HFI_BUFFER_INTERNAL_PERSIST_1, 338c934d9d4SDikshita Agarwal }; 339c934d9d4SDikshita Agarwal 3401e485ee5SStanimir Varbanov int venus_helper_intbufs_alloc(struct venus_inst *inst) 341af2c3834SStanimir Varbanov { 342f04997bdSStanimir Varbanov const unsigned int *intbuf; 343f04997bdSStanimir Varbanov size_t arr_sz, i; 344af2c3834SStanimir Varbanov int ret; 345af2c3834SStanimir Varbanov 346c934d9d4SDikshita Agarwal if (IS_V6(inst->core)) { 347c934d9d4SDikshita Agarwal arr_sz = ARRAY_SIZE(intbuf_types_6xx); 348c934d9d4SDikshita Agarwal intbuf = intbuf_types_6xx; 349c934d9d4SDikshita Agarwal } else if (IS_V4(inst->core)) { 350f04997bdSStanimir Varbanov arr_sz = ARRAY_SIZE(intbuf_types_4xx); 351f04997bdSStanimir Varbanov intbuf = intbuf_types_4xx; 352f04997bdSStanimir Varbanov } else { 353f04997bdSStanimir Varbanov arr_sz = ARRAY_SIZE(intbuf_types_1xx); 354f04997bdSStanimir Varbanov intbuf = intbuf_types_1xx; 355f04997bdSStanimir Varbanov } 356f04997bdSStanimir Varbanov 357f04997bdSStanimir Varbanov for (i = 0; i < arr_sz; i++) { 358f04997bdSStanimir Varbanov ret = intbufs_set_buffer(inst, intbuf[i]); 359af2c3834SStanimir Varbanov if (ret) 360af2c3834SStanimir Varbanov goto error; 361af2c3834SStanimir Varbanov } 362af2c3834SStanimir Varbanov 363af2c3834SStanimir Varbanov return 0; 364af2c3834SStanimir Varbanov 365af2c3834SStanimir Varbanov error: 366af2c3834SStanimir Varbanov intbufs_unset_buffers(inst); 367af2c3834SStanimir Varbanov return ret; 368af2c3834SStanimir Varbanov } 3691e485ee5SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_intbufs_alloc); 370af2c3834SStanimir Varbanov 3711e485ee5SStanimir Varbanov int venus_helper_intbufs_free(struct venus_inst *inst) 372af2c3834SStanimir Varbanov { 373af2c3834SStanimir Varbanov return intbufs_unset_buffers(inst); 374af2c3834SStanimir Varbanov } 3751e485ee5SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_intbufs_free); 376af2c3834SStanimir Varbanov 37714ea00d6SStanimir Varbanov int venus_helper_intbufs_realloc(struct venus_inst *inst) 37814ea00d6SStanimir Varbanov { 37914ea00d6SStanimir Varbanov enum hfi_version ver = inst->core->res->hfi_version; 38014ea00d6SStanimir Varbanov struct hfi_buffer_desc bd; 38114ea00d6SStanimir Varbanov struct intbuf *buf, *n; 38214ea00d6SStanimir Varbanov int ret; 38314ea00d6SStanimir Varbanov 38414ea00d6SStanimir Varbanov list_for_each_entry_safe(buf, n, &inst->internalbufs, list) { 38514ea00d6SStanimir Varbanov if (buf->type == HFI_BUFFER_INTERNAL_PERSIST || 38614ea00d6SStanimir Varbanov buf->type == HFI_BUFFER_INTERNAL_PERSIST_1) 38714ea00d6SStanimir Varbanov continue; 38814ea00d6SStanimir Varbanov 38914ea00d6SStanimir Varbanov memset(&bd, 0, sizeof(bd)); 39014ea00d6SStanimir Varbanov bd.buffer_size = buf->size; 39114ea00d6SStanimir Varbanov bd.buffer_type = buf->type; 39214ea00d6SStanimir Varbanov bd.num_buffers = 1; 39314ea00d6SStanimir Varbanov bd.device_addr = buf->da; 39414ea00d6SStanimir Varbanov bd.response_required = true; 39514ea00d6SStanimir Varbanov 39614ea00d6SStanimir Varbanov ret = hfi_session_unset_buffers(inst, &bd); 39714ea00d6SStanimir Varbanov 39814ea00d6SStanimir Varbanov dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da, 39914ea00d6SStanimir Varbanov buf->attrs); 40014ea00d6SStanimir Varbanov 40114ea00d6SStanimir Varbanov list_del_init(&buf->list); 40214ea00d6SStanimir Varbanov kfree(buf); 40314ea00d6SStanimir Varbanov } 40414ea00d6SStanimir Varbanov 40514ea00d6SStanimir Varbanov ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH(ver)); 40614ea00d6SStanimir Varbanov if (ret) 40714ea00d6SStanimir Varbanov goto err; 40814ea00d6SStanimir Varbanov 40914ea00d6SStanimir Varbanov ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH_1(ver)); 41014ea00d6SStanimir Varbanov if (ret) 41114ea00d6SStanimir Varbanov goto err; 41214ea00d6SStanimir Varbanov 41314ea00d6SStanimir Varbanov ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH_2(ver)); 41414ea00d6SStanimir Varbanov if (ret) 41514ea00d6SStanimir Varbanov goto err; 41614ea00d6SStanimir Varbanov 41714ea00d6SStanimir Varbanov return 0; 41814ea00d6SStanimir Varbanov err: 41914ea00d6SStanimir Varbanov return ret; 42014ea00d6SStanimir Varbanov } 42114ea00d6SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_intbufs_realloc); 42214ea00d6SStanimir Varbanov 423af2c3834SStanimir Varbanov static void fill_buffer_desc(const struct venus_buffer *buf, 424af2c3834SStanimir Varbanov struct hfi_buffer_desc *bd, bool response) 425af2c3834SStanimir Varbanov { 426af2c3834SStanimir Varbanov memset(bd, 0, sizeof(*bd)); 427af2c3834SStanimir Varbanov bd->buffer_type = HFI_BUFFER_OUTPUT; 428af2c3834SStanimir Varbanov bd->buffer_size = buf->size; 429af2c3834SStanimir Varbanov bd->num_buffers = 1; 430af2c3834SStanimir Varbanov bd->device_addr = buf->dma_addr; 431af2c3834SStanimir Varbanov bd->response_required = response; 432af2c3834SStanimir Varbanov } 433af2c3834SStanimir Varbanov 434af2c3834SStanimir Varbanov static void return_buf_error(struct venus_inst *inst, 435af2c3834SStanimir Varbanov struct vb2_v4l2_buffer *vbuf) 436af2c3834SStanimir Varbanov { 437af2c3834SStanimir Varbanov struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 438af2c3834SStanimir Varbanov 439af2c3834SStanimir Varbanov if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 440af2c3834SStanimir Varbanov v4l2_m2m_src_buf_remove_by_buf(m2m_ctx, vbuf); 441af2c3834SStanimir Varbanov else 4420de0ef6cSGustavo A. R. Silva v4l2_m2m_dst_buf_remove_by_buf(m2m_ctx, vbuf); 443af2c3834SStanimir Varbanov 444af2c3834SStanimir Varbanov v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); 445af2c3834SStanimir Varbanov } 446af2c3834SStanimir Varbanov 447d42974e4SStanimir Varbanov static void 448d42974e4SStanimir Varbanov put_ts_metadata(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) 449d42974e4SStanimir Varbanov { 450d42974e4SStanimir Varbanov struct vb2_buffer *vb = &vbuf->vb2_buf; 451d42974e4SStanimir Varbanov unsigned int i; 452d42974e4SStanimir Varbanov int slot = -1; 453d42974e4SStanimir Varbanov u64 ts_us = vb->timestamp; 454d42974e4SStanimir Varbanov 455d42974e4SStanimir Varbanov for (i = 0; i < ARRAY_SIZE(inst->tss); i++) { 456d42974e4SStanimir Varbanov if (!inst->tss[i].used) { 457d42974e4SStanimir Varbanov slot = i; 458d42974e4SStanimir Varbanov break; 459d42974e4SStanimir Varbanov } 460d42974e4SStanimir Varbanov } 461d42974e4SStanimir Varbanov 462d42974e4SStanimir Varbanov if (slot == -1) { 4638c91dc08SStanimir Varbanov dev_dbg(inst->core->dev, VDBGL "no free slot\n"); 464d42974e4SStanimir Varbanov return; 465d42974e4SStanimir Varbanov } 466d42974e4SStanimir Varbanov 467d42974e4SStanimir Varbanov do_div(ts_us, NSEC_PER_USEC); 468d42974e4SStanimir Varbanov 469d42974e4SStanimir Varbanov inst->tss[slot].used = true; 470d42974e4SStanimir Varbanov inst->tss[slot].flags = vbuf->flags; 471d42974e4SStanimir Varbanov inst->tss[slot].tc = vbuf->timecode; 472d42974e4SStanimir Varbanov inst->tss[slot].ts_us = ts_us; 473d42974e4SStanimir Varbanov inst->tss[slot].ts_ns = vb->timestamp; 474d42974e4SStanimir Varbanov } 475d42974e4SStanimir Varbanov 476d42974e4SStanimir Varbanov void venus_helper_get_ts_metadata(struct venus_inst *inst, u64 timestamp_us, 477d42974e4SStanimir Varbanov struct vb2_v4l2_buffer *vbuf) 478d42974e4SStanimir Varbanov { 479d42974e4SStanimir Varbanov struct vb2_buffer *vb = &vbuf->vb2_buf; 480d42974e4SStanimir Varbanov unsigned int i; 481d42974e4SStanimir Varbanov 482d42974e4SStanimir Varbanov for (i = 0; i < ARRAY_SIZE(inst->tss); ++i) { 483d42974e4SStanimir Varbanov if (!inst->tss[i].used) 484d42974e4SStanimir Varbanov continue; 485d42974e4SStanimir Varbanov 486d42974e4SStanimir Varbanov if (inst->tss[i].ts_us != timestamp_us) 487d42974e4SStanimir Varbanov continue; 488d42974e4SStanimir Varbanov 489d42974e4SStanimir Varbanov inst->tss[i].used = false; 490d42974e4SStanimir Varbanov vbuf->flags |= inst->tss[i].flags; 491d42974e4SStanimir Varbanov vbuf->timecode = inst->tss[i].tc; 492d42974e4SStanimir Varbanov vb->timestamp = inst->tss[i].ts_ns; 493d42974e4SStanimir Varbanov break; 494d42974e4SStanimir Varbanov } 495d42974e4SStanimir Varbanov } 496d42974e4SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_ts_metadata); 497d42974e4SStanimir Varbanov 498af2c3834SStanimir Varbanov static int 499af2c3834SStanimir Varbanov session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) 500af2c3834SStanimir Varbanov { 501af2c3834SStanimir Varbanov struct venus_buffer *buf = to_venus_buffer(vbuf); 502af2c3834SStanimir Varbanov struct vb2_buffer *vb = &vbuf->vb2_buf; 503af2c3834SStanimir Varbanov unsigned int type = vb->type; 504af2c3834SStanimir Varbanov struct hfi_frame_data fdata; 505af2c3834SStanimir Varbanov int ret; 506af2c3834SStanimir Varbanov 507af2c3834SStanimir Varbanov memset(&fdata, 0, sizeof(fdata)); 508af2c3834SStanimir Varbanov fdata.alloc_len = buf->size; 509af2c3834SStanimir Varbanov fdata.device_addr = buf->dma_addr; 510af2c3834SStanimir Varbanov fdata.timestamp = vb->timestamp; 511af2c3834SStanimir Varbanov do_div(fdata.timestamp, NSEC_PER_USEC); 512af2c3834SStanimir Varbanov fdata.flags = 0; 513af2c3834SStanimir Varbanov fdata.clnt_data = vbuf->vb2_buf.index; 514af2c3834SStanimir Varbanov 515af2c3834SStanimir Varbanov if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 516af2c3834SStanimir Varbanov fdata.buffer_type = HFI_BUFFER_INPUT; 517af2c3834SStanimir Varbanov fdata.filled_len = vb2_get_plane_payload(vb, 0); 518af2c3834SStanimir Varbanov fdata.offset = vb->planes[0].data_offset; 519af2c3834SStanimir Varbanov 520af2c3834SStanimir Varbanov if (vbuf->flags & V4L2_BUF_FLAG_LAST || !fdata.filled_len) 521af2c3834SStanimir Varbanov fdata.flags |= HFI_BUFFERFLAG_EOS; 522d42974e4SStanimir Varbanov 523d42974e4SStanimir Varbanov if (inst->session_type == VIDC_SESSION_TYPE_DEC) 524d42974e4SStanimir Varbanov put_ts_metadata(inst, vbuf); 525c0e284ccSAniket Masule 5267482a983SStanimir Varbanov venus_pm_load_scale(inst); 527af2c3834SStanimir Varbanov } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 528f012b23dSStanimir Varbanov if (inst->session_type == VIDC_SESSION_TYPE_ENC) 529af2c3834SStanimir Varbanov fdata.buffer_type = HFI_BUFFER_OUTPUT; 530f012b23dSStanimir Varbanov else 531f012b23dSStanimir Varbanov fdata.buffer_type = inst->opb_buftype; 532af2c3834SStanimir Varbanov fdata.filled_len = 0; 533af2c3834SStanimir Varbanov fdata.offset = 0; 534af2c3834SStanimir Varbanov } 535af2c3834SStanimir Varbanov 536af2c3834SStanimir Varbanov ret = hfi_session_process_buf(inst, &fdata); 537af2c3834SStanimir Varbanov if (ret) 538af2c3834SStanimir Varbanov return ret; 539af2c3834SStanimir Varbanov 540af2c3834SStanimir Varbanov return 0; 541af2c3834SStanimir Varbanov } 542af2c3834SStanimir Varbanov 543f0383520SStanimir Varbanov static bool is_dynamic_bufmode(struct venus_inst *inst) 544af2c3834SStanimir Varbanov { 545f0383520SStanimir Varbanov struct venus_core *core = inst->core; 5468f3b41dcSStanimir Varbanov struct hfi_plat_caps *caps; 547f0383520SStanimir Varbanov 548bc8c479aSStanimir Varbanov /* 549bc8c479aSStanimir Varbanov * v4 doesn't send BUFFER_ALLOC_MODE_SUPPORTED property and supports 550bc8c479aSStanimir Varbanov * dynamic buffer mode by default for HFI_BUFFER_OUTPUT/OUTPUT2. 551bc8c479aSStanimir Varbanov */ 5527ed9e0b3SBryan O'Donoghue if (IS_V4(core) || IS_V6(core)) 553bc8c479aSStanimir Varbanov return true; 554bc8c479aSStanimir Varbanov 555f0383520SStanimir Varbanov caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type); 556f0383520SStanimir Varbanov if (!caps) 5571cafbb86SGustavo A. R. Silva return false; 558af2c3834SStanimir Varbanov 559f0383520SStanimir Varbanov return caps->cap_bufs_mode_dynamic; 560af2c3834SStanimir Varbanov } 561af2c3834SStanimir Varbanov 5621e485ee5SStanimir Varbanov int venus_helper_unregister_bufs(struct venus_inst *inst) 563af2c3834SStanimir Varbanov { 564af2c3834SStanimir Varbanov struct venus_buffer *buf, *n; 565af2c3834SStanimir Varbanov struct hfi_buffer_desc bd; 566af2c3834SStanimir Varbanov int ret = 0; 567af2c3834SStanimir Varbanov 568f0383520SStanimir Varbanov if (is_dynamic_bufmode(inst)) 569af2c3834SStanimir Varbanov return 0; 570af2c3834SStanimir Varbanov 571af2c3834SStanimir Varbanov list_for_each_entry_safe(buf, n, &inst->registeredbufs, reg_list) { 572af2c3834SStanimir Varbanov fill_buffer_desc(buf, &bd, true); 573af2c3834SStanimir Varbanov ret = hfi_session_unset_buffers(inst, &bd); 574af2c3834SStanimir Varbanov list_del_init(&buf->reg_list); 575af2c3834SStanimir Varbanov } 576af2c3834SStanimir Varbanov 577af2c3834SStanimir Varbanov return ret; 578af2c3834SStanimir Varbanov } 5791e485ee5SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_unregister_bufs); 580af2c3834SStanimir Varbanov 581af2c3834SStanimir Varbanov static int session_register_bufs(struct venus_inst *inst) 582af2c3834SStanimir Varbanov { 583af2c3834SStanimir Varbanov struct venus_core *core = inst->core; 584af2c3834SStanimir Varbanov struct device *dev = core->dev; 585af2c3834SStanimir Varbanov struct hfi_buffer_desc bd; 586af2c3834SStanimir Varbanov struct venus_buffer *buf; 587af2c3834SStanimir Varbanov int ret = 0; 588af2c3834SStanimir Varbanov 589f0383520SStanimir Varbanov if (is_dynamic_bufmode(inst)) 590af2c3834SStanimir Varbanov return 0; 591af2c3834SStanimir Varbanov 592af2c3834SStanimir Varbanov list_for_each_entry(buf, &inst->registeredbufs, reg_list) { 593af2c3834SStanimir Varbanov fill_buffer_desc(buf, &bd, false); 594af2c3834SStanimir Varbanov ret = hfi_session_set_buffers(inst, &bd); 595af2c3834SStanimir Varbanov if (ret) { 596af2c3834SStanimir Varbanov dev_err(dev, "%s: set buffer failed\n", __func__); 597af2c3834SStanimir Varbanov break; 598af2c3834SStanimir Varbanov } 599af2c3834SStanimir Varbanov } 600af2c3834SStanimir Varbanov 601af2c3834SStanimir Varbanov return ret; 602af2c3834SStanimir Varbanov } 603af2c3834SStanimir Varbanov 604ab97a3fbSStanimir Varbanov static u32 to_hfi_raw_fmt(u32 v4l2_fmt) 605ab97a3fbSStanimir Varbanov { 606ab97a3fbSStanimir Varbanov switch (v4l2_fmt) { 607ab97a3fbSStanimir Varbanov case V4L2_PIX_FMT_NV12: 608ab97a3fbSStanimir Varbanov return HFI_COLOR_FORMAT_NV12; 609ab97a3fbSStanimir Varbanov case V4L2_PIX_FMT_NV21: 610ab97a3fbSStanimir Varbanov return HFI_COLOR_FORMAT_NV21; 611ab97a3fbSStanimir Varbanov default: 612ab97a3fbSStanimir Varbanov break; 613ab97a3fbSStanimir Varbanov } 614ab97a3fbSStanimir Varbanov 615ab97a3fbSStanimir Varbanov return 0; 616ab97a3fbSStanimir Varbanov } 617ab97a3fbSStanimir Varbanov 6187371093fSStanimir Varbanov static int platform_get_bufreq(struct venus_inst *inst, u32 buftype, 6197371093fSStanimir Varbanov struct hfi_buffer_requirements *req) 6207371093fSStanimir Varbanov { 6217371093fSStanimir Varbanov enum hfi_version version = inst->core->res->hfi_version; 6227371093fSStanimir Varbanov const struct hfi_platform *hfi_plat; 6237371093fSStanimir Varbanov struct hfi_plat_buffers_params params; 6247371093fSStanimir Varbanov bool is_dec = inst->session_type == VIDC_SESSION_TYPE_DEC; 6257371093fSStanimir Varbanov struct venc_controls *enc_ctr = &inst->controls.enc; 6267371093fSStanimir Varbanov 6277371093fSStanimir Varbanov hfi_plat = hfi_platform_get(version); 6287371093fSStanimir Varbanov 6297371093fSStanimir Varbanov if (!hfi_plat || !hfi_plat->bufreq) 6307371093fSStanimir Varbanov return -EINVAL; 6317371093fSStanimir Varbanov 6327371093fSStanimir Varbanov params.version = version; 633920173c7SDikshita Agarwal params.num_vpp_pipes = inst->core->res->num_vpp_pipes; 6347371093fSStanimir Varbanov 6357371093fSStanimir Varbanov if (is_dec) { 6367371093fSStanimir Varbanov params.width = inst->width; 6377371093fSStanimir Varbanov params.height = inst->height; 6387371093fSStanimir Varbanov params.codec = inst->fmt_out->pixfmt; 6397371093fSStanimir Varbanov params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_cap->pixfmt); 6407371093fSStanimir Varbanov params.dec.max_mbs_per_frame = mbs_per_frame_max(inst); 6417371093fSStanimir Varbanov params.dec.buffer_size_limit = 0; 6427371093fSStanimir Varbanov params.dec.is_secondary_output = 6437371093fSStanimir Varbanov inst->opb_buftype == HFI_BUFFER_OUTPUT2; 6447371093fSStanimir Varbanov params.dec.is_interlaced = 6456fc46680SZhen Lei inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE; 6467371093fSStanimir Varbanov } else { 6477371093fSStanimir Varbanov params.width = inst->out_width; 6487371093fSStanimir Varbanov params.height = inst->out_height; 6497371093fSStanimir Varbanov params.codec = inst->fmt_cap->pixfmt; 6507371093fSStanimir Varbanov params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_out->pixfmt); 6517371093fSStanimir Varbanov params.enc.work_mode = VIDC_WORK_MODE_2; 6527371093fSStanimir Varbanov params.enc.rc_type = HFI_RATE_CONTROL_OFF; 6537371093fSStanimir Varbanov if (enc_ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) 6547371093fSStanimir Varbanov params.enc.rc_type = HFI_RATE_CONTROL_CQ; 6557371093fSStanimir Varbanov params.enc.num_b_frames = enc_ctr->num_b_frames; 6567371093fSStanimir Varbanov params.enc.is_tenbit = inst->bit_depth == VIDC_BITDEPTH_10; 6577371093fSStanimir Varbanov } 6587371093fSStanimir Varbanov 6597371093fSStanimir Varbanov return hfi_plat->bufreq(¶ms, inst->session_type, buftype, req); 6607371093fSStanimir Varbanov } 6617371093fSStanimir Varbanov 662af2c3834SStanimir Varbanov int venus_helper_get_bufreq(struct venus_inst *inst, u32 type, 663af2c3834SStanimir Varbanov struct hfi_buffer_requirements *req) 664af2c3834SStanimir Varbanov { 665af2c3834SStanimir Varbanov u32 ptype = HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS; 666af2c3834SStanimir Varbanov union hfi_get_property hprop; 667af2c3834SStanimir Varbanov unsigned int i; 668af2c3834SStanimir Varbanov int ret; 669af2c3834SStanimir Varbanov 670af2c3834SStanimir Varbanov if (req) 671af2c3834SStanimir Varbanov memset(req, 0, sizeof(*req)); 672af2c3834SStanimir Varbanov 67316545aa3SDikshita Agarwal if (type == HFI_BUFFER_OUTPUT || type == HFI_BUFFER_OUTPUT2) 67416545aa3SDikshita Agarwal req->count_min = inst->fw_min_cnt; 67516545aa3SDikshita Agarwal 6767371093fSStanimir Varbanov ret = platform_get_bufreq(inst, type, req); 67716545aa3SDikshita Agarwal if (!ret) { 67816545aa3SDikshita Agarwal if (type == HFI_BUFFER_OUTPUT || type == HFI_BUFFER_OUTPUT2) 67916545aa3SDikshita Agarwal inst->fw_min_cnt = req->count_min; 6807371093fSStanimir Varbanov return 0; 68116545aa3SDikshita Agarwal } 6827371093fSStanimir Varbanov 683af2c3834SStanimir Varbanov ret = hfi_session_get_property(inst, ptype, &hprop); 684af2c3834SStanimir Varbanov if (ret) 685af2c3834SStanimir Varbanov return ret; 686af2c3834SStanimir Varbanov 687af2c3834SStanimir Varbanov ret = -EINVAL; 688af2c3834SStanimir Varbanov 689af2c3834SStanimir Varbanov for (i = 0; i < HFI_BUFFER_TYPE_MAX; i++) { 690af2c3834SStanimir Varbanov if (hprop.bufreq[i].type != type) 691af2c3834SStanimir Varbanov continue; 692af2c3834SStanimir Varbanov 693af2c3834SStanimir Varbanov if (req) 694af2c3834SStanimir Varbanov memcpy(req, &hprop.bufreq[i], sizeof(*req)); 695af2c3834SStanimir Varbanov ret = 0; 696af2c3834SStanimir Varbanov break; 697af2c3834SStanimir Varbanov } 698af2c3834SStanimir Varbanov 699af2c3834SStanimir Varbanov return ret; 700af2c3834SStanimir Varbanov } 701af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_bufreq); 702af2c3834SStanimir Varbanov 7032c2dc2fdSStanimir Varbanov struct id_mapping { 7042c2dc2fdSStanimir Varbanov u32 hfi_id; 7052c2dc2fdSStanimir Varbanov u32 v4l2_id; 7062c2dc2fdSStanimir Varbanov }; 7072c2dc2fdSStanimir Varbanov 7082c2dc2fdSStanimir Varbanov static const struct id_mapping mpeg4_profiles[] = { 7092c2dc2fdSStanimir Varbanov { HFI_MPEG4_PROFILE_SIMPLE, V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE }, 7102c2dc2fdSStanimir Varbanov { HFI_MPEG4_PROFILE_ADVANCEDSIMPLE, V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE }, 7112c2dc2fdSStanimir Varbanov }; 7122c2dc2fdSStanimir Varbanov 7132c2dc2fdSStanimir Varbanov static const struct id_mapping mpeg4_levels[] = { 7142c2dc2fdSStanimir Varbanov { HFI_MPEG4_LEVEL_0, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0 }, 7152c2dc2fdSStanimir Varbanov { HFI_MPEG4_LEVEL_0b, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B }, 7162c2dc2fdSStanimir Varbanov { HFI_MPEG4_LEVEL_1, V4L2_MPEG_VIDEO_MPEG4_LEVEL_1 }, 7172c2dc2fdSStanimir Varbanov { HFI_MPEG4_LEVEL_2, V4L2_MPEG_VIDEO_MPEG4_LEVEL_2 }, 7182c2dc2fdSStanimir Varbanov { HFI_MPEG4_LEVEL_3, V4L2_MPEG_VIDEO_MPEG4_LEVEL_3 }, 7192c2dc2fdSStanimir Varbanov { HFI_MPEG4_LEVEL_4, V4L2_MPEG_VIDEO_MPEG4_LEVEL_4 }, 7202c2dc2fdSStanimir Varbanov { HFI_MPEG4_LEVEL_5, V4L2_MPEG_VIDEO_MPEG4_LEVEL_5 }, 7212c2dc2fdSStanimir Varbanov }; 7222c2dc2fdSStanimir Varbanov 7232c2dc2fdSStanimir Varbanov static const struct id_mapping mpeg2_profiles[] = { 7242c2dc2fdSStanimir Varbanov { HFI_MPEG2_PROFILE_SIMPLE, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SIMPLE }, 7252c2dc2fdSStanimir Varbanov { HFI_MPEG2_PROFILE_MAIN, V4L2_MPEG_VIDEO_MPEG2_PROFILE_MAIN }, 7262c2dc2fdSStanimir Varbanov { HFI_MPEG2_PROFILE_SNR, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SNR_SCALABLE }, 7272c2dc2fdSStanimir Varbanov { HFI_MPEG2_PROFILE_SPATIAL, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SPATIALLY_SCALABLE }, 7282c2dc2fdSStanimir Varbanov { HFI_MPEG2_PROFILE_HIGH, V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH }, 7292c2dc2fdSStanimir Varbanov }; 7302c2dc2fdSStanimir Varbanov 7312c2dc2fdSStanimir Varbanov static const struct id_mapping mpeg2_levels[] = { 7322c2dc2fdSStanimir Varbanov { HFI_MPEG2_LEVEL_LL, V4L2_MPEG_VIDEO_MPEG2_LEVEL_LOW }, 7332c2dc2fdSStanimir Varbanov { HFI_MPEG2_LEVEL_ML, V4L2_MPEG_VIDEO_MPEG2_LEVEL_MAIN }, 7342c2dc2fdSStanimir Varbanov { HFI_MPEG2_LEVEL_H14, V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH_1440 }, 7352c2dc2fdSStanimir Varbanov { HFI_MPEG2_LEVEL_HL, V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH }, 7362c2dc2fdSStanimir Varbanov }; 7372c2dc2fdSStanimir Varbanov 7382c2dc2fdSStanimir Varbanov static const struct id_mapping h264_profiles[] = { 7392c2dc2fdSStanimir Varbanov { HFI_H264_PROFILE_BASELINE, V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE }, 7402c2dc2fdSStanimir Varbanov { HFI_H264_PROFILE_MAIN, V4L2_MPEG_VIDEO_H264_PROFILE_MAIN }, 7412c2dc2fdSStanimir Varbanov { HFI_H264_PROFILE_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_HIGH }, 7422c2dc2fdSStanimir Varbanov { HFI_H264_PROFILE_STEREO_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH }, 7432c2dc2fdSStanimir Varbanov { HFI_H264_PROFILE_MULTIVIEW_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH }, 7442c2dc2fdSStanimir Varbanov { HFI_H264_PROFILE_CONSTRAINED_BASE, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE }, 7452c2dc2fdSStanimir Varbanov { HFI_H264_PROFILE_CONSTRAINED_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH }, 7462c2dc2fdSStanimir Varbanov }; 7472c2dc2fdSStanimir Varbanov 7482c2dc2fdSStanimir Varbanov static const struct id_mapping h264_levels[] = { 7492c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_1, V4L2_MPEG_VIDEO_H264_LEVEL_1_0 }, 7502c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_1b, V4L2_MPEG_VIDEO_H264_LEVEL_1B }, 7512c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_11, V4L2_MPEG_VIDEO_H264_LEVEL_1_1 }, 7522c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_12, V4L2_MPEG_VIDEO_H264_LEVEL_1_2 }, 7532c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_13, V4L2_MPEG_VIDEO_H264_LEVEL_1_3 }, 7542c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_2, V4L2_MPEG_VIDEO_H264_LEVEL_2_0 }, 7552c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_21, V4L2_MPEG_VIDEO_H264_LEVEL_2_1 }, 7562c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_22, V4L2_MPEG_VIDEO_H264_LEVEL_2_2 }, 7572c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_3, V4L2_MPEG_VIDEO_H264_LEVEL_3_0 }, 7582c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_31, V4L2_MPEG_VIDEO_H264_LEVEL_3_1 }, 7592c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_32, V4L2_MPEG_VIDEO_H264_LEVEL_3_2 }, 7602c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_4, V4L2_MPEG_VIDEO_H264_LEVEL_4_0 }, 7612c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_41, V4L2_MPEG_VIDEO_H264_LEVEL_4_1 }, 7622c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_42, V4L2_MPEG_VIDEO_H264_LEVEL_4_2 }, 7632c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_5, V4L2_MPEG_VIDEO_H264_LEVEL_5_0 }, 7642c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_51, V4L2_MPEG_VIDEO_H264_LEVEL_5_1 }, 7652c2dc2fdSStanimir Varbanov { HFI_H264_LEVEL_52, V4L2_MPEG_VIDEO_H264_LEVEL_5_1 }, 7662c2dc2fdSStanimir Varbanov }; 7672c2dc2fdSStanimir Varbanov 7682c2dc2fdSStanimir Varbanov static const struct id_mapping hevc_profiles[] = { 7692c2dc2fdSStanimir Varbanov { HFI_HEVC_PROFILE_MAIN, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN }, 7702c2dc2fdSStanimir Varbanov { HFI_HEVC_PROFILE_MAIN_STILL_PIC, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE }, 7712c2dc2fdSStanimir Varbanov { HFI_HEVC_PROFILE_MAIN10, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10 }, 7722c2dc2fdSStanimir Varbanov }; 7732c2dc2fdSStanimir Varbanov 7742c2dc2fdSStanimir Varbanov static const struct id_mapping hevc_levels[] = { 7752c2dc2fdSStanimir Varbanov { HFI_HEVC_LEVEL_1, V4L2_MPEG_VIDEO_HEVC_LEVEL_1 }, 7762c2dc2fdSStanimir Varbanov { HFI_HEVC_LEVEL_2, V4L2_MPEG_VIDEO_HEVC_LEVEL_2 }, 7772c2dc2fdSStanimir Varbanov { HFI_HEVC_LEVEL_21, V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1 }, 7782c2dc2fdSStanimir Varbanov { HFI_HEVC_LEVEL_3, V4L2_MPEG_VIDEO_HEVC_LEVEL_3 }, 7792c2dc2fdSStanimir Varbanov { HFI_HEVC_LEVEL_31, V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1 }, 7802c2dc2fdSStanimir Varbanov { HFI_HEVC_LEVEL_4, V4L2_MPEG_VIDEO_HEVC_LEVEL_4 }, 7812c2dc2fdSStanimir Varbanov { HFI_HEVC_LEVEL_41, V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1 }, 7822c2dc2fdSStanimir Varbanov { HFI_HEVC_LEVEL_5, V4L2_MPEG_VIDEO_HEVC_LEVEL_5 }, 7832c2dc2fdSStanimir Varbanov { HFI_HEVC_LEVEL_51, V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1 }, 7842c2dc2fdSStanimir Varbanov { HFI_HEVC_LEVEL_52, V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2 }, 7852c2dc2fdSStanimir Varbanov { HFI_HEVC_LEVEL_6, V4L2_MPEG_VIDEO_HEVC_LEVEL_6 }, 7862c2dc2fdSStanimir Varbanov { HFI_HEVC_LEVEL_61, V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1 }, 7872c2dc2fdSStanimir Varbanov { HFI_HEVC_LEVEL_62, V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2 }, 7882c2dc2fdSStanimir Varbanov }; 7892c2dc2fdSStanimir Varbanov 7902c2dc2fdSStanimir Varbanov static const struct id_mapping vp8_profiles[] = { 7912c2dc2fdSStanimir Varbanov { HFI_VPX_PROFILE_VERSION_0, V4L2_MPEG_VIDEO_VP8_PROFILE_0 }, 7922c2dc2fdSStanimir Varbanov { HFI_VPX_PROFILE_VERSION_1, V4L2_MPEG_VIDEO_VP8_PROFILE_1 }, 7932c2dc2fdSStanimir Varbanov { HFI_VPX_PROFILE_VERSION_2, V4L2_MPEG_VIDEO_VP8_PROFILE_2 }, 7942c2dc2fdSStanimir Varbanov { HFI_VPX_PROFILE_VERSION_3, V4L2_MPEG_VIDEO_VP8_PROFILE_3 }, 7952c2dc2fdSStanimir Varbanov }; 7962c2dc2fdSStanimir Varbanov 7972c2dc2fdSStanimir Varbanov static const struct id_mapping vp9_profiles[] = { 7982c2dc2fdSStanimir Varbanov { HFI_VP9_PROFILE_P0, V4L2_MPEG_VIDEO_VP9_PROFILE_0 }, 7992c2dc2fdSStanimir Varbanov { HFI_VP9_PROFILE_P2_10B, V4L2_MPEG_VIDEO_VP9_PROFILE_2 }, 8002c2dc2fdSStanimir Varbanov }; 8012c2dc2fdSStanimir Varbanov 8022c2dc2fdSStanimir Varbanov static const struct id_mapping vp9_levels[] = { 8032c2dc2fdSStanimir Varbanov { HFI_VP9_LEVEL_1, V4L2_MPEG_VIDEO_VP9_LEVEL_1_0 }, 8042c2dc2fdSStanimir Varbanov { HFI_VP9_LEVEL_11, V4L2_MPEG_VIDEO_VP9_LEVEL_1_1 }, 8052c2dc2fdSStanimir Varbanov { HFI_VP9_LEVEL_2, V4L2_MPEG_VIDEO_VP9_LEVEL_2_0}, 8062c2dc2fdSStanimir Varbanov { HFI_VP9_LEVEL_21, V4L2_MPEG_VIDEO_VP9_LEVEL_2_1 }, 8072c2dc2fdSStanimir Varbanov { HFI_VP9_LEVEL_3, V4L2_MPEG_VIDEO_VP9_LEVEL_3_0}, 8082c2dc2fdSStanimir Varbanov { HFI_VP9_LEVEL_31, V4L2_MPEG_VIDEO_VP9_LEVEL_3_1 }, 8092c2dc2fdSStanimir Varbanov { HFI_VP9_LEVEL_4, V4L2_MPEG_VIDEO_VP9_LEVEL_4_0 }, 8102c2dc2fdSStanimir Varbanov { HFI_VP9_LEVEL_41, V4L2_MPEG_VIDEO_VP9_LEVEL_4_1 }, 8112c2dc2fdSStanimir Varbanov { HFI_VP9_LEVEL_5, V4L2_MPEG_VIDEO_VP9_LEVEL_5_0 }, 8122c2dc2fdSStanimir Varbanov { HFI_VP9_LEVEL_51, V4L2_MPEG_VIDEO_VP9_LEVEL_5_1 }, 8132c2dc2fdSStanimir Varbanov { HFI_VP9_LEVEL_6, V4L2_MPEG_VIDEO_VP9_LEVEL_6_0 }, 8142c2dc2fdSStanimir Varbanov { HFI_VP9_LEVEL_61, V4L2_MPEG_VIDEO_VP9_LEVEL_6_1 }, 8152c2dc2fdSStanimir Varbanov }; 8162c2dc2fdSStanimir Varbanov 8172c2dc2fdSStanimir Varbanov static u32 find_v4l2_id(u32 hfi_id, const struct id_mapping *array, unsigned int array_sz) 8182c2dc2fdSStanimir Varbanov { 8192c2dc2fdSStanimir Varbanov unsigned int i; 8202c2dc2fdSStanimir Varbanov 8212c2dc2fdSStanimir Varbanov if (!array || !array_sz) 8222c2dc2fdSStanimir Varbanov return 0; 8232c2dc2fdSStanimir Varbanov 8242c2dc2fdSStanimir Varbanov for (i = 0; i < array_sz; i++) 8252c2dc2fdSStanimir Varbanov if (hfi_id == array[i].hfi_id) 8262c2dc2fdSStanimir Varbanov return array[i].v4l2_id; 8272c2dc2fdSStanimir Varbanov 8282c2dc2fdSStanimir Varbanov return 0; 8292c2dc2fdSStanimir Varbanov } 8302c2dc2fdSStanimir Varbanov 8312c2dc2fdSStanimir Varbanov static u32 find_hfi_id(u32 v4l2_id, const struct id_mapping *array, unsigned int array_sz) 8322c2dc2fdSStanimir Varbanov { 8332c2dc2fdSStanimir Varbanov unsigned int i; 8342c2dc2fdSStanimir Varbanov 8352c2dc2fdSStanimir Varbanov if (!array || !array_sz) 8362c2dc2fdSStanimir Varbanov return 0; 8372c2dc2fdSStanimir Varbanov 8382c2dc2fdSStanimir Varbanov for (i = 0; i < array_sz; i++) 8392c2dc2fdSStanimir Varbanov if (v4l2_id == array[i].v4l2_id) 8402c2dc2fdSStanimir Varbanov return array[i].hfi_id; 8412c2dc2fdSStanimir Varbanov 8422c2dc2fdSStanimir Varbanov return 0; 8432c2dc2fdSStanimir Varbanov } 8442c2dc2fdSStanimir Varbanov 8452c2dc2fdSStanimir Varbanov static void 8462c2dc2fdSStanimir Varbanov v4l2_id_profile_level(u32 hfi_codec, struct hfi_profile_level *pl, u32 *profile, u32 *level) 8472c2dc2fdSStanimir Varbanov { 8482c2dc2fdSStanimir Varbanov u32 hfi_pf = pl->profile; 8492c2dc2fdSStanimir Varbanov u32 hfi_lvl = pl->level; 8502c2dc2fdSStanimir Varbanov 8512c2dc2fdSStanimir Varbanov switch (hfi_codec) { 8522c2dc2fdSStanimir Varbanov case HFI_VIDEO_CODEC_H264: 8532c2dc2fdSStanimir Varbanov *profile = find_v4l2_id(hfi_pf, h264_profiles, ARRAY_SIZE(h264_profiles)); 8542c2dc2fdSStanimir Varbanov *level = find_v4l2_id(hfi_lvl, h264_levels, ARRAY_SIZE(h264_levels)); 8552c2dc2fdSStanimir Varbanov break; 8562c2dc2fdSStanimir Varbanov case HFI_VIDEO_CODEC_MPEG2: 8572c2dc2fdSStanimir Varbanov *profile = find_v4l2_id(hfi_pf, mpeg2_profiles, ARRAY_SIZE(mpeg2_profiles)); 8582c2dc2fdSStanimir Varbanov *level = find_v4l2_id(hfi_lvl, mpeg2_levels, ARRAY_SIZE(mpeg2_levels)); 8592c2dc2fdSStanimir Varbanov break; 8602c2dc2fdSStanimir Varbanov case HFI_VIDEO_CODEC_MPEG4: 8612c2dc2fdSStanimir Varbanov *profile = find_v4l2_id(hfi_pf, mpeg4_profiles, ARRAY_SIZE(mpeg4_profiles)); 8622c2dc2fdSStanimir Varbanov *level = find_v4l2_id(hfi_lvl, mpeg4_levels, ARRAY_SIZE(mpeg4_levels)); 8632c2dc2fdSStanimir Varbanov break; 8642c2dc2fdSStanimir Varbanov case HFI_VIDEO_CODEC_VP8: 8652c2dc2fdSStanimir Varbanov *profile = find_v4l2_id(hfi_pf, vp8_profiles, ARRAY_SIZE(vp8_profiles)); 8662c2dc2fdSStanimir Varbanov *level = 0; 8672c2dc2fdSStanimir Varbanov break; 8682c2dc2fdSStanimir Varbanov case HFI_VIDEO_CODEC_VP9: 8692c2dc2fdSStanimir Varbanov *profile = find_v4l2_id(hfi_pf, vp9_profiles, ARRAY_SIZE(vp9_profiles)); 8702c2dc2fdSStanimir Varbanov *level = find_v4l2_id(hfi_lvl, vp9_levels, ARRAY_SIZE(vp9_levels)); 8712c2dc2fdSStanimir Varbanov break; 8722c2dc2fdSStanimir Varbanov case HFI_VIDEO_CODEC_HEVC: 8732c2dc2fdSStanimir Varbanov *profile = find_v4l2_id(hfi_pf, hevc_profiles, ARRAY_SIZE(hevc_profiles)); 8742c2dc2fdSStanimir Varbanov *level = find_v4l2_id(hfi_lvl, hevc_levels, ARRAY_SIZE(hevc_levels)); 8752c2dc2fdSStanimir Varbanov break; 8762c2dc2fdSStanimir Varbanov default: 8772c2dc2fdSStanimir Varbanov break; 8782c2dc2fdSStanimir Varbanov } 8792c2dc2fdSStanimir Varbanov } 8802c2dc2fdSStanimir Varbanov 8812c2dc2fdSStanimir Varbanov static void 8822c2dc2fdSStanimir Varbanov hfi_id_profile_level(u32 hfi_codec, u32 v4l2_pf, u32 v4l2_lvl, struct hfi_profile_level *pl) 8832c2dc2fdSStanimir Varbanov { 8842c2dc2fdSStanimir Varbanov switch (hfi_codec) { 8852c2dc2fdSStanimir Varbanov case HFI_VIDEO_CODEC_H264: 8862c2dc2fdSStanimir Varbanov pl->profile = find_hfi_id(v4l2_pf, h264_profiles, ARRAY_SIZE(h264_profiles)); 8872c2dc2fdSStanimir Varbanov pl->level = find_hfi_id(v4l2_lvl, h264_levels, ARRAY_SIZE(h264_levels)); 8882c2dc2fdSStanimir Varbanov break; 8892c2dc2fdSStanimir Varbanov case HFI_VIDEO_CODEC_MPEG2: 8902c2dc2fdSStanimir Varbanov pl->profile = find_hfi_id(v4l2_pf, mpeg2_profiles, ARRAY_SIZE(mpeg2_profiles)); 8912c2dc2fdSStanimir Varbanov pl->level = find_hfi_id(v4l2_lvl, mpeg2_levels, ARRAY_SIZE(mpeg2_levels)); 8922c2dc2fdSStanimir Varbanov break; 8932c2dc2fdSStanimir Varbanov case HFI_VIDEO_CODEC_MPEG4: 8942c2dc2fdSStanimir Varbanov pl->profile = find_hfi_id(v4l2_pf, mpeg4_profiles, ARRAY_SIZE(mpeg4_profiles)); 8952c2dc2fdSStanimir Varbanov pl->level = find_hfi_id(v4l2_lvl, mpeg4_levels, ARRAY_SIZE(mpeg4_levels)); 8962c2dc2fdSStanimir Varbanov break; 8972c2dc2fdSStanimir Varbanov case HFI_VIDEO_CODEC_VP8: 8982c2dc2fdSStanimir Varbanov pl->profile = find_hfi_id(v4l2_pf, vp8_profiles, ARRAY_SIZE(vp8_profiles)); 8992c2dc2fdSStanimir Varbanov pl->level = 0; 9002c2dc2fdSStanimir Varbanov break; 9012c2dc2fdSStanimir Varbanov case HFI_VIDEO_CODEC_VP9: 9022c2dc2fdSStanimir Varbanov pl->profile = find_hfi_id(v4l2_pf, vp9_profiles, ARRAY_SIZE(vp9_profiles)); 9032c2dc2fdSStanimir Varbanov pl->level = find_hfi_id(v4l2_lvl, vp9_levels, ARRAY_SIZE(vp9_levels)); 9042c2dc2fdSStanimir Varbanov break; 9052c2dc2fdSStanimir Varbanov case HFI_VIDEO_CODEC_HEVC: 9062c2dc2fdSStanimir Varbanov pl->profile = find_hfi_id(v4l2_pf, hevc_profiles, ARRAY_SIZE(hevc_profiles)); 9072c2dc2fdSStanimir Varbanov pl->level = find_hfi_id(v4l2_lvl, hevc_levels, ARRAY_SIZE(hevc_levels)); 9082c2dc2fdSStanimir Varbanov break; 9092c2dc2fdSStanimir Varbanov default: 9102c2dc2fdSStanimir Varbanov break; 9112c2dc2fdSStanimir Varbanov } 9122c2dc2fdSStanimir Varbanov } 9132c2dc2fdSStanimir Varbanov 9142c2dc2fdSStanimir Varbanov int venus_helper_get_profile_level(struct venus_inst *inst, u32 *profile, u32 *level) 9152c2dc2fdSStanimir Varbanov { 9162c2dc2fdSStanimir Varbanov const u32 ptype = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT; 9172c2dc2fdSStanimir Varbanov union hfi_get_property hprop; 9182c2dc2fdSStanimir Varbanov int ret; 9192c2dc2fdSStanimir Varbanov 9202c2dc2fdSStanimir Varbanov ret = hfi_session_get_property(inst, ptype, &hprop); 9212c2dc2fdSStanimir Varbanov if (ret) 9222c2dc2fdSStanimir Varbanov return ret; 9232c2dc2fdSStanimir Varbanov 9242c2dc2fdSStanimir Varbanov v4l2_id_profile_level(inst->hfi_codec, &hprop.profile_level, profile, level); 9252c2dc2fdSStanimir Varbanov 9262c2dc2fdSStanimir Varbanov return 0; 9272c2dc2fdSStanimir Varbanov } 9282c2dc2fdSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_profile_level); 9292c2dc2fdSStanimir Varbanov 9302c2dc2fdSStanimir Varbanov int venus_helper_set_profile_level(struct venus_inst *inst, u32 profile, u32 level) 9312c2dc2fdSStanimir Varbanov { 9322c2dc2fdSStanimir Varbanov const u32 ptype = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT; 9332c2dc2fdSStanimir Varbanov struct hfi_profile_level pl; 9342c2dc2fdSStanimir Varbanov 9352c2dc2fdSStanimir Varbanov hfi_id_profile_level(inst->hfi_codec, profile, level, &pl); 9362c2dc2fdSStanimir Varbanov 9372c2dc2fdSStanimir Varbanov return hfi_session_set_property(inst, ptype, &pl); 9382c2dc2fdSStanimir Varbanov } 9392c2dc2fdSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_profile_level); 9402c2dc2fdSStanimir Varbanov 941e1cb72deSStanimir Varbanov static u32 get_framesize_raw_nv12(u32 width, u32 height) 942e1cb72deSStanimir Varbanov { 943e1cb72deSStanimir Varbanov u32 y_stride, uv_stride, y_plane; 944e1cb72deSStanimir Varbanov u32 y_sclines, uv_sclines, uv_plane; 945e1cb72deSStanimir Varbanov u32 size; 946e1cb72deSStanimir Varbanov 947e1cb72deSStanimir Varbanov y_stride = ALIGN(width, 128); 948e1cb72deSStanimir Varbanov uv_stride = ALIGN(width, 128); 949e1cb72deSStanimir Varbanov y_sclines = ALIGN(height, 32); 950e1cb72deSStanimir Varbanov uv_sclines = ALIGN(((height + 1) >> 1), 16); 951e1cb72deSStanimir Varbanov 952e1cb72deSStanimir Varbanov y_plane = y_stride * y_sclines; 953e1cb72deSStanimir Varbanov uv_plane = uv_stride * uv_sclines + SZ_4K; 954e1cb72deSStanimir Varbanov size = y_plane + uv_plane + SZ_8K; 955e1cb72deSStanimir Varbanov 956e1cb72deSStanimir Varbanov return ALIGN(size, SZ_4K); 957e1cb72deSStanimir Varbanov } 958e1cb72deSStanimir Varbanov 959e1cb72deSStanimir Varbanov static u32 get_framesize_raw_nv12_ubwc(u32 width, u32 height) 960e1cb72deSStanimir Varbanov { 961e1cb72deSStanimir Varbanov u32 y_meta_stride, y_meta_plane; 962e1cb72deSStanimir Varbanov u32 y_stride, y_plane; 963e1cb72deSStanimir Varbanov u32 uv_meta_stride, uv_meta_plane; 964e1cb72deSStanimir Varbanov u32 uv_stride, uv_plane; 965e1cb72deSStanimir Varbanov u32 extradata = SZ_16K; 966e1cb72deSStanimir Varbanov 967e1cb72deSStanimir Varbanov y_meta_stride = ALIGN(DIV_ROUND_UP(width, 32), 64); 968e1cb72deSStanimir Varbanov y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(height, 8), 16); 969e1cb72deSStanimir Varbanov y_meta_plane = ALIGN(y_meta_plane, SZ_4K); 970e1cb72deSStanimir Varbanov 971e1cb72deSStanimir Varbanov y_stride = ALIGN(width, 128); 972e1cb72deSStanimir Varbanov y_plane = ALIGN(y_stride * ALIGN(height, 32), SZ_4K); 973e1cb72deSStanimir Varbanov 974e1cb72deSStanimir Varbanov uv_meta_stride = ALIGN(DIV_ROUND_UP(width / 2, 16), 64); 975e1cb72deSStanimir Varbanov uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP(height / 2, 8), 16); 976e1cb72deSStanimir Varbanov uv_meta_plane = ALIGN(uv_meta_plane, SZ_4K); 977e1cb72deSStanimir Varbanov 978e1cb72deSStanimir Varbanov uv_stride = ALIGN(width, 128); 979e1cb72deSStanimir Varbanov uv_plane = ALIGN(uv_stride * ALIGN(height / 2, 32), SZ_4K); 980e1cb72deSStanimir Varbanov 981e1cb72deSStanimir Varbanov return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane + 982e1cb72deSStanimir Varbanov max(extradata, y_stride * 48), SZ_4K); 983e1cb72deSStanimir Varbanov } 984e1cb72deSStanimir Varbanov 985ab1eda44SAniket Masule static u32 get_framesize_raw_p010(u32 width, u32 height) 986ab1eda44SAniket Masule { 987ab1eda44SAniket Masule u32 y_plane, uv_plane, y_stride, uv_stride, y_sclines, uv_sclines; 988ab1eda44SAniket Masule 989ab1eda44SAniket Masule y_stride = ALIGN(width * 2, 256); 990ab1eda44SAniket Masule uv_stride = ALIGN(width * 2, 256); 991ab1eda44SAniket Masule y_sclines = ALIGN(height, 32); 992ab1eda44SAniket Masule uv_sclines = ALIGN((height + 1) >> 1, 16); 993ab1eda44SAniket Masule y_plane = y_stride * y_sclines; 994ab1eda44SAniket Masule uv_plane = uv_stride * uv_sclines; 995ab1eda44SAniket Masule 996ab1eda44SAniket Masule return ALIGN((y_plane + uv_plane), SZ_4K); 997ab1eda44SAniket Masule } 998ab1eda44SAniket Masule 999ab1eda44SAniket Masule static u32 get_framesize_raw_p010_ubwc(u32 width, u32 height) 1000ab1eda44SAniket Masule { 1001ab1eda44SAniket Masule u32 y_stride, uv_stride, y_sclines, uv_sclines; 1002ab1eda44SAniket Masule u32 y_ubwc_plane, uv_ubwc_plane; 1003ab1eda44SAniket Masule u32 y_meta_stride, y_meta_scanlines; 1004ab1eda44SAniket Masule u32 uv_meta_stride, uv_meta_scanlines; 1005ab1eda44SAniket Masule u32 y_meta_plane, uv_meta_plane; 1006ab1eda44SAniket Masule u32 size; 1007ab1eda44SAniket Masule 1008ab1eda44SAniket Masule y_stride = ALIGN(width * 2, 256); 1009ab1eda44SAniket Masule uv_stride = ALIGN(width * 2, 256); 1010ab1eda44SAniket Masule y_sclines = ALIGN(height, 16); 1011ab1eda44SAniket Masule uv_sclines = ALIGN((height + 1) >> 1, 16); 1012ab1eda44SAniket Masule 1013ab1eda44SAniket Masule y_ubwc_plane = ALIGN(y_stride * y_sclines, SZ_4K); 1014ab1eda44SAniket Masule uv_ubwc_plane = ALIGN(uv_stride * uv_sclines, SZ_4K); 1015ab1eda44SAniket Masule y_meta_stride = ALIGN(DIV_ROUND_UP(width, 32), 64); 1016ab1eda44SAniket Masule y_meta_scanlines = ALIGN(DIV_ROUND_UP(height, 4), 16); 1017ab1eda44SAniket Masule y_meta_plane = ALIGN(y_meta_stride * y_meta_scanlines, SZ_4K); 1018ab1eda44SAniket Masule uv_meta_stride = ALIGN(DIV_ROUND_UP((width + 1) >> 1, 16), 64); 1019ab1eda44SAniket Masule uv_meta_scanlines = ALIGN(DIV_ROUND_UP((height + 1) >> 1, 4), 16); 1020ab1eda44SAniket Masule uv_meta_plane = ALIGN(uv_meta_stride * uv_meta_scanlines, SZ_4K); 1021ab1eda44SAniket Masule 1022ab1eda44SAniket Masule size = y_ubwc_plane + uv_ubwc_plane + y_meta_plane + uv_meta_plane; 1023ab1eda44SAniket Masule 1024ab1eda44SAniket Masule return ALIGN(size, SZ_4K); 1025ab1eda44SAniket Masule } 1026ab1eda44SAniket Masule 1027ab1eda44SAniket Masule static u32 get_framesize_raw_yuv420_tp10_ubwc(u32 width, u32 height) 1028ab1eda44SAniket Masule { 1029ab1eda44SAniket Masule u32 y_stride, uv_stride, y_sclines, uv_sclines; 1030ab1eda44SAniket Masule u32 y_ubwc_plane, uv_ubwc_plane; 1031ab1eda44SAniket Masule u32 y_meta_stride, y_meta_scanlines; 1032ab1eda44SAniket Masule u32 uv_meta_stride, uv_meta_scanlines; 1033ab1eda44SAniket Masule u32 y_meta_plane, uv_meta_plane; 1034ab1eda44SAniket Masule u32 extradata = SZ_16K; 1035ab1eda44SAniket Masule u32 size; 1036ab1eda44SAniket Masule 1037ab1eda44SAniket Masule y_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256); 1038ab1eda44SAniket Masule uv_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256); 1039ab1eda44SAniket Masule y_sclines = ALIGN(height, 16); 1040ab1eda44SAniket Masule uv_sclines = ALIGN((height + 1) >> 1, 16); 1041ab1eda44SAniket Masule 1042ab1eda44SAniket Masule y_ubwc_plane = ALIGN(y_stride * y_sclines, SZ_4K); 1043ab1eda44SAniket Masule uv_ubwc_plane = ALIGN(uv_stride * uv_sclines, SZ_4K); 1044ab1eda44SAniket Masule y_meta_stride = ALIGN(DIV_ROUND_UP(width, 48), 64); 1045ab1eda44SAniket Masule y_meta_scanlines = ALIGN(DIV_ROUND_UP(height, 4), 16); 1046ab1eda44SAniket Masule y_meta_plane = ALIGN(y_meta_stride * y_meta_scanlines, SZ_4K); 1047ab1eda44SAniket Masule uv_meta_stride = ALIGN(DIV_ROUND_UP((width + 1) >> 1, 24), 64); 1048ab1eda44SAniket Masule uv_meta_scanlines = ALIGN(DIV_ROUND_UP((height + 1) >> 1, 4), 16); 1049ab1eda44SAniket Masule uv_meta_plane = ALIGN(uv_meta_stride * uv_meta_scanlines, SZ_4K); 1050ab1eda44SAniket Masule 1051ab1eda44SAniket Masule size = y_ubwc_plane + uv_ubwc_plane + y_meta_plane + uv_meta_plane; 1052ab1eda44SAniket Masule size += max(extradata + SZ_8K, y_stride * 48); 1053ab1eda44SAniket Masule 1054ab1eda44SAniket Masule return ALIGN(size, SZ_4K); 1055ab1eda44SAniket Masule } 1056ab1eda44SAniket Masule 1057e1cb72deSStanimir Varbanov u32 venus_helper_get_framesz_raw(u32 hfi_fmt, u32 width, u32 height) 1058e1cb72deSStanimir Varbanov { 1059e1cb72deSStanimir Varbanov switch (hfi_fmt) { 1060e1cb72deSStanimir Varbanov case HFI_COLOR_FORMAT_NV12: 1061e1cb72deSStanimir Varbanov case HFI_COLOR_FORMAT_NV21: 1062e1cb72deSStanimir Varbanov return get_framesize_raw_nv12(width, height); 1063e1cb72deSStanimir Varbanov case HFI_COLOR_FORMAT_NV12_UBWC: 1064e1cb72deSStanimir Varbanov return get_framesize_raw_nv12_ubwc(width, height); 1065ab1eda44SAniket Masule case HFI_COLOR_FORMAT_P010: 1066ab1eda44SAniket Masule return get_framesize_raw_p010(width, height); 1067ab1eda44SAniket Masule case HFI_COLOR_FORMAT_P010_UBWC: 1068ab1eda44SAniket Masule return get_framesize_raw_p010_ubwc(width, height); 1069ab1eda44SAniket Masule case HFI_COLOR_FORMAT_YUV420_TP10_UBWC: 1070ab1eda44SAniket Masule return get_framesize_raw_yuv420_tp10_ubwc(width, height); 1071e1cb72deSStanimir Varbanov default: 1072e1cb72deSStanimir Varbanov return 0; 1073e1cb72deSStanimir Varbanov } 1074e1cb72deSStanimir Varbanov } 1075e1cb72deSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_framesz_raw); 1076e1cb72deSStanimir Varbanov 1077e1cb72deSStanimir Varbanov u32 venus_helper_get_framesz(u32 v4l2_fmt, u32 width, u32 height) 1078e1cb72deSStanimir Varbanov { 1079e1cb72deSStanimir Varbanov u32 hfi_fmt, sz; 1080e1cb72deSStanimir Varbanov bool compressed; 1081e1cb72deSStanimir Varbanov 1082e1cb72deSStanimir Varbanov switch (v4l2_fmt) { 1083e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_MPEG: 1084e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_H264: 1085e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_H264_NO_SC: 1086e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_H264_MVC: 1087e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_H263: 1088e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_MPEG1: 1089e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_MPEG2: 1090e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_MPEG4: 1091e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_XVID: 1092e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_VC1_ANNEX_G: 1093e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_VC1_ANNEX_L: 1094e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_VP8: 1095e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_VP9: 1096e1cb72deSStanimir Varbanov case V4L2_PIX_FMT_HEVC: 1097e1cb72deSStanimir Varbanov compressed = true; 1098e1cb72deSStanimir Varbanov break; 1099e1cb72deSStanimir Varbanov default: 1100e1cb72deSStanimir Varbanov compressed = false; 1101e1cb72deSStanimir Varbanov break; 1102e1cb72deSStanimir Varbanov } 1103e1cb72deSStanimir Varbanov 1104e1cb72deSStanimir Varbanov if (compressed) { 1105e1cb72deSStanimir Varbanov sz = ALIGN(height, 32) * ALIGN(width, 32) * 3 / 2 / 2; 1106ddd1fc49SStanimir Varbanov if (width < 1280 || height < 720) 1107ddd1fc49SStanimir Varbanov sz *= 8; 1108e1cb72deSStanimir Varbanov return ALIGN(sz, SZ_4K); 1109e1cb72deSStanimir Varbanov } 1110e1cb72deSStanimir Varbanov 1111e1cb72deSStanimir Varbanov hfi_fmt = to_hfi_raw_fmt(v4l2_fmt); 1112e1cb72deSStanimir Varbanov if (!hfi_fmt) 1113e1cb72deSStanimir Varbanov return 0; 1114e1cb72deSStanimir Varbanov 1115e1cb72deSStanimir Varbanov return venus_helper_get_framesz_raw(hfi_fmt, width, height); 1116e1cb72deSStanimir Varbanov } 1117e1cb72deSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_framesz); 1118e1cb72deSStanimir Varbanov 1119af2c3834SStanimir Varbanov int venus_helper_set_input_resolution(struct venus_inst *inst, 1120af2c3834SStanimir Varbanov unsigned int width, unsigned int height) 1121af2c3834SStanimir Varbanov { 1122af2c3834SStanimir Varbanov u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE; 1123af2c3834SStanimir Varbanov struct hfi_framesize fs; 1124af2c3834SStanimir Varbanov 1125af2c3834SStanimir Varbanov fs.buffer_type = HFI_BUFFER_INPUT; 1126af2c3834SStanimir Varbanov fs.width = width; 1127af2c3834SStanimir Varbanov fs.height = height; 1128af2c3834SStanimir Varbanov 1129af2c3834SStanimir Varbanov return hfi_session_set_property(inst, ptype, &fs); 1130af2c3834SStanimir Varbanov } 1131af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_input_resolution); 1132af2c3834SStanimir Varbanov 1133af2c3834SStanimir Varbanov int venus_helper_set_output_resolution(struct venus_inst *inst, 1134404054e1SStanimir Varbanov unsigned int width, unsigned int height, 1135404054e1SStanimir Varbanov u32 buftype) 1136af2c3834SStanimir Varbanov { 1137af2c3834SStanimir Varbanov u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE; 1138af2c3834SStanimir Varbanov struct hfi_framesize fs; 1139af2c3834SStanimir Varbanov 1140404054e1SStanimir Varbanov fs.buffer_type = buftype; 1141af2c3834SStanimir Varbanov fs.width = width; 1142af2c3834SStanimir Varbanov fs.height = height; 1143af2c3834SStanimir Varbanov 1144af2c3834SStanimir Varbanov return hfi_session_set_property(inst, ptype, &fs); 1145af2c3834SStanimir Varbanov } 1146af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_output_resolution); 1147af2c3834SStanimir Varbanov 11481ad17595SDikshita Agarwal static u32 venus_helper_get_work_mode(struct venus_inst *inst) 11491ad17595SDikshita Agarwal { 11501ad17595SDikshita Agarwal u32 mode; 11511ad17595SDikshita Agarwal u32 num_mbs; 11521ad17595SDikshita Agarwal 11531ad17595SDikshita Agarwal mode = VIDC_WORK_MODE_2; 11541ad17595SDikshita Agarwal if (inst->session_type == VIDC_SESSION_TYPE_DEC) { 11551ad17595SDikshita Agarwal num_mbs = (ALIGN(inst->height, 16) * ALIGN(inst->width, 16)) / 256; 11561ad17595SDikshita Agarwal if (inst->hfi_codec == HFI_VIDEO_CODEC_MPEG2 || 11571ad17595SDikshita Agarwal inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE || 11581ad17595SDikshita Agarwal num_mbs <= NUM_MBS_720P) 11591ad17595SDikshita Agarwal mode = VIDC_WORK_MODE_1; 11601ad17595SDikshita Agarwal } else { 11611ad17595SDikshita Agarwal num_mbs = (ALIGN(inst->out_height, 16) * ALIGN(inst->out_width, 16)) / 256; 11621ad17595SDikshita Agarwal if (inst->hfi_codec == HFI_VIDEO_CODEC_VP8 && 11631ad17595SDikshita Agarwal num_mbs <= NUM_MBS_4K) 11641ad17595SDikshita Agarwal mode = VIDC_WORK_MODE_1; 11651ad17595SDikshita Agarwal } 11661ad17595SDikshita Agarwal 11671ad17595SDikshita Agarwal return mode; 11681ad17595SDikshita Agarwal } 11691ad17595SDikshita Agarwal 11701ad17595SDikshita Agarwal int venus_helper_set_work_mode(struct venus_inst *inst) 117101165b84SStanimir Varbanov { 117201165b84SStanimir Varbanov const u32 ptype = HFI_PROPERTY_PARAM_WORK_MODE; 117301165b84SStanimir Varbanov struct hfi_video_work_mode wm; 11741ad17595SDikshita Agarwal u32 mode; 117501165b84SStanimir Varbanov 11767ed9e0b3SBryan O'Donoghue if (!IS_V4(inst->core) && !IS_V6(inst->core)) 117701165b84SStanimir Varbanov return 0; 117801165b84SStanimir Varbanov 11791ad17595SDikshita Agarwal mode = venus_helper_get_work_mode(inst); 118001165b84SStanimir Varbanov wm.video_work_mode = mode; 118101165b84SStanimir Varbanov return hfi_session_set_property(inst, ptype, &wm); 118201165b84SStanimir Varbanov } 118301165b84SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_work_mode); 118401165b84SStanimir Varbanov 1185bc28936bSDikshita Agarwal int venus_helper_set_format_constraints(struct venus_inst *inst) 1186bc28936bSDikshita Agarwal { 1187bc28936bSDikshita Agarwal const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO; 1188bc28936bSDikshita Agarwal struct hfi_uncompressed_plane_actual_constraints_info pconstraint; 1189bc28936bSDikshita Agarwal 1190bc28936bSDikshita Agarwal if (!IS_V6(inst->core)) 1191bc28936bSDikshita Agarwal return 0; 1192bc28936bSDikshita Agarwal 11931ac61fafSMansur Alisha Shaik if (inst->opb_fmt == HFI_COLOR_FORMAT_NV12_UBWC) 11941ac61fafSMansur Alisha Shaik return 0; 11951ac61fafSMansur Alisha Shaik 1196bc28936bSDikshita Agarwal pconstraint.buffer_type = HFI_BUFFER_OUTPUT2; 1197bc28936bSDikshita Agarwal pconstraint.num_planes = 2; 1198bc28936bSDikshita Agarwal pconstraint.plane_format[0].stride_multiples = 128; 1199bc28936bSDikshita Agarwal pconstraint.plane_format[0].max_stride = 8192; 1200bc28936bSDikshita Agarwal pconstraint.plane_format[0].min_plane_buffer_height_multiple = 32; 1201bc28936bSDikshita Agarwal pconstraint.plane_format[0].buffer_alignment = 256; 1202bc28936bSDikshita Agarwal 1203bc28936bSDikshita Agarwal pconstraint.plane_format[1].stride_multiples = 128; 1204bc28936bSDikshita Agarwal pconstraint.plane_format[1].max_stride = 8192; 1205bc28936bSDikshita Agarwal pconstraint.plane_format[1].min_plane_buffer_height_multiple = 16; 1206bc28936bSDikshita Agarwal pconstraint.plane_format[1].buffer_alignment = 256; 1207bc28936bSDikshita Agarwal 1208bc28936bSDikshita Agarwal return hfi_session_set_property(inst, ptype, &pconstraint); 1209bc28936bSDikshita Agarwal } 1210bc28936bSDikshita Agarwal EXPORT_SYMBOL_GPL(venus_helper_set_format_constraints); 1211bc28936bSDikshita Agarwal 1212af2c3834SStanimir Varbanov int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, 12131eb04b2eSStanimir Varbanov unsigned int output_bufs, 12141eb04b2eSStanimir Varbanov unsigned int output2_bufs) 1215af2c3834SStanimir Varbanov { 1216af2c3834SStanimir Varbanov u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL; 1217af2c3834SStanimir Varbanov struct hfi_buffer_count_actual buf_count; 1218af2c3834SStanimir Varbanov int ret; 1219af2c3834SStanimir Varbanov 1220af2c3834SStanimir Varbanov buf_count.type = HFI_BUFFER_INPUT; 1221af2c3834SStanimir Varbanov buf_count.count_actual = input_bufs; 1222af2c3834SStanimir Varbanov 1223af2c3834SStanimir Varbanov ret = hfi_session_set_property(inst, ptype, &buf_count); 1224af2c3834SStanimir Varbanov if (ret) 1225af2c3834SStanimir Varbanov return ret; 1226af2c3834SStanimir Varbanov 1227af2c3834SStanimir Varbanov buf_count.type = HFI_BUFFER_OUTPUT; 1228af2c3834SStanimir Varbanov buf_count.count_actual = output_bufs; 1229af2c3834SStanimir Varbanov 12301eb04b2eSStanimir Varbanov ret = hfi_session_set_property(inst, ptype, &buf_count); 12311eb04b2eSStanimir Varbanov if (ret) 12321eb04b2eSStanimir Varbanov return ret; 12331eb04b2eSStanimir Varbanov 12341eb04b2eSStanimir Varbanov if (output2_bufs) { 12351eb04b2eSStanimir Varbanov buf_count.type = HFI_BUFFER_OUTPUT2; 12361eb04b2eSStanimir Varbanov buf_count.count_actual = output2_bufs; 12371eb04b2eSStanimir Varbanov 12381eb04b2eSStanimir Varbanov ret = hfi_session_set_property(inst, ptype, &buf_count); 12391eb04b2eSStanimir Varbanov } 12401eb04b2eSStanimir Varbanov 12411eb04b2eSStanimir Varbanov return ret; 1242af2c3834SStanimir Varbanov } 1243af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_num_bufs); 1244af2c3834SStanimir Varbanov 1245ab97a3fbSStanimir Varbanov int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format, 1246ab97a3fbSStanimir Varbanov u32 buftype) 1247ab97a3fbSStanimir Varbanov { 1248ab97a3fbSStanimir Varbanov const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT; 1249ab97a3fbSStanimir Varbanov struct hfi_uncompressed_format_select fmt; 1250ab97a3fbSStanimir Varbanov 1251ab97a3fbSStanimir Varbanov fmt.buffer_type = buftype; 1252ab97a3fbSStanimir Varbanov fmt.format = hfi_format; 1253ab97a3fbSStanimir Varbanov 1254ab97a3fbSStanimir Varbanov return hfi_session_set_property(inst, ptype, &fmt); 1255ab97a3fbSStanimir Varbanov } 1256ab97a3fbSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_raw_format); 1257ab97a3fbSStanimir Varbanov 1258af2c3834SStanimir Varbanov int venus_helper_set_color_format(struct venus_inst *inst, u32 pixfmt) 1259af2c3834SStanimir Varbanov { 1260ab97a3fbSStanimir Varbanov u32 hfi_format, buftype; 1261af2c3834SStanimir Varbanov 1262af2c3834SStanimir Varbanov if (inst->session_type == VIDC_SESSION_TYPE_DEC) 1263ab97a3fbSStanimir Varbanov buftype = HFI_BUFFER_OUTPUT; 1264af2c3834SStanimir Varbanov else if (inst->session_type == VIDC_SESSION_TYPE_ENC) 1265ab97a3fbSStanimir Varbanov buftype = HFI_BUFFER_INPUT; 1266af2c3834SStanimir Varbanov else 1267af2c3834SStanimir Varbanov return -EINVAL; 1268af2c3834SStanimir Varbanov 1269ab97a3fbSStanimir Varbanov hfi_format = to_hfi_raw_fmt(pixfmt); 1270ab97a3fbSStanimir Varbanov if (!hfi_format) 1271af2c3834SStanimir Varbanov return -EINVAL; 1272af2c3834SStanimir Varbanov 1273ab97a3fbSStanimir Varbanov return venus_helper_set_raw_format(inst, hfi_format, buftype); 1274af2c3834SStanimir Varbanov } 1275af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_color_format); 1276af2c3834SStanimir Varbanov 1277f012b23dSStanimir Varbanov int venus_helper_set_multistream(struct venus_inst *inst, bool out_en, 1278f012b23dSStanimir Varbanov bool out2_en) 1279f012b23dSStanimir Varbanov { 1280f012b23dSStanimir Varbanov struct hfi_multi_stream multi = {0}; 1281f012b23dSStanimir Varbanov u32 ptype = HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM; 1282f012b23dSStanimir Varbanov int ret; 1283f012b23dSStanimir Varbanov 1284f012b23dSStanimir Varbanov multi.buffer_type = HFI_BUFFER_OUTPUT; 1285f012b23dSStanimir Varbanov multi.enable = out_en; 1286f012b23dSStanimir Varbanov 1287f012b23dSStanimir Varbanov ret = hfi_session_set_property(inst, ptype, &multi); 1288f012b23dSStanimir Varbanov if (ret) 1289f012b23dSStanimir Varbanov return ret; 1290f012b23dSStanimir Varbanov 1291f012b23dSStanimir Varbanov multi.buffer_type = HFI_BUFFER_OUTPUT2; 1292f012b23dSStanimir Varbanov multi.enable = out2_en; 1293f012b23dSStanimir Varbanov 1294f012b23dSStanimir Varbanov return hfi_session_set_property(inst, ptype, &multi); 1295f012b23dSStanimir Varbanov } 1296f012b23dSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_multistream); 1297f012b23dSStanimir Varbanov 12982b0a8517SStanimir Varbanov int venus_helper_set_dyn_bufmode(struct venus_inst *inst) 12992b0a8517SStanimir Varbanov { 13002b0a8517SStanimir Varbanov const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE; 13012b0a8517SStanimir Varbanov struct hfi_buffer_alloc_mode mode; 13022b0a8517SStanimir Varbanov int ret; 13032b0a8517SStanimir Varbanov 13042b0a8517SStanimir Varbanov if (!is_dynamic_bufmode(inst)) 13052b0a8517SStanimir Varbanov return 0; 13062b0a8517SStanimir Varbanov 13072b0a8517SStanimir Varbanov mode.type = HFI_BUFFER_OUTPUT; 13082b0a8517SStanimir Varbanov mode.mode = HFI_BUFFER_MODE_DYNAMIC; 13092b0a8517SStanimir Varbanov 13102b0a8517SStanimir Varbanov ret = hfi_session_set_property(inst, ptype, &mode); 13112b0a8517SStanimir Varbanov if (ret) 13122b0a8517SStanimir Varbanov return ret; 13132b0a8517SStanimir Varbanov 13142b0a8517SStanimir Varbanov mode.type = HFI_BUFFER_OUTPUT2; 13152b0a8517SStanimir Varbanov 13162b0a8517SStanimir Varbanov return hfi_session_set_property(inst, ptype, &mode); 13172b0a8517SStanimir Varbanov } 13182b0a8517SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_dyn_bufmode); 13192b0a8517SStanimir Varbanov 1320d4a5b0a6SStanimir Varbanov int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype) 1321d4a5b0a6SStanimir Varbanov { 1322d4a5b0a6SStanimir Varbanov const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL; 1323d4a5b0a6SStanimir Varbanov struct hfi_buffer_size_actual bufsz; 1324d4a5b0a6SStanimir Varbanov 1325d4a5b0a6SStanimir Varbanov bufsz.type = buftype; 1326d4a5b0a6SStanimir Varbanov bufsz.size = bufsize; 1327d4a5b0a6SStanimir Varbanov 1328d4a5b0a6SStanimir Varbanov return hfi_session_set_property(inst, ptype, &bufsz); 1329d4a5b0a6SStanimir Varbanov } 1330d4a5b0a6SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_set_bufsize); 1331d4a5b0a6SStanimir Varbanov 1332130c0117SStanimir Varbanov unsigned int venus_helper_get_opb_size(struct venus_inst *inst) 1333130c0117SStanimir Varbanov { 1334130c0117SStanimir Varbanov /* the encoder has only one output */ 1335130c0117SStanimir Varbanov if (inst->session_type == VIDC_SESSION_TYPE_ENC) 1336130c0117SStanimir Varbanov return inst->output_buf_size; 1337130c0117SStanimir Varbanov 1338130c0117SStanimir Varbanov if (inst->opb_buftype == HFI_BUFFER_OUTPUT) 1339130c0117SStanimir Varbanov return inst->output_buf_size; 1340130c0117SStanimir Varbanov else if (inst->opb_buftype == HFI_BUFFER_OUTPUT2) 1341130c0117SStanimir Varbanov return inst->output2_buf_size; 1342130c0117SStanimir Varbanov 1343130c0117SStanimir Varbanov return 0; 1344130c0117SStanimir Varbanov } 1345130c0117SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_opb_size); 1346130c0117SStanimir Varbanov 1347af2c3834SStanimir Varbanov static void delayed_process_buf_func(struct work_struct *work) 1348af2c3834SStanimir Varbanov { 1349af2c3834SStanimir Varbanov struct venus_buffer *buf, *n; 1350af2c3834SStanimir Varbanov struct venus_inst *inst; 1351af2c3834SStanimir Varbanov int ret; 1352af2c3834SStanimir Varbanov 1353af2c3834SStanimir Varbanov inst = container_of(work, struct venus_inst, delayed_process_work); 1354af2c3834SStanimir Varbanov 1355af2c3834SStanimir Varbanov mutex_lock(&inst->lock); 1356af2c3834SStanimir Varbanov 1357af2c3834SStanimir Varbanov if (!(inst->streamon_out & inst->streamon_cap)) 1358af2c3834SStanimir Varbanov goto unlock; 1359af2c3834SStanimir Varbanov 1360af2c3834SStanimir Varbanov list_for_each_entry_safe(buf, n, &inst->delayed_process, ref_list) { 1361af2c3834SStanimir Varbanov if (buf->flags & HFI_BUFFERFLAG_READONLY) 1362af2c3834SStanimir Varbanov continue; 1363af2c3834SStanimir Varbanov 1364af2c3834SStanimir Varbanov ret = session_process_buf(inst, &buf->vb); 1365af2c3834SStanimir Varbanov if (ret) 1366af2c3834SStanimir Varbanov return_buf_error(inst, &buf->vb); 1367af2c3834SStanimir Varbanov 1368af2c3834SStanimir Varbanov list_del_init(&buf->ref_list); 1369af2c3834SStanimir Varbanov } 1370af2c3834SStanimir Varbanov unlock: 1371af2c3834SStanimir Varbanov mutex_unlock(&inst->lock); 1372af2c3834SStanimir Varbanov } 1373af2c3834SStanimir Varbanov 1374af2c3834SStanimir Varbanov void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx) 1375af2c3834SStanimir Varbanov { 1376af2c3834SStanimir Varbanov struct venus_buffer *buf; 1377af2c3834SStanimir Varbanov 1378af2c3834SStanimir Varbanov list_for_each_entry(buf, &inst->registeredbufs, reg_list) { 1379af2c3834SStanimir Varbanov if (buf->vb.vb2_buf.index == idx) { 1380af2c3834SStanimir Varbanov buf->flags &= ~HFI_BUFFERFLAG_READONLY; 1381af2c3834SStanimir Varbanov schedule_work(&inst->delayed_process_work); 1382af2c3834SStanimir Varbanov break; 1383af2c3834SStanimir Varbanov } 1384af2c3834SStanimir Varbanov } 1385af2c3834SStanimir Varbanov } 1386af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_release_buf_ref); 1387af2c3834SStanimir Varbanov 1388af2c3834SStanimir Varbanov void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf) 1389af2c3834SStanimir Varbanov { 1390af2c3834SStanimir Varbanov struct venus_buffer *buf = to_venus_buffer(vbuf); 1391af2c3834SStanimir Varbanov 1392af2c3834SStanimir Varbanov buf->flags |= HFI_BUFFERFLAG_READONLY; 1393af2c3834SStanimir Varbanov } 1394af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_acquire_buf_ref); 1395af2c3834SStanimir Varbanov 1396af2c3834SStanimir Varbanov static int is_buf_refed(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) 1397af2c3834SStanimir Varbanov { 1398af2c3834SStanimir Varbanov struct venus_buffer *buf = to_venus_buffer(vbuf); 1399af2c3834SStanimir Varbanov 1400af2c3834SStanimir Varbanov if (buf->flags & HFI_BUFFERFLAG_READONLY) { 1401af2c3834SStanimir Varbanov list_add_tail(&buf->ref_list, &inst->delayed_process); 1402af2c3834SStanimir Varbanov schedule_work(&inst->delayed_process_work); 1403af2c3834SStanimir Varbanov return 1; 1404af2c3834SStanimir Varbanov } 1405af2c3834SStanimir Varbanov 1406af2c3834SStanimir Varbanov return 0; 1407af2c3834SStanimir Varbanov } 1408af2c3834SStanimir Varbanov 1409af2c3834SStanimir Varbanov struct vb2_v4l2_buffer * 1410af2c3834SStanimir Varbanov venus_helper_find_buf(struct venus_inst *inst, unsigned int type, u32 idx) 1411af2c3834SStanimir Varbanov { 1412af2c3834SStanimir Varbanov struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 1413af2c3834SStanimir Varbanov 1414af2c3834SStanimir Varbanov if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 1415af2c3834SStanimir Varbanov return v4l2_m2m_src_buf_remove_by_idx(m2m_ctx, idx); 1416af2c3834SStanimir Varbanov else 1417af2c3834SStanimir Varbanov return v4l2_m2m_dst_buf_remove_by_idx(m2m_ctx, idx); 1418af2c3834SStanimir Varbanov } 1419af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_find_buf); 1420af2c3834SStanimir Varbanov 142140d87aafSMansur Alisha Shaik void venus_helper_change_dpb_owner(struct venus_inst *inst, 142240d87aafSMansur Alisha Shaik struct vb2_v4l2_buffer *vbuf, unsigned int type, 142340d87aafSMansur Alisha Shaik unsigned int buf_type, u32 tag) 142440d87aafSMansur Alisha Shaik { 142540d87aafSMansur Alisha Shaik struct intbuf *dpb_buf; 142640d87aafSMansur Alisha Shaik 142740d87aafSMansur Alisha Shaik if (!V4L2_TYPE_IS_CAPTURE(type) || 142840d87aafSMansur Alisha Shaik buf_type != inst->dpb_buftype) 142940d87aafSMansur Alisha Shaik return; 143040d87aafSMansur Alisha Shaik 143140d87aafSMansur Alisha Shaik list_for_each_entry(dpb_buf, &inst->dpbbufs, list) 143240d87aafSMansur Alisha Shaik if (dpb_buf->dpb_out_tag == tag) { 143340d87aafSMansur Alisha Shaik dpb_buf->owned_by = DRIVER; 143440d87aafSMansur Alisha Shaik break; 143540d87aafSMansur Alisha Shaik } 143640d87aafSMansur Alisha Shaik } 143740d87aafSMansur Alisha Shaik EXPORT_SYMBOL_GPL(venus_helper_change_dpb_owner); 143840d87aafSMansur Alisha Shaik 1439af2c3834SStanimir Varbanov int venus_helper_vb2_buf_init(struct vb2_buffer *vb) 1440af2c3834SStanimir Varbanov { 1441af2c3834SStanimir Varbanov struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 1442af2c3834SStanimir Varbanov struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 1443af2c3834SStanimir Varbanov struct venus_buffer *buf = to_venus_buffer(vbuf); 1444af2c3834SStanimir Varbanov 1445af2c3834SStanimir Varbanov buf->size = vb2_plane_size(vb, 0); 1446cc82fd69SAlexandre Courbot buf->dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); 1447af2c3834SStanimir Varbanov 1448af2c3834SStanimir Varbanov if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 1449af2c3834SStanimir Varbanov list_add_tail(&buf->reg_list, &inst->registeredbufs); 1450af2c3834SStanimir Varbanov 1451af2c3834SStanimir Varbanov return 0; 1452af2c3834SStanimir Varbanov } 1453af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_init); 1454af2c3834SStanimir Varbanov 1455af2c3834SStanimir Varbanov int venus_helper_vb2_buf_prepare(struct vb2_buffer *vb) 1456af2c3834SStanimir Varbanov { 1457af2c3834SStanimir Varbanov struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 1458f012b23dSStanimir Varbanov unsigned int out_buf_size = venus_helper_get_opb_size(inst); 145905979046SStanimir Varbanov struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 146005979046SStanimir Varbanov 146105979046SStanimir Varbanov if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { 146205979046SStanimir Varbanov if (vbuf->field == V4L2_FIELD_ANY) 146305979046SStanimir Varbanov vbuf->field = V4L2_FIELD_NONE; 146405979046SStanimir Varbanov if (vbuf->field != V4L2_FIELD_NONE) { 146505979046SStanimir Varbanov dev_err(inst->core->dev, "%s field isn't supported\n", 146605979046SStanimir Varbanov __func__); 146705979046SStanimir Varbanov return -EINVAL; 146805979046SStanimir Varbanov } 146905979046SStanimir Varbanov } 1470af2c3834SStanimir Varbanov 1471af2c3834SStanimir Varbanov if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 1472f012b23dSStanimir Varbanov vb2_plane_size(vb, 0) < out_buf_size) 1473af2c3834SStanimir Varbanov return -EINVAL; 1474af2c3834SStanimir Varbanov if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && 1475af2c3834SStanimir Varbanov vb2_plane_size(vb, 0) < inst->input_buf_size) 1476af2c3834SStanimir Varbanov return -EINVAL; 1477af2c3834SStanimir Varbanov 1478af2c3834SStanimir Varbanov return 0; 1479af2c3834SStanimir Varbanov } 1480af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_prepare); 1481af2c3834SStanimir Varbanov 1482fd1ee315SStanimir Varbanov static void cache_payload(struct venus_inst *inst, struct vb2_buffer *vb) 1483fd1ee315SStanimir Varbanov { 1484fd1ee315SStanimir Varbanov struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 1485fd1ee315SStanimir Varbanov unsigned int idx = vbuf->vb2_buf.index; 1486fd1ee315SStanimir Varbanov 1487fd1ee315SStanimir Varbanov if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 1488fd1ee315SStanimir Varbanov inst->payloads[idx] = vb2_get_plane_payload(vb, 0); 1489fd1ee315SStanimir Varbanov } 1490fd1ee315SStanimir Varbanov 1491af2c3834SStanimir Varbanov void venus_helper_vb2_buf_queue(struct vb2_buffer *vb) 1492af2c3834SStanimir Varbanov { 1493af2c3834SStanimir Varbanov struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 1494af2c3834SStanimir Varbanov struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 1495af2c3834SStanimir Varbanov struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 1496af2c3834SStanimir Varbanov int ret; 1497af2c3834SStanimir Varbanov 1498af2c3834SStanimir Varbanov v4l2_m2m_buf_queue(m2m_ctx, vbuf); 1499af2c3834SStanimir Varbanov 1500acf8a57dSStanimir Varbanov /* Skip processing queued capture buffers after LAST flag */ 1501acf8a57dSStanimir Varbanov if (inst->session_type == VIDC_SESSION_TYPE_DEC && 1502acf8a57dSStanimir Varbanov V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) && 1503acf8a57dSStanimir Varbanov inst->codec_state == VENUS_DEC_STATE_DRC) 150421560ddfSStanimir Varbanov return; 1505acf8a57dSStanimir Varbanov 1506fd1ee315SStanimir Varbanov cache_payload(inst, vb); 1507fd1ee315SStanimir Varbanov 1508beac8290SStanimir Varbanov if (inst->session_type == VIDC_SESSION_TYPE_ENC && 1509beac8290SStanimir Varbanov !(inst->streamon_out && inst->streamon_cap)) 151021560ddfSStanimir Varbanov return; 1511af2c3834SStanimir Varbanov 1512beac8290SStanimir Varbanov if (vb2_start_streaming_called(vb->vb2_queue)) { 1513af2c3834SStanimir Varbanov ret = is_buf_refed(inst, vbuf); 1514af2c3834SStanimir Varbanov if (ret) 151521560ddfSStanimir Varbanov return; 1516af2c3834SStanimir Varbanov 1517af2c3834SStanimir Varbanov ret = session_process_buf(inst, vbuf); 1518af2c3834SStanimir Varbanov if (ret) 1519af2c3834SStanimir Varbanov return_buf_error(inst, vbuf); 1520beac8290SStanimir Varbanov } 1521af2c3834SStanimir Varbanov } 1522af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_queue); 1523af2c3834SStanimir Varbanov 15240febf923SStanimir Varbanov void venus_helper_buffers_done(struct venus_inst *inst, unsigned int type, 1525af2c3834SStanimir Varbanov enum vb2_buffer_state state) 1526af2c3834SStanimir Varbanov { 1527af2c3834SStanimir Varbanov struct vb2_v4l2_buffer *buf; 1528af2c3834SStanimir Varbanov 15290febf923SStanimir Varbanov if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 1530af2c3834SStanimir Varbanov while ((buf = v4l2_m2m_src_buf_remove(inst->m2m_ctx))) 1531af2c3834SStanimir Varbanov v4l2_m2m_buf_done(buf, state); 15320febf923SStanimir Varbanov } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 1533af2c3834SStanimir Varbanov while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx))) 1534af2c3834SStanimir Varbanov v4l2_m2m_buf_done(buf, state); 1535af2c3834SStanimir Varbanov } 15360febf923SStanimir Varbanov } 1537af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_buffers_done); 1538af2c3834SStanimir Varbanov 1539af2c3834SStanimir Varbanov void venus_helper_vb2_stop_streaming(struct vb2_queue *q) 1540af2c3834SStanimir Varbanov { 1541af2c3834SStanimir Varbanov struct venus_inst *inst = vb2_get_drv_priv(q); 1542af2c3834SStanimir Varbanov struct venus_core *core = inst->core; 1543af2c3834SStanimir Varbanov int ret; 1544af2c3834SStanimir Varbanov 1545af2c3834SStanimir Varbanov mutex_lock(&inst->lock); 1546af2c3834SStanimir Varbanov 1547af2c3834SStanimir Varbanov if (inst->streamon_out & inst->streamon_cap) { 1548af2c3834SStanimir Varbanov ret = hfi_session_stop(inst); 1549af2c3834SStanimir Varbanov ret |= hfi_session_unload_res(inst); 15501e485ee5SStanimir Varbanov ret |= venus_helper_unregister_bufs(inst); 15511e485ee5SStanimir Varbanov ret |= venus_helper_intbufs_free(inst); 1552af2c3834SStanimir Varbanov ret |= hfi_session_deinit(inst); 1553af2c3834SStanimir Varbanov 1554b46ff4ebSStanimir Varbanov if (inst->session_error || test_bit(0, &core->sys_error)) 1555af2c3834SStanimir Varbanov ret = -EIO; 1556af2c3834SStanimir Varbanov 1557af2c3834SStanimir Varbanov if (ret) 1558af2c3834SStanimir Varbanov hfi_session_abort(inst); 1559af2c3834SStanimir Varbanov 1560f012b23dSStanimir Varbanov venus_helper_free_dpb_bufs(inst); 1561f012b23dSStanimir Varbanov 15627482a983SStanimir Varbanov venus_pm_load_scale(inst); 1563bbd770aeSStanimir Varbanov INIT_LIST_HEAD(&inst->registeredbufs); 1564af2c3834SStanimir Varbanov } 1565af2c3834SStanimir Varbanov 15660febf923SStanimir Varbanov venus_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 15670febf923SStanimir Varbanov VB2_BUF_STATE_ERROR); 15680febf923SStanimir Varbanov venus_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 15690febf923SStanimir Varbanov VB2_BUF_STATE_ERROR); 1570af2c3834SStanimir Varbanov 1571af2c3834SStanimir Varbanov if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 1572af2c3834SStanimir Varbanov inst->streamon_out = 0; 1573af2c3834SStanimir Varbanov else 1574af2c3834SStanimir Varbanov inst->streamon_cap = 0; 1575af2c3834SStanimir Varbanov 15764ebf9693SAniket Masule venus_pm_release_core(inst); 15774ebf9693SAniket Masule 15783227a8f7SStanimir Varbanov inst->session_error = 0; 15793227a8f7SStanimir Varbanov 1580af2c3834SStanimir Varbanov mutex_unlock(&inst->lock); 1581af2c3834SStanimir Varbanov } 1582af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_vb2_stop_streaming); 1583af2c3834SStanimir Varbanov 1584aa6dcf17SStanimir Varbanov void venus_helper_vb2_queue_error(struct venus_inst *inst) 1585aa6dcf17SStanimir Varbanov { 1586aa6dcf17SStanimir Varbanov struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 1587aa6dcf17SStanimir Varbanov struct vb2_queue *q; 1588aa6dcf17SStanimir Varbanov 1589aa6dcf17SStanimir Varbanov q = v4l2_m2m_get_src_vq(m2m_ctx); 1590aa6dcf17SStanimir Varbanov vb2_queue_error(q); 1591aa6dcf17SStanimir Varbanov q = v4l2_m2m_get_dst_vq(m2m_ctx); 1592aa6dcf17SStanimir Varbanov vb2_queue_error(q); 1593aa6dcf17SStanimir Varbanov } 1594aa6dcf17SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_vb2_queue_error); 1595aa6dcf17SStanimir Varbanov 159614ea00d6SStanimir Varbanov int venus_helper_process_initial_cap_bufs(struct venus_inst *inst) 159714ea00d6SStanimir Varbanov { 159814ea00d6SStanimir Varbanov struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 159914ea00d6SStanimir Varbanov struct v4l2_m2m_buffer *buf, *n; 160014ea00d6SStanimir Varbanov int ret; 160114ea00d6SStanimir Varbanov 160214ea00d6SStanimir Varbanov v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) { 160314ea00d6SStanimir Varbanov ret = session_process_buf(inst, &buf->vb); 160414ea00d6SStanimir Varbanov if (ret) { 160514ea00d6SStanimir Varbanov return_buf_error(inst, &buf->vb); 160614ea00d6SStanimir Varbanov return ret; 160714ea00d6SStanimir Varbanov } 160814ea00d6SStanimir Varbanov } 160914ea00d6SStanimir Varbanov 161014ea00d6SStanimir Varbanov return 0; 161114ea00d6SStanimir Varbanov } 161214ea00d6SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_process_initial_cap_bufs); 161314ea00d6SStanimir Varbanov 161414ea00d6SStanimir Varbanov int venus_helper_process_initial_out_bufs(struct venus_inst *inst) 161514ea00d6SStanimir Varbanov { 161614ea00d6SStanimir Varbanov struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 161714ea00d6SStanimir Varbanov struct v4l2_m2m_buffer *buf, *n; 161814ea00d6SStanimir Varbanov int ret; 161914ea00d6SStanimir Varbanov 162014ea00d6SStanimir Varbanov v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) { 162114ea00d6SStanimir Varbanov ret = session_process_buf(inst, &buf->vb); 162214ea00d6SStanimir Varbanov if (ret) { 162314ea00d6SStanimir Varbanov return_buf_error(inst, &buf->vb); 162414ea00d6SStanimir Varbanov return ret; 162514ea00d6SStanimir Varbanov } 162614ea00d6SStanimir Varbanov } 162714ea00d6SStanimir Varbanov 162814ea00d6SStanimir Varbanov return 0; 162914ea00d6SStanimir Varbanov } 163014ea00d6SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_process_initial_out_bufs); 163114ea00d6SStanimir Varbanov 1632af2c3834SStanimir Varbanov int venus_helper_vb2_start_streaming(struct venus_inst *inst) 1633af2c3834SStanimir Varbanov { 1634af2c3834SStanimir Varbanov int ret; 1635af2c3834SStanimir Varbanov 16361e485ee5SStanimir Varbanov ret = venus_helper_intbufs_alloc(inst); 1637af2c3834SStanimir Varbanov if (ret) 1638af2c3834SStanimir Varbanov return ret; 1639af2c3834SStanimir Varbanov 1640af2c3834SStanimir Varbanov ret = session_register_bufs(inst); 1641af2c3834SStanimir Varbanov if (ret) 1642af2c3834SStanimir Varbanov goto err_bufs_free; 1643af2c3834SStanimir Varbanov 16447482a983SStanimir Varbanov venus_pm_load_scale(inst); 1645af2c3834SStanimir Varbanov 1646af2c3834SStanimir Varbanov ret = hfi_session_load_res(inst); 1647af2c3834SStanimir Varbanov if (ret) 1648af2c3834SStanimir Varbanov goto err_unreg_bufs; 1649af2c3834SStanimir Varbanov 1650af2c3834SStanimir Varbanov ret = hfi_session_start(inst); 1651af2c3834SStanimir Varbanov if (ret) 1652af2c3834SStanimir Varbanov goto err_unload_res; 1653af2c3834SStanimir Varbanov 1654af2c3834SStanimir Varbanov return 0; 1655af2c3834SStanimir Varbanov 1656af2c3834SStanimir Varbanov err_unload_res: 1657af2c3834SStanimir Varbanov hfi_session_unload_res(inst); 1658af2c3834SStanimir Varbanov err_unreg_bufs: 16591e485ee5SStanimir Varbanov venus_helper_unregister_bufs(inst); 1660af2c3834SStanimir Varbanov err_bufs_free: 16611e485ee5SStanimir Varbanov venus_helper_intbufs_free(inst); 1662af2c3834SStanimir Varbanov return ret; 1663af2c3834SStanimir Varbanov } 1664af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_vb2_start_streaming); 1665af2c3834SStanimir Varbanov 1666af2c3834SStanimir Varbanov void venus_helper_m2m_device_run(void *priv) 1667af2c3834SStanimir Varbanov { 1668af2c3834SStanimir Varbanov struct venus_inst *inst = priv; 1669af2c3834SStanimir Varbanov struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 1670af2c3834SStanimir Varbanov struct v4l2_m2m_buffer *buf, *n; 1671af2c3834SStanimir Varbanov int ret; 1672af2c3834SStanimir Varbanov 1673af2c3834SStanimir Varbanov mutex_lock(&inst->lock); 1674af2c3834SStanimir Varbanov 1675af2c3834SStanimir Varbanov v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) { 1676af2c3834SStanimir Varbanov ret = session_process_buf(inst, &buf->vb); 1677af2c3834SStanimir Varbanov if (ret) 1678af2c3834SStanimir Varbanov return_buf_error(inst, &buf->vb); 1679af2c3834SStanimir Varbanov } 1680af2c3834SStanimir Varbanov 1681af2c3834SStanimir Varbanov v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) { 1682af2c3834SStanimir Varbanov ret = session_process_buf(inst, &buf->vb); 1683af2c3834SStanimir Varbanov if (ret) 1684af2c3834SStanimir Varbanov return_buf_error(inst, &buf->vb); 1685af2c3834SStanimir Varbanov } 1686af2c3834SStanimir Varbanov 1687af2c3834SStanimir Varbanov mutex_unlock(&inst->lock); 1688af2c3834SStanimir Varbanov } 1689af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_m2m_device_run); 1690af2c3834SStanimir Varbanov 1691af2c3834SStanimir Varbanov void venus_helper_m2m_job_abort(void *priv) 1692af2c3834SStanimir Varbanov { 1693af2c3834SStanimir Varbanov struct venus_inst *inst = priv; 1694af2c3834SStanimir Varbanov 1695af2c3834SStanimir Varbanov v4l2_m2m_job_finish(inst->m2m_dev, inst->m2m_ctx); 1696af2c3834SStanimir Varbanov } 1697af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_m2m_job_abort); 1698af2c3834SStanimir Varbanov 1699aa603389SStanimir Varbanov int venus_helper_session_init(struct venus_inst *inst) 1700aa603389SStanimir Varbanov { 1701aa603389SStanimir Varbanov enum hfi_version version = inst->core->res->hfi_version; 1702aa603389SStanimir Varbanov u32 session_type = inst->session_type; 1703aa603389SStanimir Varbanov u32 codec; 1704aa603389SStanimir Varbanov int ret; 1705aa603389SStanimir Varbanov 1706aa603389SStanimir Varbanov codec = inst->session_type == VIDC_SESSION_TYPE_DEC ? 1707aa603389SStanimir Varbanov inst->fmt_out->pixfmt : inst->fmt_cap->pixfmt; 1708aa603389SStanimir Varbanov 1709aa603389SStanimir Varbanov ret = hfi_session_init(inst, codec); 1710aa603389SStanimir Varbanov if (ret) 1711aa603389SStanimir Varbanov return ret; 1712aa603389SStanimir Varbanov 1713aa603389SStanimir Varbanov inst->clk_data.vpp_freq = hfi_platform_get_codec_vpp_freq(version, codec, 1714aa603389SStanimir Varbanov session_type); 1715aa603389SStanimir Varbanov inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(version, codec, 1716aa603389SStanimir Varbanov session_type); 17173cfe5815SDikshita Agarwal inst->clk_data.low_power_freq = hfi_platform_get_codec_lp_freq(version, codec, 17183cfe5815SDikshita Agarwal session_type); 1719aa603389SStanimir Varbanov 1720aa603389SStanimir Varbanov return 0; 1721aa603389SStanimir Varbanov } 1722aa603389SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_session_init); 1723aa603389SStanimir Varbanov 1724af2c3834SStanimir Varbanov void venus_helper_init_instance(struct venus_inst *inst) 1725af2c3834SStanimir Varbanov { 1726af2c3834SStanimir Varbanov if (inst->session_type == VIDC_SESSION_TYPE_DEC) { 1727af2c3834SStanimir Varbanov INIT_LIST_HEAD(&inst->delayed_process); 1728af2c3834SStanimir Varbanov INIT_WORK(&inst->delayed_process_work, 1729af2c3834SStanimir Varbanov delayed_process_buf_func); 1730af2c3834SStanimir Varbanov } 1731af2c3834SStanimir Varbanov } 1732af2c3834SStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_init_instance); 1733aa3a8414SStanimir Varbanov 17348f3b41dcSStanimir Varbanov static bool find_fmt_from_caps(struct hfi_plat_caps *caps, u32 buftype, u32 fmt) 1735f012b23dSStanimir Varbanov { 1736f012b23dSStanimir Varbanov unsigned int i; 1737f012b23dSStanimir Varbanov 1738f012b23dSStanimir Varbanov for (i = 0; i < caps->num_fmts; i++) { 1739f012b23dSStanimir Varbanov if (caps->fmts[i].buftype == buftype && 1740f012b23dSStanimir Varbanov caps->fmts[i].fmt == fmt) 1741f012b23dSStanimir Varbanov return true; 1742f012b23dSStanimir Varbanov } 1743f012b23dSStanimir Varbanov 1744f012b23dSStanimir Varbanov return false; 1745f012b23dSStanimir Varbanov } 1746f012b23dSStanimir Varbanov 1747f012b23dSStanimir Varbanov int venus_helper_get_out_fmts(struct venus_inst *inst, u32 v4l2_fmt, 1748f012b23dSStanimir Varbanov u32 *out_fmt, u32 *out2_fmt, bool ubwc) 1749f012b23dSStanimir Varbanov { 1750f012b23dSStanimir Varbanov struct venus_core *core = inst->core; 17518f3b41dcSStanimir Varbanov struct hfi_plat_caps *caps; 1752f012b23dSStanimir Varbanov u32 ubwc_fmt, fmt = to_hfi_raw_fmt(v4l2_fmt); 1753f012b23dSStanimir Varbanov bool found, found_ubwc; 1754f012b23dSStanimir Varbanov 1755f012b23dSStanimir Varbanov *out_fmt = *out2_fmt = 0; 1756f012b23dSStanimir Varbanov 1757f012b23dSStanimir Varbanov if (!fmt) 1758f012b23dSStanimir Varbanov return -EINVAL; 1759f012b23dSStanimir Varbanov 1760f012b23dSStanimir Varbanov caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type); 1761f012b23dSStanimir Varbanov if (!caps) 1762f012b23dSStanimir Varbanov return -EINVAL; 1763f012b23dSStanimir Varbanov 1764ab1eda44SAniket Masule if (inst->bit_depth == VIDC_BITDEPTH_10 && 1765ab1eda44SAniket Masule inst->session_type == VIDC_SESSION_TYPE_DEC) { 1766ab1eda44SAniket Masule found_ubwc = 1767ab1eda44SAniket Masule find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, 1768ab1eda44SAniket Masule HFI_COLOR_FORMAT_YUV420_TP10_UBWC); 1769ab1eda44SAniket Masule found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, 1770ab1eda44SAniket Masule HFI_COLOR_FORMAT_NV12); 1771ab1eda44SAniket Masule if (found_ubwc && found) { 1772ab1eda44SAniket Masule /* 1773ab1eda44SAniket Masule * Hard-code DPB buffers to be 10bit UBWC and decoder 1774ab1eda44SAniket Masule * output buffers in 8bit NV12 until V4L2 is able to 1775ab1eda44SAniket Masule * expose compressed/tiled formats to applications. 1776ab1eda44SAniket Masule */ 1777ab1eda44SAniket Masule *out_fmt = HFI_COLOR_FORMAT_YUV420_TP10_UBWC; 1778ab1eda44SAniket Masule *out2_fmt = HFI_COLOR_FORMAT_NV12; 1779ab1eda44SAniket Masule return 0; 1780ab1eda44SAniket Masule } 1781ab1eda44SAniket Masule 1782ab1eda44SAniket Masule return -EINVAL; 1783ab1eda44SAniket Masule } 1784ab1eda44SAniket Masule 1785f012b23dSStanimir Varbanov if (ubwc) { 1786f012b23dSStanimir Varbanov ubwc_fmt = fmt | HFI_COLOR_FORMAT_UBWC_BASE; 1787f012b23dSStanimir Varbanov found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, 1788f012b23dSStanimir Varbanov ubwc_fmt); 1789f012b23dSStanimir Varbanov found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt); 1790f012b23dSStanimir Varbanov 1791f012b23dSStanimir Varbanov if (found_ubwc && found) { 1792f012b23dSStanimir Varbanov *out_fmt = ubwc_fmt; 1793f012b23dSStanimir Varbanov *out2_fmt = fmt; 1794f012b23dSStanimir Varbanov return 0; 1795f012b23dSStanimir Varbanov } 1796f012b23dSStanimir Varbanov } 1797f012b23dSStanimir Varbanov 1798f012b23dSStanimir Varbanov found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, fmt); 1799f012b23dSStanimir Varbanov if (found) { 1800f012b23dSStanimir Varbanov *out_fmt = fmt; 1801f012b23dSStanimir Varbanov *out2_fmt = 0; 1802f012b23dSStanimir Varbanov return 0; 1803f012b23dSStanimir Varbanov } 1804f012b23dSStanimir Varbanov 1805f012b23dSStanimir Varbanov found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt); 1806f012b23dSStanimir Varbanov if (found) { 1807f012b23dSStanimir Varbanov *out_fmt = 0; 1808f012b23dSStanimir Varbanov *out2_fmt = fmt; 1809f012b23dSStanimir Varbanov return 0; 1810f012b23dSStanimir Varbanov } 1811f012b23dSStanimir Varbanov 1812f012b23dSStanimir Varbanov return -EINVAL; 1813f012b23dSStanimir Varbanov } 1814f012b23dSStanimir Varbanov EXPORT_SYMBOL_GPL(venus_helper_get_out_fmts); 181501e869e7SDikshita Agarwal 181601e869e7SDikshita Agarwal int venus_helper_set_stride(struct venus_inst *inst, 181701e869e7SDikshita Agarwal unsigned int width, unsigned int height) 181801e869e7SDikshita Agarwal { 181901e869e7SDikshita Agarwal const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO; 182001e869e7SDikshita Agarwal 182101e869e7SDikshita Agarwal struct hfi_uncompressed_plane_actual_info plane_actual_info; 182201e869e7SDikshita Agarwal 182301e869e7SDikshita Agarwal plane_actual_info.buffer_type = HFI_BUFFER_INPUT; 182401e869e7SDikshita Agarwal plane_actual_info.num_planes = 2; 182501e869e7SDikshita Agarwal plane_actual_info.plane_format[0].actual_stride = width; 182601e869e7SDikshita Agarwal plane_actual_info.plane_format[0].actual_plane_buffer_height = height; 182701e869e7SDikshita Agarwal plane_actual_info.plane_format[1].actual_stride = width; 182801e869e7SDikshita Agarwal plane_actual_info.plane_format[1].actual_plane_buffer_height = height / 2; 182901e869e7SDikshita Agarwal 183001e869e7SDikshita Agarwal return hfi_session_set_property(inst, ptype, &plane_actual_info); 183101e869e7SDikshita Agarwal } 183201e869e7SDikshita Agarwal EXPORT_SYMBOL_GPL(venus_helper_set_stride); 1833