cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vdec_vp9_if.c (26266B)


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