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