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