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_vp8_if.c (16492B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2016 MediaTek Inc.
      4 * Author: Jungchang Tsao <jungchang.tsao@mediatek.com>
      5 *	   PC Chen <pc.chen@mediatek.com>
      6 */
      7
      8#include <linux/slab.h>
      9#include "../vdec_drv_if.h"
     10#include "../mtk_vcodec_util.h"
     11#include "../mtk_vcodec_dec.h"
     12#include "../mtk_vcodec_intr.h"
     13#include "../vdec_vpu_if.h"
     14#include "../vdec_drv_base.h"
     15
     16/* Decoding picture buffer size (3 reference frames plus current frame) */
     17#define VP8_DPB_SIZE			4
     18
     19/* HW working buffer size (bytes) */
     20#define VP8_WORKING_BUF_SZ		(45 * 4096)
     21
     22/* HW control register address */
     23#define VP8_SEGID_DRAM_ADDR		0x3c
     24#define VP8_HW_VLD_ADDR			0x93C
     25#define VP8_HW_VLD_VALUE		0x940
     26#define VP8_BSASET			0x100
     27#define VP8_BSDSET			0x104
     28#define VP8_RW_CKEN_SET			0x0
     29#define VP8_RW_DCM_CON			0x18
     30#define VP8_WO_VLD_SRST			0x108
     31#define VP8_RW_MISC_SYS_SEL		0x84
     32#define VP8_RW_MISC_SPEC_CON		0xC8
     33#define VP8_WO_VLD_SRST			0x108
     34#define VP8_RW_VP8_CTRL			0xA4
     35#define VP8_RW_MISC_DCM_CON		0xEC
     36#define VP8_RW_MISC_SRST		0xF4
     37#define VP8_RW_MISC_FUNC_CON		0xCC
     38
     39#define VP8_MAX_FRM_BUF_NUM		5
     40#define VP8_MAX_FRM_BUF_NODE_NUM	(VP8_MAX_FRM_BUF_NUM * 2)
     41
     42/* required buffer size (bytes) to store decode information */
     43#define VP8_HW_SEGMENT_DATA_SZ		272
     44#define VP8_HW_SEGMENT_UINT		4
     45
     46#define VP8_DEC_TABLE_PROC_LOOP		96
     47#define VP8_DEC_TABLE_UNIT		3
     48#define VP8_DEC_TABLE_SZ		300
     49#define VP8_DEC_TABLE_OFFSET		2
     50#define VP8_DEC_TABLE_RW_UNIT		4
     51
     52/**
     53 * struct vdec_vp8_dec_info - decode misc information
     54 * @working_buf_dma   : working buffer dma address
     55 * @prev_y_dma        : previous decoded frame buffer Y plane address
     56 * @cur_y_fb_dma      : current plane Y frame buffer dma address
     57 * @cur_c_fb_dma      : current plane C frame buffer dma address
     58 * @bs_dma	      : bitstream dma address
     59 * @bs_sz	      : bitstream size
     60 * @resolution_changed: resolution change flag 1 - changed,  0 - not change
     61 * @show_frame	      : display this frame or not
     62 * @wait_key_frame    : wait key frame coming
     63 */
     64struct vdec_vp8_dec_info {
     65	uint64_t working_buf_dma;
     66	uint64_t prev_y_dma;
     67	uint64_t cur_y_fb_dma;
     68	uint64_t cur_c_fb_dma;
     69	uint64_t bs_dma;
     70	uint32_t bs_sz;
     71	uint32_t resolution_changed;
     72	uint32_t show_frame;
     73	uint32_t wait_key_frame;
     74};
     75
     76/**
     77 * struct vdec_vp8_vsi - VPU shared information
     78 * @dec			: decoding information
     79 * @pic			: picture information
     80 * @dec_table		: decoder coefficient table
     81 * @segment_buf		: segmentation buffer
     82 * @load_data		: flag to indicate reload decode data
     83 */
     84struct vdec_vp8_vsi {
     85	struct vdec_vp8_dec_info dec;
     86	struct vdec_pic_info pic;
     87	uint32_t dec_table[VP8_DEC_TABLE_SZ];
     88	uint32_t segment_buf[VP8_HW_SEGMENT_DATA_SZ][VP8_HW_SEGMENT_UINT];
     89	uint32_t load_data;
     90};
     91
     92/**
     93 * struct vdec_vp8_hw_reg_base - HW register base
     94 * @sys		: base address for sys
     95 * @misc	: base address for misc
     96 * @ld		: base address for ld
     97 * @top		: base address for top
     98 * @cm		: base address for cm
     99 * @hwd		: base address for hwd
    100 * @hwb		: base address for hwb
    101 */
    102struct vdec_vp8_hw_reg_base {
    103	void __iomem *sys;
    104	void __iomem *misc;
    105	void __iomem *ld;
    106	void __iomem *top;
    107	void __iomem *cm;
    108	void __iomem *hwd;
    109	void __iomem *hwb;
    110};
    111
    112/**
    113 * struct vdec_vp8_vpu_inst - VPU instance for VP8 decode
    114 * @wq_hd	: Wait queue to wait VPU message ack
    115 * @signaled	: 1 - Host has received ack message from VPU, 0 - not receive
    116 * @failure	: VPU execution result status 0 - success, others - fail
    117 * @inst_addr	: VPU decoder instance address
    118 */
    119struct vdec_vp8_vpu_inst {
    120	wait_queue_head_t wq_hd;
    121	int signaled;
    122	int failure;
    123	uint32_t inst_addr;
    124};
    125
    126/* frame buffer (fb) list
    127 * [available_fb_node_list]  - decode fb are initialized to 0 and populated in
    128 * [fb_use_list]  - fb is set after decode and is moved to this list
    129 * [fb_free_list] - fb is not needed for reference will be moved from
    130 *		     [fb_use_list] to [fb_free_list] and
    131 *		     once user remove fb from [fb_free_list],
    132 *		     it is circulated back to [available_fb_node_list]
    133 * [fb_disp_list] - fb is set after decode and is moved to this list
    134 *                   once user remove fb from [fb_disp_list] it is
    135 *                   circulated back to [available_fb_node_list]
    136 */
    137
    138/**
    139 * struct vdec_vp8_inst - VP8 decoder instance
    140 * @cur_fb		   : current frame buffer
    141 * @dec_fb		   : decode frame buffer node
    142 * @available_fb_node_list : list to store available frame buffer node
    143 * @fb_use_list		   : list to store frame buffer in use
    144 * @fb_free_list	   : list to store free frame buffer
    145 * @fb_disp_list	   : list to store display ready frame buffer
    146 * @working_buf		   : HW decoder working buffer
    147 * @reg_base		   : HW register base address
    148 * @frm_cnt		   : decode frame count
    149 * @ctx			   : V4L2 context
    150 * @vpu			   : VPU instance for decoder
    151 * @vsi			   : VPU share information
    152 */
    153struct vdec_vp8_inst {
    154	struct vdec_fb *cur_fb;
    155	struct vdec_fb_node dec_fb[VP8_MAX_FRM_BUF_NODE_NUM];
    156	struct list_head available_fb_node_list;
    157	struct list_head fb_use_list;
    158	struct list_head fb_free_list;
    159	struct list_head fb_disp_list;
    160	struct mtk_vcodec_mem working_buf;
    161	struct vdec_vp8_hw_reg_base reg_base;
    162	unsigned int frm_cnt;
    163	struct mtk_vcodec_ctx *ctx;
    164	struct vdec_vpu_inst vpu;
    165	struct vdec_vp8_vsi *vsi;
    166};
    167
    168static void get_hw_reg_base(struct vdec_vp8_inst *inst)
    169{
    170	inst->reg_base.top = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_TOP);
    171	inst->reg_base.cm = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_CM);
    172	inst->reg_base.hwd = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_HWD);
    173	inst->reg_base.sys = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_SYS);
    174	inst->reg_base.misc = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_MISC);
    175	inst->reg_base.ld = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_LD);
    176	inst->reg_base.hwb = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_HWB);
    177}
    178
    179static void write_hw_segmentation_data(struct vdec_vp8_inst *inst)
    180{
    181	int i, j;
    182	u32 seg_id_addr;
    183	u32 val;
    184	void __iomem *cm = inst->reg_base.cm;
    185	struct vdec_vp8_vsi *vsi = inst->vsi;
    186
    187	seg_id_addr = readl(inst->reg_base.top + VP8_SEGID_DRAM_ADDR) >> 4;
    188
    189	for (i = 0; i < ARRAY_SIZE(vsi->segment_buf); i++) {
    190		for (j = ARRAY_SIZE(vsi->segment_buf[i]) - 1; j >= 0; j--) {
    191			val = (1 << 16) + ((seg_id_addr + i) << 2) + j;
    192			writel(val, cm + VP8_HW_VLD_ADDR);
    193
    194			val = vsi->segment_buf[i][j];
    195			writel(val, cm + VP8_HW_VLD_VALUE);
    196		}
    197	}
    198}
    199
    200static void read_hw_segmentation_data(struct vdec_vp8_inst *inst)
    201{
    202	int i, j;
    203	u32 seg_id_addr;
    204	u32 val;
    205	void __iomem *cm = inst->reg_base.cm;
    206	struct vdec_vp8_vsi *vsi = inst->vsi;
    207
    208	seg_id_addr = readl(inst->reg_base.top + VP8_SEGID_DRAM_ADDR) >> 4;
    209
    210	for (i = 0; i < ARRAY_SIZE(vsi->segment_buf); i++) {
    211		for (j = ARRAY_SIZE(vsi->segment_buf[i]) - 1; j >= 0; j--) {
    212			val = ((seg_id_addr + i) << 2) + j;
    213			writel(val, cm + VP8_HW_VLD_ADDR);
    214
    215			val = readl(cm + VP8_HW_VLD_VALUE);
    216			vsi->segment_buf[i][j] = val;
    217		}
    218	}
    219}
    220
    221/* reset HW and enable HW read/write data function */
    222static void enable_hw_rw_function(struct vdec_vp8_inst *inst)
    223{
    224	u32 val = 0;
    225	void __iomem *sys = inst->reg_base.sys;
    226	void __iomem *misc = inst->reg_base.misc;
    227	void __iomem *ld = inst->reg_base.ld;
    228	void __iomem *hwb = inst->reg_base.hwb;
    229	void __iomem *hwd = inst->reg_base.hwd;
    230
    231	writel(0x1, sys + VP8_RW_CKEN_SET);
    232	writel(0x101, ld + VP8_WO_VLD_SRST);
    233	writel(0x101, hwb + VP8_WO_VLD_SRST);
    234
    235	writel(1, sys);
    236	val = readl(misc + VP8_RW_MISC_SRST);
    237	writel((val & 0xFFFFFFFE), misc + VP8_RW_MISC_SRST);
    238
    239	writel(0x1, misc + VP8_RW_MISC_SYS_SEL);
    240	writel(0x17F, misc + VP8_RW_MISC_SPEC_CON);
    241	writel(0x71201100, misc + VP8_RW_MISC_FUNC_CON);
    242	writel(0x0, ld + VP8_WO_VLD_SRST);
    243	writel(0x0, hwb + VP8_WO_VLD_SRST);
    244	writel(0x1, sys + VP8_RW_DCM_CON);
    245	writel(0x1, misc + VP8_RW_MISC_DCM_CON);
    246	writel(0x1, hwd + VP8_RW_VP8_CTRL);
    247}
    248
    249static void store_dec_table(struct vdec_vp8_inst *inst)
    250{
    251	int i, j;
    252	u32 addr = 0, val = 0;
    253	void __iomem *hwd = inst->reg_base.hwd;
    254	u32 *p = &inst->vsi->dec_table[VP8_DEC_TABLE_OFFSET];
    255
    256	for (i = 0; i < VP8_DEC_TABLE_PROC_LOOP; i++) {
    257		writel(addr, hwd + VP8_BSASET);
    258		for (j = 0; j < VP8_DEC_TABLE_UNIT ; j++) {
    259			val = *p++;
    260			writel(val, hwd + VP8_BSDSET);
    261		}
    262		addr += VP8_DEC_TABLE_RW_UNIT;
    263	}
    264}
    265
    266static void load_dec_table(struct vdec_vp8_inst *inst)
    267{
    268	int i;
    269	u32 addr = 0;
    270	u32 *p = &inst->vsi->dec_table[VP8_DEC_TABLE_OFFSET];
    271	void __iomem *hwd = inst->reg_base.hwd;
    272
    273	for (i = 0; i < VP8_DEC_TABLE_PROC_LOOP; i++) {
    274		writel(addr, hwd + VP8_BSASET);
    275		/* read total 11 bytes */
    276		*p++ = readl(hwd + VP8_BSDSET);
    277		*p++ = readl(hwd + VP8_BSDSET);
    278		*p++ = readl(hwd + VP8_BSDSET) & 0xFFFFFF;
    279		addr += VP8_DEC_TABLE_RW_UNIT;
    280	}
    281}
    282
    283static void get_pic_info(struct vdec_vp8_inst *inst, struct vdec_pic_info *pic)
    284{
    285	*pic = inst->vsi->pic;
    286
    287	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
    288			 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
    289	mtk_vcodec_debug(inst, "fb size: Y(%d), C(%d)",
    290			 pic->fb_sz[0], pic->fb_sz[1]);
    291}
    292
    293static void vp8_dec_finish(struct vdec_vp8_inst *inst)
    294{
    295	struct vdec_fb_node *node;
    296	uint64_t prev_y_dma = inst->vsi->dec.prev_y_dma;
    297
    298	mtk_vcodec_debug(inst, "prev fb base dma=%llx", prev_y_dma);
    299
    300	/* put last decode ok frame to fb_free_list */
    301	if (prev_y_dma != 0) {
    302		list_for_each_entry(node, &inst->fb_use_list, list) {
    303			struct vdec_fb *fb = (struct vdec_fb *)node->fb;
    304
    305			if (prev_y_dma == (uint64_t)fb->base_y.dma_addr) {
    306				list_move_tail(&node->list,
    307					       &inst->fb_free_list);
    308				break;
    309			}
    310		}
    311	}
    312
    313	/* available_fb_node_list -> fb_use_list */
    314	node = list_first_entry(&inst->available_fb_node_list,
    315				struct vdec_fb_node, list);
    316	node->fb = inst->cur_fb;
    317	list_move_tail(&node->list, &inst->fb_use_list);
    318
    319	/* available_fb_node_list -> fb_disp_list */
    320	if (inst->vsi->dec.show_frame) {
    321		node = list_first_entry(&inst->available_fb_node_list,
    322					struct vdec_fb_node, list);
    323		node->fb = inst->cur_fb;
    324		list_move_tail(&node->list, &inst->fb_disp_list);
    325	}
    326}
    327
    328static void move_fb_list_use_to_free(struct vdec_vp8_inst *inst)
    329{
    330	struct vdec_fb_node *node, *tmp;
    331
    332	list_for_each_entry_safe(node, tmp, &inst->fb_use_list, list)
    333		list_move_tail(&node->list, &inst->fb_free_list);
    334}
    335
    336static void init_list(struct vdec_vp8_inst *inst)
    337{
    338	int i;
    339
    340	INIT_LIST_HEAD(&inst->available_fb_node_list);
    341	INIT_LIST_HEAD(&inst->fb_use_list);
    342	INIT_LIST_HEAD(&inst->fb_free_list);
    343	INIT_LIST_HEAD(&inst->fb_disp_list);
    344
    345	for (i = 0; i < ARRAY_SIZE(inst->dec_fb); i++) {
    346		INIT_LIST_HEAD(&inst->dec_fb[i].list);
    347		inst->dec_fb[i].fb = NULL;
    348		list_add_tail(&inst->dec_fb[i].list,
    349			      &inst->available_fb_node_list);
    350	}
    351}
    352
    353static void add_fb_to_free_list(struct vdec_vp8_inst *inst, void *fb)
    354{
    355	struct vdec_fb_node *node;
    356
    357	if (fb) {
    358		node = list_first_entry(&inst->available_fb_node_list,
    359					struct vdec_fb_node, list);
    360		node->fb = fb;
    361		list_move_tail(&node->list, &inst->fb_free_list);
    362	}
    363}
    364
    365static int alloc_working_buf(struct vdec_vp8_inst *inst)
    366{
    367	int err;
    368	struct mtk_vcodec_mem *mem = &inst->working_buf;
    369
    370	mem->size = VP8_WORKING_BUF_SZ;
    371	err = mtk_vcodec_mem_alloc(inst->ctx, mem);
    372	if (err) {
    373		mtk_vcodec_err(inst, "Cannot allocate working buffer");
    374		return err;
    375	}
    376
    377	inst->vsi->dec.working_buf_dma = (uint64_t)mem->dma_addr;
    378	return 0;
    379}
    380
    381static void free_working_buf(struct vdec_vp8_inst *inst)
    382{
    383	struct mtk_vcodec_mem *mem = &inst->working_buf;
    384
    385	if (mem->va)
    386		mtk_vcodec_mem_free(inst->ctx, mem);
    387
    388	inst->vsi->dec.working_buf_dma = 0;
    389}
    390
    391static int vdec_vp8_init(struct mtk_vcodec_ctx *ctx)
    392{
    393	struct vdec_vp8_inst *inst;
    394	int err;
    395
    396	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
    397	if (!inst)
    398		return  -ENOMEM;
    399
    400	inst->ctx = ctx;
    401
    402	inst->vpu.id = IPI_VDEC_VP8;
    403	inst->vpu.ctx = ctx;
    404
    405	err = vpu_dec_init(&inst->vpu);
    406	if (err) {
    407		mtk_vcodec_err(inst, "vdec_vp8 init err=%d", err);
    408		goto error_free_inst;
    409	}
    410
    411	inst->vsi = (struct vdec_vp8_vsi *)inst->vpu.vsi;
    412	init_list(inst);
    413	err = alloc_working_buf(inst);
    414	if (err)
    415		goto error_deinit;
    416
    417	get_hw_reg_base(inst);
    418	mtk_vcodec_debug(inst, "VP8 Instance >> %p", inst);
    419
    420	ctx->drv_handle = inst;
    421	return 0;
    422
    423error_deinit:
    424	vpu_dec_deinit(&inst->vpu);
    425error_free_inst:
    426	kfree(inst);
    427	return err;
    428}
    429
    430static int vdec_vp8_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
    431			   struct vdec_fb *fb, bool *res_chg)
    432{
    433	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
    434	struct vdec_vp8_dec_info *dec = &inst->vsi->dec;
    435	struct vdec_vpu_inst *vpu = &inst->vpu;
    436	unsigned char *bs_va;
    437	unsigned int data;
    438	int err = 0;
    439	uint64_t y_fb_dma;
    440	uint64_t c_fb_dma;
    441
    442	/* bs NULL means flush decoder */
    443	if (bs == NULL) {
    444		move_fb_list_use_to_free(inst);
    445		return vpu_dec_reset(vpu);
    446	}
    447
    448	y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
    449	c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
    450
    451	mtk_vcodec_debug(inst, "+ [%d] FB y_dma=%llx c_dma=%llx fb=%p",
    452			 inst->frm_cnt, y_fb_dma, c_fb_dma, fb);
    453
    454	inst->cur_fb = fb;
    455	dec->bs_dma = (unsigned long)bs->dma_addr;
    456	dec->bs_sz = bs->size;
    457	dec->cur_y_fb_dma = y_fb_dma;
    458	dec->cur_c_fb_dma = c_fb_dma;
    459
    460	mtk_vcodec_debug(inst, "\n + FRAME[%d] +\n", inst->frm_cnt);
    461
    462	write_hw_segmentation_data(inst);
    463	enable_hw_rw_function(inst);
    464	store_dec_table(inst);
    465
    466	bs_va = (unsigned char *)bs->va;
    467
    468	/* retrieve width/hight and scale info from header */
    469	data = (*(bs_va + 9) << 24) | (*(bs_va + 8) << 16) |
    470	       (*(bs_va + 7) << 8) | *(bs_va + 6);
    471	err = vpu_dec_start(vpu, &data, 1);
    472	if (err) {
    473		add_fb_to_free_list(inst, fb);
    474		if (dec->wait_key_frame) {
    475			mtk_vcodec_debug(inst, "wait key frame !");
    476			return 0;
    477		}
    478
    479		goto error;
    480	}
    481
    482	if (dec->resolution_changed) {
    483		mtk_vcodec_debug(inst, "- resolution_changed -");
    484		*res_chg = true;
    485		add_fb_to_free_list(inst, fb);
    486		return 0;
    487	}
    488
    489	/* wait decoder done interrupt */
    490	mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
    491				     WAIT_INTR_TIMEOUT_MS, 0);
    492
    493	if (inst->vsi->load_data)
    494		load_dec_table(inst);
    495
    496	vp8_dec_finish(inst);
    497	read_hw_segmentation_data(inst);
    498
    499	err = vpu_dec_end(vpu);
    500	if (err)
    501		goto error;
    502
    503	mtk_vcodec_debug(inst, "\n - FRAME[%d] - show=%d\n", inst->frm_cnt,
    504			 dec->show_frame);
    505	inst->frm_cnt++;
    506	*res_chg = false;
    507	return 0;
    508
    509error:
    510	mtk_vcodec_err(inst, "\n - FRAME[%d] - err=%d\n", inst->frm_cnt, err);
    511	return err;
    512}
    513
    514static void get_disp_fb(struct vdec_vp8_inst *inst, struct vdec_fb **out_fb)
    515{
    516	struct vdec_fb_node *node;
    517	struct vdec_fb *fb;
    518
    519	node = list_first_entry_or_null(&inst->fb_disp_list,
    520					struct vdec_fb_node, list);
    521	if (node) {
    522		list_move_tail(&node->list, &inst->available_fb_node_list);
    523		fb = (struct vdec_fb *)node->fb;
    524		fb->status |= FB_ST_DISPLAY;
    525		mtk_vcodec_debug(inst, "[FB] get disp fb %p st=%d",
    526				 node->fb, fb->status);
    527	} else {
    528		fb = NULL;
    529		mtk_vcodec_debug(inst, "[FB] there is no disp fb");
    530	}
    531
    532	*out_fb = fb;
    533}
    534
    535static void get_free_fb(struct vdec_vp8_inst *inst, struct vdec_fb **out_fb)
    536{
    537	struct vdec_fb_node *node;
    538	struct vdec_fb *fb;
    539
    540	node = list_first_entry_or_null(&inst->fb_free_list,
    541					struct vdec_fb_node, list);
    542	if (node) {
    543		list_move_tail(&node->list, &inst->available_fb_node_list);
    544		fb = (struct vdec_fb *)node->fb;
    545		fb->status |= FB_ST_FREE;
    546		mtk_vcodec_debug(inst, "[FB] get free fb %p st=%d",
    547				 node->fb, fb->status);
    548	} else {
    549		fb = NULL;
    550		mtk_vcodec_debug(inst, "[FB] there is no free fb");
    551	}
    552
    553	*out_fb = fb;
    554}
    555
    556static void get_crop_info(struct vdec_vp8_inst *inst, struct v4l2_rect *cr)
    557{
    558	cr->left = 0;
    559	cr->top = 0;
    560	cr->width = inst->vsi->pic.pic_w;
    561	cr->height = inst->vsi->pic.pic_h;
    562	mtk_vcodec_debug(inst, "get crop info l=%d, t=%d, w=%d, h=%d",
    563			 cr->left, cr->top, cr->width, cr->height);
    564}
    565
    566static int vdec_vp8_get_param(void *h_vdec, enum vdec_get_param_type type,
    567			      void *out)
    568{
    569	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
    570
    571	switch (type) {
    572	case GET_PARAM_DISP_FRAME_BUFFER:
    573		get_disp_fb(inst, out);
    574		break;
    575
    576	case GET_PARAM_FREE_FRAME_BUFFER:
    577		get_free_fb(inst, out);
    578		break;
    579
    580	case GET_PARAM_PIC_INFO:
    581		get_pic_info(inst, out);
    582		break;
    583
    584	case GET_PARAM_CROP_INFO:
    585		get_crop_info(inst, out);
    586		break;
    587
    588	case GET_PARAM_DPB_SIZE:
    589		*((unsigned int *)out) = VP8_DPB_SIZE;
    590		break;
    591
    592	default:
    593		mtk_vcodec_err(inst, "invalid get parameter type=%d", type);
    594		return -EINVAL;
    595	}
    596
    597	return 0;
    598}
    599
    600static void vdec_vp8_deinit(void *h_vdec)
    601{
    602	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
    603
    604	mtk_vcodec_debug_enter(inst);
    605
    606	vpu_dec_deinit(&inst->vpu);
    607	free_working_buf(inst);
    608	kfree(inst);
    609}
    610
    611const struct vdec_common_if vdec_vp8_if = {
    612	.init		= vdec_vp8_init,
    613	.decode		= vdec_vp8_decode,
    614	.get_param	= vdec_vp8_get_param,
    615	.deinit		= vdec_vp8_deinit,
    616};