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        if (inst->opb_fmt == HFI_COLOR_FORMAT_NV12_UBWC)
1141                return 0;
1142
1143        pconstraint.buffer_type = HFI_BUFFER_OUTPUT2;
1144        pconstraint.num_planes = 2;
1145        pconstraint.plane_format[0].stride_multiples = 128;
1146        pconstraint.plane_format[0].max_stride = 8192;
1147        pconstraint.plane_format[0].min_plane_buffer_height_multiple = 32;
1148        pconstraint.plane_format[0].buffer_alignment = 256;
1149
1150        pconstraint.plane_format[1].stride_multiples = 128;
1151        pconstraint.plane_format[1].max_stride = 8192;
1152        pconstraint.plane_format[1].min_plane_buffer_height_multiple = 16;
1153        pconstraint.plane_format[1].buffer_alignment = 256;
1154
1155        return hfi_session_set_property(inst, ptype, &pconstraint);
1156}
1157EXPORT_SYMBOL_GPL(venus_helper_set_format_constraints);
1158
1159int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs,
1160                              unsigned int output_bufs,
1161                              unsigned int output2_bufs)
1162{
1163        u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL;
1164        struct hfi_buffer_count_actual buf_count;
1165        int ret;
1166
1167        buf_count.type = HFI_BUFFER_INPUT;
1168        buf_count.count_actual = input_bufs;
1169
1170        ret = hfi_session_set_property(inst, ptype, &buf_count);
1171        if (ret)
1172                return ret;
1173
1174        buf_count.type = HFI_BUFFER_OUTPUT;
1175        buf_count.count_actual = output_bufs;
1176
1177        ret = hfi_session_set_property(inst, ptype, &buf_count);
1178        if (ret)
1179                return ret;
1180
1181        if (output2_bufs) {
1182                buf_count.type = HFI_BUFFER_OUTPUT2;
1183                buf_count.count_actual = output2_bufs;
1184
1185                ret = hfi_session_set_property(inst, ptype, &buf_count);
1186        }
1187
1188        return ret;
1189}
1190EXPORT_SYMBOL_GPL(venus_helper_set_num_bufs);
1191
1192int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format,
1193                                u32 buftype)
1194{
1195        const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT;
1196        struct hfi_uncompressed_format_select fmt;
1197
1198        fmt.buffer_type = buftype;
1199        fmt.format = hfi_format;
1200
1201        return hfi_session_set_property(inst, ptype, &fmt);
1202}
1203EXPORT_SYMBOL_GPL(venus_helper_set_raw_format);
1204
1205int venus_helper_set_color_format(struct venus_inst *inst, u32 pixfmt)
1206{
1207        u32 hfi_format, buftype;
1208
1209        if (inst->session_type == VIDC_SESSION_TYPE_DEC)
1210                buftype = HFI_BUFFER_OUTPUT;
1211        else if (inst->session_type == VIDC_SESSION_TYPE_ENC)
1212                buftype = HFI_BUFFER_INPUT;
1213        else
1214                return -EINVAL;
1215
1216        hfi_format = to_hfi_raw_fmt(pixfmt);
1217        if (!hfi_format)
1218                return -EINVAL;
1219
1220        return venus_helper_set_raw_format(inst, hfi_format, buftype);
1221}
1222EXPORT_SYMBOL_GPL(venus_helper_set_color_format);
1223
1224int venus_helper_set_multistream(struct venus_inst *inst, bool out_en,
1225                                 bool out2_en)
1226{
1227        struct hfi_multi_stream multi = {0};
1228        u32 ptype = HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM;
1229        int ret;
1230
1231        multi.buffer_type = HFI_BUFFER_OUTPUT;
1232        multi.enable = out_en;
1233
1234        ret = hfi_session_set_property(inst, ptype, &multi);
1235        if (ret)
1236                return ret;
1237
1238        multi.buffer_type = HFI_BUFFER_OUTPUT2;
1239        multi.enable = out2_en;
1240
1241        return hfi_session_set_property(inst, ptype, &multi);
1242}
1243EXPORT_SYMBOL_GPL(venus_helper_set_multistream);
1244
1245int venus_helper_set_dyn_bufmode(struct venus_inst *inst)
1246{
1247        const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE;
1248        struct hfi_buffer_alloc_mode mode;
1249        int ret;
1250
1251        if (!is_dynamic_bufmode(inst))
1252                return 0;
1253
1254        mode.type = HFI_BUFFER_OUTPUT;
1255        mode.mode = HFI_BUFFER_MODE_DYNAMIC;
1256
1257        ret = hfi_session_set_property(inst, ptype, &mode);
1258        if (ret)
1259                return ret;
1260
1261        mode.type = HFI_BUFFER_OUTPUT2;
1262
1263        return hfi_session_set_property(inst, ptype, &mode);
1264}
1265EXPORT_SYMBOL_GPL(venus_helper_set_dyn_bufmode);
1266
1267int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype)
1268{
1269        const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL;
1270        struct hfi_buffer_size_actual bufsz;
1271
1272        bufsz.type = buftype;
1273        bufsz.size = bufsize;
1274
1275        return hfi_session_set_property(inst, ptype, &bufsz);
1276}
1277EXPORT_SYMBOL_GPL(venus_helper_set_bufsize);
1278
1279unsigned int venus_helper_get_opb_size(struct venus_inst *inst)
1280{
1281        /* the encoder has only one output */
1282        if (inst->session_type == VIDC_SESSION_TYPE_ENC)
1283                return inst->output_buf_size;
1284
1285        if (inst->opb_buftype == HFI_BUFFER_OUTPUT)
1286                return inst->output_buf_size;
1287        else if (inst->opb_buftype == HFI_BUFFER_OUTPUT2)
1288                return inst->output2_buf_size;
1289
1290        return 0;
1291}
1292EXPORT_SYMBOL_GPL(venus_helper_get_opb_size);
1293
1294static void delayed_process_buf_func(struct work_struct *work)
1295{
1296        struct venus_buffer *buf, *n;
1297        struct venus_inst *inst;
1298        int ret;
1299
1300        inst = container_of(work, struct venus_inst, delayed_process_work);
1301
1302        mutex_lock(&inst->lock);
1303
1304        if (!(inst->streamon_out & inst->streamon_cap))
1305                goto unlock;
1306
1307        list_for_each_entry_safe(buf, n, &inst->delayed_process, ref_list) {
1308                if (buf->flags & HFI_BUFFERFLAG_READONLY)
1309                        continue;
1310
1311                ret = session_process_buf(inst, &buf->vb);
1312                if (ret)
1313                        return_buf_error(inst, &buf->vb);
1314
1315                list_del_init(&buf->ref_list);
1316        }
1317unlock:
1318        mutex_unlock(&inst->lock);
1319}
1320
1321void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx)
1322{
1323        struct venus_buffer *buf;
1324
1325        list_for_each_entry(buf, &inst->registeredbufs, reg_list) {
1326                if (buf->vb.vb2_buf.index == idx) {
1327                        buf->flags &= ~HFI_BUFFERFLAG_READONLY;
1328                        schedule_work(&inst->delayed_process_work);
1329                        break;
1330                }
1331        }
1332}
1333EXPORT_SYMBOL_GPL(venus_helper_release_buf_ref);
1334
1335void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf)
1336{
1337        struct venus_buffer *buf = to_venus_buffer(vbuf);
1338
1339        buf->flags |= HFI_BUFFERFLAG_READONLY;
1340}
1341EXPORT_SYMBOL_GPL(venus_helper_acquire_buf_ref);
1342
1343static int is_buf_refed(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)
1344{
1345        struct venus_buffer *buf = to_venus_buffer(vbuf);
1346
1347        if (buf->flags & HFI_BUFFERFLAG_READONLY) {
1348                list_add_tail(&buf->ref_list, &inst->delayed_process);
1349                schedule_work(&inst->delayed_process_work);
1350                return 1;
1351        }
1352
1353        return 0;
1354}
1355
1356struct vb2_v4l2_buffer *
1357venus_helper_find_buf(struct venus_inst *inst, unsigned int type, u32 idx)
1358{
1359        struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
1360
1361        if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1362                return v4l2_m2m_src_buf_remove_by_idx(m2m_ctx, idx);
1363        else
1364                return v4l2_m2m_dst_buf_remove_by_idx(m2m_ctx, idx);
1365}
1366EXPORT_SYMBOL_GPL(venus_helper_find_buf);
1367
1368int venus_helper_vb2_buf_init(struct vb2_buffer *vb)
1369{
1370        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1371        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1372        struct venus_buffer *buf = to_venus_buffer(vbuf);
1373
1374        buf->size = vb2_plane_size(vb, 0);
1375        buf->dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
1376
1377        if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1378                list_add_tail(&buf->reg_list, &inst->registeredbufs);
1379
1380        return 0;
1381}
1382EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_init);
1383
1384int venus_helper_vb2_buf_prepare(struct vb2_buffer *vb)
1385{
1386        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1387        unsigned int out_buf_size = venus_helper_get_opb_size(inst);
1388        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1389
1390        if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
1391                if (vbuf->field == V4L2_FIELD_ANY)
1392                        vbuf->field = V4L2_FIELD_NONE;
1393                if (vbuf->field != V4L2_FIELD_NONE) {
1394                        dev_err(inst->core->dev, "%s field isn't supported\n",
1395                                __func__);
1396                        return -EINVAL;
1397                }
1398        }
1399
1400        if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
1401            vb2_plane_size(vb, 0) < out_buf_size)
1402                return -EINVAL;
1403        if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
1404            vb2_plane_size(vb, 0) < inst->input_buf_size)
1405                return -EINVAL;
1406
1407        return 0;
1408}
1409EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_prepare);
1410
1411static void cache_payload(struct venus_inst *inst, struct vb2_buffer *vb)
1412{
1413        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1414        unsigned int idx = vbuf->vb2_buf.index;
1415
1416        if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1417                inst->payloads[idx] = vb2_get_plane_payload(vb, 0);
1418}
1419
1420void venus_helper_vb2_buf_queue(struct vb2_buffer *vb)
1421{
1422        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1423        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1424        struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
1425        int ret;
1426
1427        v4l2_m2m_buf_queue(m2m_ctx, vbuf);
1428
1429        /* Skip processing queued capture buffers after LAST flag */
1430        if (inst->session_type == VIDC_SESSION_TYPE_DEC &&
1431            V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) &&
1432            inst->codec_state == VENUS_DEC_STATE_DRC)
1433                return;
1434
1435        cache_payload(inst, vb);
1436
1437        if (inst->session_type == VIDC_SESSION_TYPE_ENC &&
1438            !(inst->streamon_out && inst->streamon_cap))
1439                return;
1440
1441        if (vb2_start_streaming_called(vb->vb2_queue)) {
1442                ret = is_buf_refed(inst, vbuf);
1443                if (ret)
1444                        return;
1445
1446                ret = session_process_buf(inst, vbuf);
1447                if (ret)
1448                        return_buf_error(inst, vbuf);
1449        }
1450}
1451EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_queue);
1452
1453void venus_helper_buffers_done(struct venus_inst *inst, unsigned int type,
1454                               enum vb2_buffer_state state)
1455{
1456        struct vb2_v4l2_buffer *buf;
1457
1458        if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1459                while ((buf = v4l2_m2m_src_buf_remove(inst->m2m_ctx)))
1460                        v4l2_m2m_buf_done(buf, state);
1461        } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1462                while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx)))
1463                        v4l2_m2m_buf_done(buf, state);
1464        }
1465}
1466EXPORT_SYMBOL_GPL(venus_helper_buffers_done);
1467
1468void venus_helper_vb2_stop_streaming(struct vb2_queue *q)
1469{
1470        struct venus_inst *inst = vb2_get_drv_priv(q);
1471        struct venus_core *core = inst->core;
1472        int ret;
1473
1474        mutex_lock(&inst->lock);
1475
1476        if (inst->streamon_out & inst->streamon_cap) {
1477                ret = hfi_session_stop(inst);
1478                ret |= hfi_session_unload_res(inst);
1479                ret |= venus_helper_unregister_bufs(inst);
1480                ret |= venus_helper_intbufs_free(inst);
1481                ret |= hfi_session_deinit(inst);
1482
1483                if (inst->session_error || core->sys_error)
1484                        ret = -EIO;
1485
1486                if (ret)
1487                        hfi_session_abort(inst);
1488
1489                venus_helper_free_dpb_bufs(inst);
1490
1491                venus_pm_load_scale(inst);
1492                INIT_LIST_HEAD(&inst->registeredbufs);
1493        }
1494
1495        venus_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
1496                                  VB2_BUF_STATE_ERROR);
1497        venus_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
1498                                  VB2_BUF_STATE_ERROR);
1499
1500        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1501                inst->streamon_out = 0;
1502        else
1503                inst->streamon_cap = 0;
1504
1505        venus_pm_release_core(inst);
1506
1507        mutex_unlock(&inst->lock);
1508}
1509EXPORT_SYMBOL_GPL(venus_helper_vb2_stop_streaming);
1510
1511int venus_helper_process_initial_cap_bufs(struct venus_inst *inst)
1512{
1513        struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
1514        struct v4l2_m2m_buffer *buf, *n;
1515        int ret;
1516
1517        v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) {
1518                ret = session_process_buf(inst, &buf->vb);
1519                if (ret) {
1520                        return_buf_error(inst, &buf->vb);
1521                        return ret;
1522                }
1523        }
1524
1525        return 0;
1526}
1527EXPORT_SYMBOL_GPL(venus_helper_process_initial_cap_bufs);
1528
1529int venus_helper_process_initial_out_bufs(struct venus_inst *inst)
1530{
1531        struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
1532        struct v4l2_m2m_buffer *buf, *n;
1533        int ret;
1534
1535        v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) {
1536                ret = session_process_buf(inst, &buf->vb);
1537                if (ret) {
1538                        return_buf_error(inst, &buf->vb);
1539                        return ret;
1540                }
1541        }
1542
1543        return 0;
1544}
1545EXPORT_SYMBOL_GPL(venus_helper_process_initial_out_bufs);
1546
1547int venus_helper_vb2_start_streaming(struct venus_inst *inst)
1548{
1549        int ret;
1550
1551        ret = venus_helper_intbufs_alloc(inst);
1552        if (ret)
1553                return ret;
1554
1555        ret = session_register_bufs(inst);
1556        if (ret)
1557                goto err_bufs_free;
1558
1559        venus_pm_load_scale(inst);
1560
1561        ret = hfi_session_load_res(inst);
1562        if (ret)
1563                goto err_unreg_bufs;
1564
1565        ret = hfi_session_start(inst);
1566        if (ret)
1567                goto err_unload_res;
1568
1569        return 0;
1570
1571err_unload_res:
1572        hfi_session_unload_res(inst);
1573err_unreg_bufs:
1574        venus_helper_unregister_bufs(inst);
1575err_bufs_free:
1576        venus_helper_intbufs_free(inst);
1577        return ret;
1578}
1579EXPORT_SYMBOL_GPL(venus_helper_vb2_start_streaming);
1580
1581void venus_helper_m2m_device_run(void *priv)
1582{
1583        struct venus_inst *inst = priv;
1584        struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
1585        struct v4l2_m2m_buffer *buf, *n;
1586        int ret;
1587
1588        mutex_lock(&inst->lock);
1589
1590        v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) {
1591                ret = session_process_buf(inst, &buf->vb);
1592                if (ret)
1593                        return_buf_error(inst, &buf->vb);
1594        }
1595
1596        v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) {
1597                ret = session_process_buf(inst, &buf->vb);
1598                if (ret)
1599                        return_buf_error(inst, &buf->vb);
1600        }
1601
1602        mutex_unlock(&inst->lock);
1603}
1604EXPORT_SYMBOL_GPL(venus_helper_m2m_device_run);
1605
1606void venus_helper_m2m_job_abort(void *priv)
1607{
1608        struct venus_inst *inst = priv;
1609
1610        v4l2_m2m_job_finish(inst->m2m_dev, inst->m2m_ctx);
1611}
1612EXPORT_SYMBOL_GPL(venus_helper_m2m_job_abort);
1613
1614int venus_helper_session_init(struct venus_inst *inst)
1615{
1616        enum hfi_version version = inst->core->res->hfi_version;
1617        u32 session_type = inst->session_type;
1618        u32 codec;
1619        int ret;
1620
1621        codec = inst->session_type == VIDC_SESSION_TYPE_DEC ?
1622                        inst->fmt_out->pixfmt : inst->fmt_cap->pixfmt;
1623
1624        ret = hfi_session_init(inst, codec);
1625        if (ret)
1626                return ret;
1627
1628        inst->clk_data.vpp_freq = hfi_platform_get_codec_vpp_freq(version, codec,
1629                                                                  session_type);
1630        inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(version, codec,
1631                                                                  session_type);
1632        inst->clk_data.low_power_freq = hfi_platform_get_codec_lp_freq(version, codec,
1633                                                                       session_type);
1634
1635        return 0;
1636}
1637EXPORT_SYMBOL_GPL(venus_helper_session_init);
1638
1639void venus_helper_init_instance(struct venus_inst *inst)
1640{
1641        if (inst->session_type == VIDC_SESSION_TYPE_DEC) {
1642                INIT_LIST_HEAD(&inst->delayed_process);
1643                INIT_WORK(&inst->delayed_process_work,
1644                          delayed_process_buf_func);
1645        }
1646}
1647EXPORT_SYMBOL_GPL(venus_helper_init_instance);
1648
1649static bool find_fmt_from_caps(struct hfi_plat_caps *caps, u32 buftype, u32 fmt)
1650{
1651        unsigned int i;
1652
1653        for (i = 0; i < caps->num_fmts; i++) {
1654                if (caps->fmts[i].buftype == buftype &&
1655                    caps->fmts[i].fmt == fmt)
1656                        return true;
1657        }
1658
1659        return false;
1660}
1661
1662int venus_helper_get_out_fmts(struct venus_inst *inst, u32 v4l2_fmt,
1663                              u32 *out_fmt, u32 *out2_fmt, bool ubwc)
1664{
1665        struct venus_core *core = inst->core;
1666        struct hfi_plat_caps *caps;
1667        u32 ubwc_fmt, fmt = to_hfi_raw_fmt(v4l2_fmt);
1668        bool found, found_ubwc;
1669
1670        *out_fmt = *out2_fmt = 0;
1671
1672        if (!fmt)
1673                return -EINVAL;
1674
1675        caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);
1676        if (!caps)
1677                return -EINVAL;
1678
1679        if (inst->bit_depth == VIDC_BITDEPTH_10 &&
1680            inst->session_type == VIDC_SESSION_TYPE_DEC) {
1681                found_ubwc =
1682                        find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,
1683                                           HFI_COLOR_FORMAT_YUV420_TP10_UBWC);
1684                found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2,
1685                                           HFI_COLOR_FORMAT_NV12);
1686                if (found_ubwc && found) {
1687                        /*
1688                         * Hard-code DPB buffers to be 10bit UBWC and decoder
1689                         * output buffers in 8bit NV12 until V4L2 is able to
1690                         * expose compressed/tiled formats to applications.
1691                         */
1692                        *out_fmt = HFI_COLOR_FORMAT_YUV420_TP10_UBWC;
1693                        *out2_fmt = HFI_COLOR_FORMAT_NV12;
1694                        return 0;
1695                }
1696
1697                return -EINVAL;
1698        }
1699
1700        if (ubwc) {
1701                ubwc_fmt = fmt | HFI_COLOR_FORMAT_UBWC_BASE;
1702                found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,
1703                                                ubwc_fmt);
1704                found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);
1705
1706                if (found_ubwc && found) {
1707                        *out_fmt = ubwc_fmt;
1708                        *out2_fmt = fmt;
1709                        return 0;
1710                }
1711        }
1712
1713        found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, fmt);
1714        if (found) {
1715                *out_fmt = fmt;
1716                *out2_fmt = 0;
1717                return 0;
1718        }
1719
1720        found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);
1721        if (found) {
1722                *out_fmt = 0;
1723                *out2_fmt = fmt;
1724                return 0;
1725        }
1726
1727        return -EINVAL;
1728}
1729EXPORT_SYMBOL_GPL(venus_helper_get_out_fmts);
1730
1731int venus_helper_set_stride(struct venus_inst *inst,
1732                            unsigned int width, unsigned int height)
1733{
1734        const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO;
1735
1736        struct hfi_uncompressed_plane_actual_info plane_actual_info;
1737
1738        plane_actual_info.buffer_type = HFI_BUFFER_INPUT;
1739        plane_actual_info.num_planes = 2;
1740        plane_actual_info.plane_format[0].actual_stride = width;
1741        plane_actual_info.plane_format[0].actual_plane_buffer_height = height;
1742        plane_actual_info.plane_format[1].actual_stride = width;
1743        plane_actual_info.plane_format[1].actual_plane_buffer_height = height / 2;
1744
1745        return hfi_session_set_property(inst, ptype, &plane_actual_info);
1746}
1747EXPORT_SYMBOL_GPL(venus_helper_set_stride);
1748