linux/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2016 MediaTek Inc.
   3 * Author: Daniel Hsiao <daniel.hsiao@mediatek.com>
   4 *      Kai-Sean Yang <kai-sean.yang@mediatek.com>
   5 *      Tiffany Lin <tiffany.lin@mediatek.com>
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License
   9 * version 2 as published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 */
  16
  17#include <linux/fs.h>
  18#include <linux/slab.h>
  19#include <linux/syscalls.h>
  20#include <linux/delay.h>
  21#include <linux/time.h>
  22
  23#include "../mtk_vcodec_intr.h"
  24#include "../vdec_drv_base.h"
  25#include "../vdec_vpu_if.h"
  26
  27#define VP9_SUPER_FRAME_BS_SZ 64
  28#define MAX_VP9_DPB_SIZE        9
  29
  30#define REFS_PER_FRAME 3
  31#define MAX_NUM_REF_FRAMES 8
  32#define VP9_MAX_FRM_BUF_NUM 9
  33#define VP9_MAX_FRM_BUF_NODE_NUM (VP9_MAX_FRM_BUF_NUM * 2)
  34#define VP9_SEG_ID_SZ 0x12000
  35
  36/**
  37 * struct vp9_dram_buf - contains buffer info for vpu
  38 * @va : cpu address
  39 * @pa : iova address
  40 * @sz : buffer size
  41 * @padding : for 64 bytes alignment
  42 */
  43struct vp9_dram_buf {
  44        unsigned long va;
  45        unsigned long pa;
  46        unsigned int sz;
  47        unsigned int padding;
  48};
  49
  50/**
  51 * struct vp9_fb_info - contains frame buffer info
  52 * @fb : frmae buffer
  53 * @reserved : reserved field used by vpu
  54 */
  55struct vp9_fb_info {
  56        struct vdec_fb *fb;
  57        unsigned int reserved[32];
  58};
  59
  60/**
  61 * struct vp9_ref_cnt_buf - contains reference buffer information
  62 * @buf : referenced frame buffer
  63 * @ref_cnt : referenced frame buffer's reference count.
  64 *      When reference count=0, remove it from reference list
  65 */
  66struct vp9_ref_cnt_buf {
  67        struct vp9_fb_info buf;
  68        unsigned int ref_cnt;
  69};
  70
  71/**
  72 * struct vp9_fb_info - contains current frame's reference buffer information
  73 * @buf : reference buffer
  74 * @idx : reference buffer index to frm_bufs
  75 * @reserved : reserved field used by vpu
  76 */
  77struct vp9_ref_buf {
  78        struct vp9_fb_info *buf;
  79        unsigned int idx;
  80        unsigned int reserved[6];
  81};
  82
  83/**
  84 * struct vp9_fb_info - contains frame buffer info
  85 * @fb : super frame reference frame buffer
  86 * @used : this reference frame info entry is used
  87 * @padding : for 64 bytes size align
  88 */
  89struct vp9_sf_ref_fb {
  90        struct vdec_fb fb;
  91        int used;
  92        int padding;
  93};
  94
  95/*
  96 * struct vdec_vp9_vsi - shared buffer between host and VPU firmware
  97 *      AP-W/R : AP is writer/reader on this item
  98 *      VPU-W/R: VPU is write/reader on this item
  99 * @sf_bs_buf : super frame backup buffer (AP-W, VPU-R)
 100 * @sf_ref_fb : record supoer frame reference buffer information
 101 *      (AP-R/W, VPU-R/W)
 102 * @sf_next_ref_fb_idx : next available super frame (AP-W, VPU-R)
 103 * @sf_frm_cnt : super frame count, filled by vpu (AP-R, VPU-W)
 104 * @sf_frm_offset : super frame offset, filled by vpu (AP-R, VPU-W)
 105 * @sf_frm_sz : super frame size, filled by vpu (AP-R, VPU-W)
 106 * @sf_frm_idx : current super frame (AP-R, VPU-W)
 107 * @sf_init : inform super frame info already parsed by vpu (AP-R, VPU-W)
 108 * @fb : capture buffer (AP-W, VPU-R)
 109 * @bs : bs buffer (AP-W, VPU-R)
 110 * @cur_fb : current show capture buffer (AP-R/W, VPU-R/W)
 111 * @pic_w : picture width (AP-R, VPU-W)
 112 * @pic_h : picture height (AP-R, VPU-W)
 113 * @buf_w : codec width (AP-R, VPU-W)
 114 * @buf_h : coded height (AP-R, VPU-W)
 115 * @buf_sz_y_bs : ufo compressed y plane size (AP-R, VPU-W)
 116 * @buf_sz_c_bs : ufo compressed cbcr plane size (AP-R, VPU-W)
 117 * @buf_len_sz_y : size used to store y plane ufo info (AP-R, VPU-W)
 118 * @buf_len_sz_c : size used to store cbcr plane ufo info (AP-R, VPU-W)
 119
 120 * @profile : profile sparsed from vpu (AP-R, VPU-W)
 121 * @show_frame : display this frame or not (AP-R, VPU-W)
 122 * @show_existing_frame : inform this frame is show existing frame
 123 *      (AP-R, VPU-W)
 124 * @frm_to_show_idx : index to show frame (AP-R, VPU-W)
 125
 126 * @refresh_frm_flags : indicate when frame need to refine reference count
 127 *      (AP-R, VPU-W)
 128 * @resolution_changed : resolution change in this frame (AP-R, VPU-W)
 129
 130 * @frm_bufs : maintain reference buffer info (AP-R/W, VPU-R/W)
 131 * @ref_frm_map : maintain reference buffer map info (AP-R/W, VPU-R/W)
 132 * @new_fb_idx : index to frm_bufs array (AP-R, VPU-W)
 133 * @frm_num : decoded frame number, include sub-frame count (AP-R, VPU-W)
 134 * @mv_buf : motion vector working buffer (AP-W, VPU-R)
 135 * @frm_refs : maintain three reference buffer info (AP-R/W, VPU-R/W)
 136 * @seg_id_buf : segmentation map working buffer (AP-W, VPU-R)
 137 */
 138struct vdec_vp9_vsi {
 139        unsigned char sf_bs_buf[VP9_SUPER_FRAME_BS_SZ];
 140        struct vp9_sf_ref_fb sf_ref_fb[VP9_MAX_FRM_BUF_NUM-1];
 141        int sf_next_ref_fb_idx;
 142        unsigned int sf_frm_cnt;
 143        unsigned int sf_frm_offset[VP9_MAX_FRM_BUF_NUM-1];
 144        unsigned int sf_frm_sz[VP9_MAX_FRM_BUF_NUM-1];
 145        unsigned int sf_frm_idx;
 146        unsigned int sf_init;
 147        struct vdec_fb fb;
 148        struct mtk_vcodec_mem bs;
 149        struct vdec_fb cur_fb;
 150        unsigned int pic_w;
 151        unsigned int pic_h;
 152        unsigned int buf_w;
 153        unsigned int buf_h;
 154        unsigned int buf_sz_y_bs;
 155        unsigned int buf_sz_c_bs;
 156        unsigned int buf_len_sz_y;
 157        unsigned int buf_len_sz_c;
 158        unsigned int profile;
 159        unsigned int show_frame;
 160        unsigned int show_existing_frame;
 161        unsigned int frm_to_show_idx;
 162        unsigned int refresh_frm_flags;
 163        unsigned int resolution_changed;
 164
 165        struct vp9_ref_cnt_buf frm_bufs[VP9_MAX_FRM_BUF_NUM];
 166        int ref_frm_map[MAX_NUM_REF_FRAMES];
 167        unsigned int new_fb_idx;
 168        unsigned int frm_num;
 169        struct vp9_dram_buf mv_buf;
 170
 171        struct vp9_ref_buf frm_refs[REFS_PER_FRAME];
 172        struct vp9_dram_buf seg_id_buf;
 173
 174};
 175
 176/*
 177 * struct vdec_vp9_inst - vp9 decode instance
 178 * @mv_buf : working buffer for mv
 179 * @seg_id_buf : working buffer for segmentation map
 180 * @dec_fb : vdec_fb node to link fb to different fb_xxx_list
 181 * @available_fb_node_list : current available vdec_fb node
 182 * @fb_use_list : current used or referenced vdec_fb
 183 * @fb_free_list : current available to free vdec_fb
 184 * @fb_disp_list : current available to display vdec_fb
 185 * @cur_fb : current frame buffer
 186 * @ctx : current decode context
 187 * @vpu : vpu instance information
 188 * @vsi : shared buffer between host and VPU firmware
 189 * @total_frm_cnt : total frame count, it do not include sub-frames in super
 190 *          frame
 191 * @mem : instance memory information
 192 */
 193struct vdec_vp9_inst {
 194        struct mtk_vcodec_mem mv_buf;
 195        struct mtk_vcodec_mem seg_id_buf;
 196
 197        struct vdec_fb_node dec_fb[VP9_MAX_FRM_BUF_NODE_NUM];
 198        struct list_head available_fb_node_list;
 199        struct list_head fb_use_list;
 200        struct list_head fb_free_list;
 201        struct list_head fb_disp_list;
 202        struct vdec_fb *cur_fb;
 203        struct mtk_vcodec_ctx *ctx;
 204        struct vdec_vpu_inst vpu;
 205        struct vdec_vp9_vsi *vsi;
 206        unsigned int total_frm_cnt;
 207        struct mtk_vcodec_mem mem;
 208};
 209
 210static bool vp9_is_sf_ref_fb(struct vdec_vp9_inst *inst, struct vdec_fb *fb)
 211{
 212        int i;
 213        struct vdec_vp9_vsi *vsi = inst->vsi;
 214
 215        for (i = 0; i < ARRAY_SIZE(vsi->sf_ref_fb); i++) {
 216                if (fb == &vsi->sf_ref_fb[i].fb)
 217                        return true;
 218        }
 219        return false;
 220}
 221
 222static struct vdec_fb *vp9_rm_from_fb_use_list(struct vdec_vp9_inst
 223                                        *inst, void *addr)
 224{
 225        struct vdec_fb *fb = NULL;
 226        struct vdec_fb_node *node;
 227
 228        list_for_each_entry(node, &inst->fb_use_list, list) {
 229                fb = (struct vdec_fb *)node->fb;
 230                if (fb->base_y.va == addr) {
 231                        list_move_tail(&node->list,
 232                                       &inst->available_fb_node_list);
 233                        break;
 234                }
 235        }
 236        return fb;
 237}
 238
 239static void vp9_add_to_fb_free_list(struct vdec_vp9_inst *inst,
 240                             struct vdec_fb *fb)
 241{
 242        struct vdec_fb_node *node;
 243
 244        if (fb) {
 245                node = list_first_entry_or_null(&inst->available_fb_node_list,
 246                                        struct vdec_fb_node, list);
 247
 248                if (node) {
 249                        node->fb = fb;
 250                        list_move_tail(&node->list, &inst->fb_free_list);
 251                }
 252        } else {
 253                mtk_vcodec_debug(inst, "No free fb node");
 254        }
 255}
 256
 257static void vp9_free_sf_ref_fb(struct vdec_fb *fb)
 258{
 259        struct vp9_sf_ref_fb *sf_ref_fb =
 260                container_of(fb, struct vp9_sf_ref_fb, fb);
 261
 262        sf_ref_fb->used = 0;
 263}
 264
 265static void vp9_ref_cnt_fb(struct vdec_vp9_inst *inst, int *idx,
 266                           int new_idx)
 267{
 268        struct vdec_vp9_vsi *vsi = inst->vsi;
 269        int ref_idx = *idx;
 270
 271        if (ref_idx >= 0 && vsi->frm_bufs[ref_idx].ref_cnt > 0) {
 272                vsi->frm_bufs[ref_idx].ref_cnt--;
 273
 274                if (vsi->frm_bufs[ref_idx].ref_cnt == 0) {
 275                        if (!vp9_is_sf_ref_fb(inst,
 276                                              vsi->frm_bufs[ref_idx].buf.fb)) {
 277                                struct vdec_fb *fb;
 278
 279                                fb = vp9_rm_from_fb_use_list(inst,
 280                                     vsi->frm_bufs[ref_idx].buf.fb->base_y.va);
 281                                vp9_add_to_fb_free_list(inst, fb);
 282                        } else
 283                                vp9_free_sf_ref_fb(
 284                                        vsi->frm_bufs[ref_idx].buf.fb);
 285                }
 286        }
 287
 288        *idx = new_idx;
 289        vsi->frm_bufs[new_idx].ref_cnt++;
 290}
 291
 292static void vp9_free_all_sf_ref_fb(struct vdec_vp9_inst *inst)
 293{
 294        int i;
 295        struct vdec_vp9_vsi *vsi = inst->vsi;
 296
 297        for (i = 0; i < ARRAY_SIZE(vsi->sf_ref_fb); i++) {
 298                if (vsi->sf_ref_fb[i].fb.base_y.va) {
 299                        mtk_vcodec_mem_free(inst->ctx,
 300                                &vsi->sf_ref_fb[i].fb.base_y);
 301                        mtk_vcodec_mem_free(inst->ctx,
 302                                &vsi->sf_ref_fb[i].fb.base_c);
 303                        vsi->sf_ref_fb[i].used = 0;
 304                }
 305        }
 306}
 307
 308/* For each sub-frame except the last one, the driver will dynamically
 309 * allocate reference buffer by calling vp9_get_sf_ref_fb()
 310 * The last sub-frame will use the original fb provided by the
 311 * vp9_dec_decode() interface
 312 */
 313static int vp9_get_sf_ref_fb(struct vdec_vp9_inst *inst)
 314{
 315        int idx;
 316        struct mtk_vcodec_mem *mem_basy_y;
 317        struct mtk_vcodec_mem *mem_basy_c;
 318        struct vdec_vp9_vsi *vsi = inst->vsi;
 319
 320        for (idx = 0;
 321                idx < ARRAY_SIZE(vsi->sf_ref_fb);
 322                idx++) {
 323                if (vsi->sf_ref_fb[idx].fb.base_y.va &&
 324                    vsi->sf_ref_fb[idx].used == 0) {
 325                        return idx;
 326                }
 327        }
 328
 329        for (idx = 0;
 330                idx < ARRAY_SIZE(vsi->sf_ref_fb);
 331                idx++) {
 332                if (vsi->sf_ref_fb[idx].fb.base_y.va == NULL)
 333                        break;
 334        }
 335
 336        if (idx == ARRAY_SIZE(vsi->sf_ref_fb)) {
 337                mtk_vcodec_err(inst, "List Full");
 338                return -1;
 339        }
 340
 341        mem_basy_y = &vsi->sf_ref_fb[idx].fb.base_y;
 342        mem_basy_y->size = vsi->buf_sz_y_bs +
 343                vsi->buf_len_sz_y;
 344
 345        if (mtk_vcodec_mem_alloc(inst->ctx, mem_basy_y)) {
 346                mtk_vcodec_err(inst, "Cannot allocate sf_ref_buf y_buf");
 347                return -1;
 348        }
 349
 350        mem_basy_c = &vsi->sf_ref_fb[idx].fb.base_c;
 351        mem_basy_c->size = vsi->buf_sz_c_bs +
 352                vsi->buf_len_sz_c;
 353
 354        if (mtk_vcodec_mem_alloc(inst->ctx, mem_basy_c)) {
 355                mtk_vcodec_err(inst, "Cannot allocate sf_ref_fb c_buf");
 356                return -1;
 357        }
 358        vsi->sf_ref_fb[idx].used = 0;
 359
 360        return idx;
 361}
 362
 363static bool vp9_alloc_work_buf(struct vdec_vp9_inst *inst)
 364{
 365        struct vdec_vp9_vsi *vsi = inst->vsi;
 366        int result;
 367        struct mtk_vcodec_mem *mem;
 368
 369        unsigned int max_pic_w;
 370        unsigned int max_pic_h;
 371
 372
 373        if (!(inst->ctx->dev->dec_capability &
 374                VCODEC_CAPABILITY_4K_DISABLED)) {
 375                max_pic_w = VCODEC_DEC_4K_CODED_WIDTH;
 376                max_pic_h = VCODEC_DEC_4K_CODED_HEIGHT;
 377        } else {
 378                max_pic_w = MTK_VDEC_MAX_W;
 379                max_pic_h = MTK_VDEC_MAX_H;
 380        }
 381
 382        if ((vsi->pic_w > max_pic_w) ||
 383                (vsi->pic_h > max_pic_h)) {
 384                mtk_vcodec_err(inst, "Invalid w/h %d/%d",
 385                                vsi->pic_w, vsi->pic_h);
 386                return false;
 387        }
 388
 389        mtk_vcodec_debug(inst, "BUF CHG(%d): w/h/sb_w/sb_h=%d/%d/%d/%d",
 390                        vsi->resolution_changed,
 391                        vsi->pic_w,
 392                        vsi->pic_h,
 393                        vsi->buf_w,
 394                        vsi->buf_h);
 395
 396        mem = &inst->mv_buf;
 397        if (mem->va)
 398                mtk_vcodec_mem_free(inst->ctx, mem);
 399
 400        mem->size = ((vsi->buf_w / 64) *
 401                    (vsi->buf_h / 64) + 2) * 36 * 16;
 402        result = mtk_vcodec_mem_alloc(inst->ctx, mem);
 403        if (result) {
 404                mem->size = 0;
 405                mtk_vcodec_err(inst, "Cannot allocate mv_buf");
 406                return false;
 407        }
 408        /* Set the va again */
 409        vsi->mv_buf.va = (unsigned long)mem->va;
 410        vsi->mv_buf.pa = (unsigned long)mem->dma_addr;
 411        vsi->mv_buf.sz = (unsigned int)mem->size;
 412
 413
 414        mem = &inst->seg_id_buf;
 415        if (mem->va)
 416                mtk_vcodec_mem_free(inst->ctx, mem);
 417
 418        mem->size = VP9_SEG_ID_SZ;
 419        result = mtk_vcodec_mem_alloc(inst->ctx, mem);
 420        if (result) {
 421                mem->size = 0;
 422                mtk_vcodec_err(inst, "Cannot allocate seg_id_buf");
 423                return false;
 424        }
 425        /* Set the va again */
 426        vsi->seg_id_buf.va = (unsigned long)mem->va;
 427        vsi->seg_id_buf.pa = (unsigned long)mem->dma_addr;
 428        vsi->seg_id_buf.sz = (unsigned int)mem->size;
 429
 430
 431        vp9_free_all_sf_ref_fb(inst);
 432        vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
 433
 434        return true;
 435}
 436
 437static bool vp9_add_to_fb_disp_list(struct vdec_vp9_inst *inst,
 438                             struct vdec_fb *fb)
 439{
 440        struct vdec_fb_node *node;
 441
 442        if (!fb) {
 443                mtk_vcodec_err(inst, "fb == NULL");
 444                return false;
 445        }
 446
 447        node = list_first_entry_or_null(&inst->available_fb_node_list,
 448                                        struct vdec_fb_node, list);
 449        if (node) {
 450                node->fb = fb;
 451                list_move_tail(&node->list, &inst->fb_disp_list);
 452        } else {
 453                mtk_vcodec_err(inst, "No available fb node");
 454                return false;
 455        }
 456
 457        return true;
 458}
 459
 460/* If any buffer updating is signaled it should be done here. */
 461static void vp9_swap_frm_bufs(struct vdec_vp9_inst *inst)
 462{
 463        struct vdec_vp9_vsi *vsi = inst->vsi;
 464        struct vp9_fb_info *frm_to_show;
 465        int ref_index = 0, mask;
 466
 467        for (mask = vsi->refresh_frm_flags; mask; mask >>= 1) {
 468                if (mask & 1)
 469                        vp9_ref_cnt_fb(inst, &vsi->ref_frm_map[ref_index],
 470                                       vsi->new_fb_idx);
 471                ++ref_index;
 472        }
 473
 474        frm_to_show = &vsi->frm_bufs[vsi->new_fb_idx].buf;
 475        vsi->frm_bufs[vsi->new_fb_idx].ref_cnt--;
 476
 477        if (frm_to_show->fb != inst->cur_fb) {
 478                /* This frame is show exist frame and no decode output
 479                 * copy frame data from frm_to_show to current CAPTURE
 480                 * buffer
 481                 */
 482                if ((frm_to_show->fb != NULL) &&
 483                        (inst->cur_fb->base_y.size >=
 484                        frm_to_show->fb->base_y.size)) {
 485                        memcpy((void *)inst->cur_fb->base_y.va,
 486                                (void *)frm_to_show->fb->base_y.va,
 487                                vsi->buf_w *
 488                                vsi->buf_h);
 489                        memcpy((void *)inst->cur_fb->base_c.va,
 490                                (void *)frm_to_show->fb->base_c.va,
 491                                vsi->buf_w *
 492                                vsi->buf_h / 2);
 493                } else {
 494                        /* After resolution change case, current CAPTURE buffer
 495                         * may have less buffer size than frm_to_show buffer
 496                         * size
 497                         */
 498                        if (frm_to_show->fb != NULL)
 499                                mtk_vcodec_err(inst,
 500                                        "inst->cur_fb->base_y.size=%zu, frm_to_show->fb.base_y.size=%zu",
 501                                        inst->cur_fb->base_y.size,
 502                                        frm_to_show->fb->base_y.size);
 503                }
 504                if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) {
 505                        if (vsi->show_frame)
 506                                vp9_add_to_fb_disp_list(inst, inst->cur_fb);
 507                }
 508        } else {
 509                if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) {
 510                        if (vsi->show_frame)
 511                                vp9_add_to_fb_disp_list(inst, frm_to_show->fb);
 512                }
 513        }
 514
 515        /* when ref_cnt ==0, move this fb to fb_free_list. v4l2 driver will
 516         * clean fb_free_list
 517         */
 518        if (vsi->frm_bufs[vsi->new_fb_idx].ref_cnt == 0) {
 519                if (!vp9_is_sf_ref_fb(
 520                        inst, vsi->frm_bufs[vsi->new_fb_idx].buf.fb)) {
 521                        struct vdec_fb *fb;
 522
 523                        fb = vp9_rm_from_fb_use_list(inst,
 524                        vsi->frm_bufs[vsi->new_fb_idx].buf.fb->base_y.va);
 525
 526                        vp9_add_to_fb_free_list(inst, fb);
 527                } else {
 528                        vp9_free_sf_ref_fb(
 529                                vsi->frm_bufs[vsi->new_fb_idx].buf.fb);
 530                }
 531        }
 532
 533        /* if this super frame and it is not last sub-frame, get next fb for
 534         * sub-frame decode
 535         */
 536        if (vsi->sf_frm_cnt > 0 && vsi->sf_frm_idx != vsi->sf_frm_cnt - 1)
 537                vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
 538}
 539
 540static bool vp9_wait_dec_end(struct vdec_vp9_inst *inst)
 541{
 542        struct mtk_vcodec_ctx *ctx = inst->ctx;
 543
 544        mtk_vcodec_wait_for_done_ctx(inst->ctx,
 545                        MTK_INST_IRQ_RECEIVED,
 546                        WAIT_INTR_TIMEOUT_MS);
 547
 548        if (ctx->irq_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
 549                return true;
 550        else
 551                return false;
 552}
 553
 554static struct vdec_vp9_inst *vp9_alloc_inst(struct mtk_vcodec_ctx *ctx)
 555{
 556        int result;
 557        struct mtk_vcodec_mem mem;
 558        struct vdec_vp9_inst *inst;
 559
 560        memset(&mem, 0, sizeof(mem));
 561        mem.size = sizeof(struct vdec_vp9_inst);
 562        result = mtk_vcodec_mem_alloc(ctx, &mem);
 563        if (result)
 564                return NULL;
 565
 566        inst = mem.va;
 567        inst->mem = mem;
 568
 569        return inst;
 570}
 571
 572static void vp9_free_inst(struct vdec_vp9_inst *inst)
 573{
 574        struct mtk_vcodec_mem mem;
 575
 576        mem = inst->mem;
 577        if (mem.va)
 578                mtk_vcodec_mem_free(inst->ctx, &mem);
 579}
 580
 581static bool vp9_decode_end_proc(struct vdec_vp9_inst *inst)
 582{
 583        struct vdec_vp9_vsi *vsi = inst->vsi;
 584        bool ret = false;
 585
 586        if (!vsi->show_existing_frame) {
 587                ret = vp9_wait_dec_end(inst);
 588                if (!ret) {
 589                        mtk_vcodec_err(inst, "Decode failed, Decode Timeout @[%d]",
 590                                vsi->frm_num);
 591                        return false;
 592                }
 593
 594                if (vpu_dec_end(&inst->vpu)) {
 595                        mtk_vcodec_err(inst, "vp9_dec_vpu_end failed");
 596                        return false;
 597                }
 598                mtk_vcodec_debug(inst, "Decode Ok @%d (%d/%d)", vsi->frm_num,
 599                                vsi->pic_w, vsi->pic_h);
 600        } else {
 601                mtk_vcodec_debug(inst, "Decode Ok @%d (show_existing_frame)",
 602                                vsi->frm_num);
 603        }
 604
 605        vp9_swap_frm_bufs(inst);
 606        vsi->frm_num++;
 607        return true;
 608}
 609
 610static bool vp9_is_last_sub_frm(struct vdec_vp9_inst *inst)
 611{
 612        struct vdec_vp9_vsi *vsi = inst->vsi;
 613
 614        if (vsi->sf_frm_cnt <= 0 || vsi->sf_frm_idx == vsi->sf_frm_cnt)
 615                return true;
 616
 617        return false;
 618}
 619
 620static struct vdec_fb *vp9_rm_from_fb_disp_list(struct vdec_vp9_inst *inst)
 621{
 622        struct vdec_fb_node *node;
 623        struct vdec_fb *fb = NULL;
 624
 625        node = list_first_entry_or_null(&inst->fb_disp_list,
 626                                        struct vdec_fb_node, list);
 627        if (node) {
 628                fb = (struct vdec_fb *)node->fb;
 629                fb->status |= FB_ST_DISPLAY;
 630                list_move_tail(&node->list, &inst->available_fb_node_list);
 631                mtk_vcodec_debug(inst, "[FB] get disp fb %p st=%d",
 632                                 node->fb, fb->status);
 633        } else
 634                mtk_vcodec_debug(inst, "[FB] there is no disp fb");
 635
 636        return fb;
 637}
 638
 639static bool vp9_add_to_fb_use_list(struct vdec_vp9_inst *inst,
 640                            struct vdec_fb *fb)
 641{
 642        struct vdec_fb_node *node;
 643
 644        if (!fb) {
 645                mtk_vcodec_debug(inst, "fb == NULL");
 646                return false;
 647        }
 648
 649        node = list_first_entry_or_null(&inst->available_fb_node_list,
 650                                        struct vdec_fb_node, list);
 651        if (node) {
 652                node->fb = fb;
 653                list_move_tail(&node->list, &inst->fb_use_list);
 654        } else {
 655                mtk_vcodec_err(inst, "No free fb node");
 656                return false;
 657        }
 658        return true;
 659}
 660
 661static void vp9_reset(struct vdec_vp9_inst *inst)
 662{
 663        struct vdec_fb_node *node, *tmp;
 664
 665        list_for_each_entry_safe(node, tmp, &inst->fb_use_list, list)
 666                list_move_tail(&node->list, &inst->fb_free_list);
 667
 668        vp9_free_all_sf_ref_fb(inst);
 669        inst->vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
 670
 671        if (vpu_dec_reset(&inst->vpu))
 672                mtk_vcodec_err(inst, "vp9_dec_vpu_reset failed");
 673
 674        /* Set the va again, since vpu_dec_reset will clear mv_buf in vpu */
 675        inst->vsi->mv_buf.va = (unsigned long)inst->mv_buf.va;
 676        inst->vsi->mv_buf.pa = (unsigned long)inst->mv_buf.dma_addr;
 677        inst->vsi->mv_buf.sz = (unsigned long)inst->mv_buf.size;
 678
 679        /* Set the va again, since vpu_dec_reset will clear seg_id_buf in vpu */
 680        inst->vsi->seg_id_buf.va = (unsigned long)inst->seg_id_buf.va;
 681        inst->vsi->seg_id_buf.pa = (unsigned long)inst->seg_id_buf.dma_addr;
 682        inst->vsi->seg_id_buf.sz = (unsigned long)inst->seg_id_buf.size;
 683
 684}
 685
 686static void init_all_fb_lists(struct vdec_vp9_inst *inst)
 687{
 688        int i;
 689
 690        INIT_LIST_HEAD(&inst->available_fb_node_list);
 691        INIT_LIST_HEAD(&inst->fb_use_list);
 692        INIT_LIST_HEAD(&inst->fb_free_list);
 693        INIT_LIST_HEAD(&inst->fb_disp_list);
 694
 695        for (i = 0; i < ARRAY_SIZE(inst->dec_fb); i++) {
 696                INIT_LIST_HEAD(&inst->dec_fb[i].list);
 697                inst->dec_fb[i].fb = NULL;
 698                list_add_tail(&inst->dec_fb[i].list,
 699                              &inst->available_fb_node_list);
 700        }
 701}
 702
 703static void get_pic_info(struct vdec_vp9_inst *inst, struct vdec_pic_info *pic)
 704{
 705        pic->y_bs_sz = inst->vsi->buf_sz_y_bs;
 706        pic->c_bs_sz = inst->vsi->buf_sz_c_bs;
 707        pic->y_len_sz = inst->vsi->buf_len_sz_y;
 708        pic->c_len_sz = inst->vsi->buf_len_sz_c;
 709
 710        pic->pic_w = inst->vsi->pic_w;
 711        pic->pic_h = inst->vsi->pic_h;
 712        pic->buf_w = inst->vsi->buf_w;
 713        pic->buf_h = inst->vsi->buf_h;
 714
 715        mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
 716                 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
 717        mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
 718                 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
 719}
 720
 721static void get_disp_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb)
 722{
 723
 724        *out_fb = vp9_rm_from_fb_disp_list(inst);
 725        if (*out_fb)
 726                (*out_fb)->status |= FB_ST_DISPLAY;
 727}
 728
 729static void get_free_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb)
 730{
 731        struct vdec_fb_node *node;
 732        struct vdec_fb *fb = NULL;
 733
 734        node = list_first_entry_or_null(&inst->fb_free_list,
 735                                        struct vdec_fb_node, list);
 736        if (node) {
 737                list_move_tail(&node->list, &inst->available_fb_node_list);
 738                fb = (struct vdec_fb *)node->fb;
 739                fb->status |= FB_ST_FREE;
 740                mtk_vcodec_debug(inst, "[FB] get free fb %p st=%d",
 741                                 node->fb, fb->status);
 742        } else {
 743                mtk_vcodec_debug(inst, "[FB] there is no free fb");
 744        }
 745
 746        *out_fb = fb;
 747}
 748
 749static int validate_vsi_array_indexes(struct vdec_vp9_inst *inst,
 750                struct vdec_vp9_vsi *vsi) {
 751        if (vsi->sf_frm_idx >= VP9_MAX_FRM_BUF_NUM - 1) {
 752                mtk_vcodec_err(inst, "Invalid vsi->sf_frm_idx=%u.",
 753                                vsi->sf_frm_idx);
 754                return -EIO;
 755        }
 756        if (vsi->frm_to_show_idx >= VP9_MAX_FRM_BUF_NUM) {
 757                mtk_vcodec_err(inst, "Invalid vsi->frm_to_show_idx=%u.",
 758                                vsi->frm_to_show_idx);
 759                return -EIO;
 760        }
 761        if (vsi->new_fb_idx >= VP9_MAX_FRM_BUF_NUM) {
 762                mtk_vcodec_err(inst, "Invalid vsi->new_fb_idx=%u.",
 763                                vsi->new_fb_idx);
 764                return -EIO;
 765        }
 766        return 0;
 767}
 768
 769static void vdec_vp9_deinit(unsigned long h_vdec)
 770{
 771        struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
 772        struct mtk_vcodec_mem *mem;
 773        int ret = 0;
 774
 775        ret = vpu_dec_deinit(&inst->vpu);
 776        if (ret)
 777                mtk_vcodec_err(inst, "vpu_dec_deinit failed");
 778
 779        mem = &inst->mv_buf;
 780        if (mem->va)
 781                mtk_vcodec_mem_free(inst->ctx, mem);
 782
 783        mem = &inst->seg_id_buf;
 784        if (mem->va)
 785                mtk_vcodec_mem_free(inst->ctx, mem);
 786
 787        vp9_free_all_sf_ref_fb(inst);
 788        vp9_free_inst(inst);
 789}
 790
 791static int vdec_vp9_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
 792{
 793        struct vdec_vp9_inst *inst;
 794
 795        inst = vp9_alloc_inst(ctx);
 796        if (!inst)
 797                return -ENOMEM;
 798
 799        inst->total_frm_cnt = 0;
 800        inst->ctx = ctx;
 801
 802        inst->vpu.id = IPI_VDEC_VP9;
 803        inst->vpu.dev = ctx->dev->vpu_plat_dev;
 804        inst->vpu.ctx = ctx;
 805        inst->vpu.handler = vpu_dec_ipi_handler;
 806
 807        if (vpu_dec_init(&inst->vpu)) {
 808                mtk_vcodec_err(inst, "vp9_dec_vpu_init failed");
 809                goto err_deinit_inst;
 810        }
 811
 812        inst->vsi = (struct vdec_vp9_vsi *)inst->vpu.vsi;
 813        init_all_fb_lists(inst);
 814
 815        (*h_vdec) = (unsigned long)inst;
 816        return 0;
 817
 818err_deinit_inst:
 819        vp9_free_inst(inst);
 820
 821        return -EINVAL;
 822}
 823
 824static int vdec_vp9_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
 825                   struct vdec_fb *fb, bool *res_chg)
 826{
 827        int ret = 0;
 828        struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
 829        struct vdec_vp9_vsi *vsi = inst->vsi;
 830        u32 data[3];
 831        int i;
 832
 833        *res_chg = false;
 834
 835        if ((bs == NULL) && (fb == NULL)) {
 836                mtk_vcodec_debug(inst, "[EOS]");
 837                vp9_reset(inst);
 838                return ret;
 839        }
 840
 841        if (bs == NULL) {
 842                mtk_vcodec_err(inst, "bs == NULL");
 843                return -EINVAL;
 844        }
 845
 846        mtk_vcodec_debug(inst, "Input BS Size = %zu", bs->size);
 847
 848        while (1) {
 849                struct vdec_fb *cur_fb = NULL;
 850
 851                data[0] = *((unsigned int *)bs->va);
 852                data[1] = *((unsigned int *)(bs->va + 4));
 853                data[2] = *((unsigned int *)(bs->va + 8));
 854
 855                vsi->bs = *bs;
 856
 857                if (fb)
 858                        vsi->fb = *fb;
 859
 860                if (!vsi->sf_init) {
 861                        unsigned int sf_bs_sz;
 862                        unsigned int sf_bs_off;
 863                        unsigned char *sf_bs_src;
 864                        unsigned char *sf_bs_dst;
 865
 866                        sf_bs_sz = bs->size > VP9_SUPER_FRAME_BS_SZ ?
 867                                        VP9_SUPER_FRAME_BS_SZ : bs->size;
 868                        sf_bs_off = VP9_SUPER_FRAME_BS_SZ - sf_bs_sz;
 869                        sf_bs_src = bs->va + bs->size - sf_bs_sz;
 870                        sf_bs_dst = vsi->sf_bs_buf + sf_bs_off;
 871                        memcpy(sf_bs_dst, sf_bs_src, sf_bs_sz);
 872                } else {
 873                        if ((vsi->sf_frm_cnt > 0) &&
 874                                (vsi->sf_frm_idx < vsi->sf_frm_cnt)) {
 875                                unsigned int idx = vsi->sf_frm_idx;
 876
 877                                memcpy((void *)bs->va,
 878                                        (void *)(bs->va +
 879                                        vsi->sf_frm_offset[idx]),
 880                                        vsi->sf_frm_sz[idx]);
 881                        }
 882                }
 883                memset(inst->seg_id_buf.va, 0, inst->seg_id_buf.size);
 884                ret = vpu_dec_start(&inst->vpu, data, 3);
 885                if (ret) {
 886                        mtk_vcodec_err(inst, "vpu_dec_start failed");
 887                        goto DECODE_ERROR;
 888                }
 889
 890                ret = validate_vsi_array_indexes(inst, vsi);
 891                if (ret) {
 892                        mtk_vcodec_err(inst, "Invalid values from VPU.");
 893                        goto DECODE_ERROR;
 894                }
 895
 896                if (vsi->resolution_changed) {
 897                        if (!vp9_alloc_work_buf(inst)) {
 898                                ret = -EINVAL;
 899                                goto DECODE_ERROR;
 900                        }
 901                }
 902
 903                if (vsi->sf_frm_cnt > 0) {
 904                        cur_fb = &vsi->sf_ref_fb[vsi->sf_next_ref_fb_idx].fb;
 905
 906                        if (vsi->sf_frm_idx < vsi->sf_frm_cnt)
 907                                inst->cur_fb = cur_fb;
 908                        else
 909                                inst->cur_fb = fb;
 910                } else {
 911                        inst->cur_fb = fb;
 912                }
 913
 914                vsi->frm_bufs[vsi->new_fb_idx].buf.fb = inst->cur_fb;
 915                if (!vp9_is_sf_ref_fb(inst, inst->cur_fb))
 916                        vp9_add_to_fb_use_list(inst, inst->cur_fb);
 917
 918                mtk_vcodec_debug(inst, "[#pic %d]", vsi->frm_num);
 919
 920                if (vsi->show_existing_frame)
 921                        mtk_vcodec_debug(inst,
 922                                "drv->new_fb_idx=%d, drv->frm_to_show_idx=%d",
 923                                vsi->new_fb_idx, vsi->frm_to_show_idx);
 924
 925                if (vsi->show_existing_frame && (vsi->frm_to_show_idx <
 926                                        VP9_MAX_FRM_BUF_NUM)) {
 927                        mtk_vcodec_err(inst,
 928                                "Skip Decode drv->new_fb_idx=%d, drv->frm_to_show_idx=%d",
 929                                vsi->new_fb_idx, vsi->frm_to_show_idx);
 930
 931                        vp9_ref_cnt_fb(inst, &vsi->new_fb_idx,
 932                                        vsi->frm_to_show_idx);
 933                        ret = -EINVAL;
 934                        goto DECODE_ERROR;
 935                }
 936
 937                /* VPU assign the buffer pointer in its address space,
 938                 * reassign here
 939                 */
 940                for (i = 0; i < ARRAY_SIZE(vsi->frm_refs); i++) {
 941                        unsigned int idx = vsi->frm_refs[i].idx;
 942
 943                        vsi->frm_refs[i].buf = &vsi->frm_bufs[idx].buf;
 944                }
 945
 946                if (vsi->resolution_changed) {
 947                        *res_chg = true;
 948                        mtk_vcodec_debug(inst, "VDEC_ST_RESOLUTION_CHANGED");
 949
 950                        ret = 0;
 951                        goto DECODE_ERROR;
 952                }
 953
 954                if (vp9_decode_end_proc(inst) != true) {
 955                        mtk_vcodec_err(inst, "vp9_decode_end_proc");
 956                        ret = -EINVAL;
 957                        goto DECODE_ERROR;
 958                }
 959
 960                if (vp9_is_last_sub_frm(inst))
 961                        break;
 962
 963        }
 964        inst->total_frm_cnt++;
 965
 966DECODE_ERROR:
 967        if (ret < 0)
 968                vp9_add_to_fb_free_list(inst, fb);
 969
 970        return ret;
 971}
 972
 973static void get_crop_info(struct vdec_vp9_inst *inst, struct v4l2_rect *cr)
 974{
 975        cr->left = 0;
 976        cr->top = 0;
 977        cr->width = inst->vsi->pic_w;
 978        cr->height = inst->vsi->pic_h;
 979        mtk_vcodec_debug(inst, "get crop info l=%d, t=%d, w=%d, h=%d\n",
 980                         cr->left, cr->top, cr->width, cr->height);
 981}
 982
 983static int vdec_vp9_get_param(unsigned long h_vdec,
 984                enum vdec_get_param_type type, void *out)
 985{
 986        struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
 987        int ret = 0;
 988
 989        switch (type) {
 990        case GET_PARAM_DISP_FRAME_BUFFER:
 991                get_disp_fb(inst, out);
 992                break;
 993        case GET_PARAM_FREE_FRAME_BUFFER:
 994                get_free_fb(inst, out);
 995                break;
 996        case GET_PARAM_PIC_INFO:
 997                get_pic_info(inst, out);
 998                break;
 999        case GET_PARAM_DPB_SIZE:
1000                *((unsigned int *)out) = MAX_VP9_DPB_SIZE;
1001                break;
1002        case GET_PARAM_CROP_INFO:
1003                get_crop_info(inst, out);
1004                break;
1005        default:
1006                mtk_vcodec_err(inst, "not supported param type %d", type);
1007                ret = -EINVAL;
1008                break;
1009        }
1010
1011        return ret;
1012}
1013
1014static struct vdec_common_if vdec_vp9_if = {
1015        .init           = vdec_vp9_init,
1016        .decode         = vdec_vp9_decode,
1017        .get_param      = vdec_vp9_get_param,
1018        .deinit         = vdec_vp9_deinit,
1019};
1020
1021struct vdec_common_if *get_vp9_dec_comm_if(void);
1022
1023struct vdec_common_if *get_vp9_dec_comm_if(void)
1024{
1025        return &vdec_vp9_if;
1026}
1027