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_h264_if.c (12851B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2016 MediaTek Inc.
      4 * Author: PC Chen <pc.chen@mediatek.com>
      5 */
      6
      7#include <linux/module.h>
      8#include <linux/slab.h>
      9
     10#include "../vdec_drv_if.h"
     11#include "../mtk_vcodec_util.h"
     12#include "../mtk_vcodec_dec.h"
     13#include "../mtk_vcodec_intr.h"
     14#include "../vdec_vpu_if.h"
     15#include "../vdec_drv_base.h"
     16
     17#define NAL_NON_IDR_SLICE			0x01
     18#define NAL_IDR_SLICE				0x05
     19#define NAL_H264_PPS				0x08
     20#define NAL_TYPE(value)				((value) & 0x1F)
     21
     22#define BUF_PREDICTION_SZ			(32 * 1024)
     23
     24#define MB_UNIT_LEN				16
     25
     26/* motion vector size (bytes) for every macro block */
     27#define HW_MB_STORE_SZ				64
     28
     29#define H264_MAX_FB_NUM				17
     30#define HDR_PARSING_BUF_SZ			1024
     31
     32#define DEC_ERR_RET(ret)			((ret) >> 16)
     33#define H264_ERR_NOT_VALID			3
     34
     35/**
     36 * struct h264_fb - h264 decode frame buffer information
     37 * @vdec_fb_va  : virtual address of struct vdec_fb
     38 * @y_fb_dma    : dma address of Y frame buffer (luma)
     39 * @c_fb_dma    : dma address of C frame buffer (chroma)
     40 * @poc         : picture order count of frame buffer
     41 * @reserved    : for 8 bytes alignment
     42 */
     43struct h264_fb {
     44	uint64_t vdec_fb_va;
     45	uint64_t y_fb_dma;
     46	uint64_t c_fb_dma;
     47	int32_t poc;
     48	uint32_t reserved;
     49};
     50
     51/**
     52 * struct h264_ring_fb_list - ring frame buffer list
     53 * @fb_list   : frame buffer array
     54 * @read_idx  : read index
     55 * @write_idx : write index
     56 * @count     : buffer count in list
     57 * @reserved  : for 8 bytes alignment
     58 */
     59struct h264_ring_fb_list {
     60	struct h264_fb fb_list[H264_MAX_FB_NUM];
     61	unsigned int read_idx;
     62	unsigned int write_idx;
     63	unsigned int count;
     64	unsigned int reserved;
     65};
     66
     67/**
     68 * struct vdec_h264_dec_info - decode information
     69 * @dpb_sz		: decoding picture buffer size
     70 * @resolution_changed  : resolution change happen
     71 * @realloc_mv_buf	: flag to notify driver to re-allocate mv buffer
     72 * @reserved		: for 8 bytes alignment
     73 * @bs_dma		: Input bit-stream buffer dma address
     74 * @y_fb_dma		: Y frame buffer dma address
     75 * @c_fb_dma		: C frame buffer dma address
     76 * @vdec_fb_va		: VDEC frame buffer struct virtual address
     77 */
     78struct vdec_h264_dec_info {
     79	uint32_t dpb_sz;
     80	uint32_t resolution_changed;
     81	uint32_t realloc_mv_buf;
     82	uint32_t reserved;
     83	uint64_t bs_dma;
     84	uint64_t y_fb_dma;
     85	uint64_t c_fb_dma;
     86	uint64_t vdec_fb_va;
     87};
     88
     89/**
     90 * struct vdec_h264_vsi - shared memory for decode information exchange
     91 *                        between VPU and Host.
     92 *                        The memory is allocated by VPU then mapping to Host
     93 *                        in vpu_dec_init() and freed in vpu_dec_deinit()
     94 *                        by VPU.
     95 *                        AP-W/R : AP is writer/reader on this item
     96 *                        VPU-W/R: VPU is write/reader on this item
     97 * @hdr_buf      : Header parsing buffer (AP-W, VPU-R)
     98 * @pred_buf_dma : HW working predication buffer dma address (AP-W, VPU-R)
     99 * @mv_buf_dma   : HW working motion vector buffer dma address (AP-W, VPU-R)
    100 * @list_free    : free frame buffer ring list (AP-W/R, VPU-W)
    101 * @list_disp    : display frame buffer ring list (AP-R, VPU-W)
    102 * @dec          : decode information (AP-R, VPU-W)
    103 * @pic          : picture information (AP-R, VPU-W)
    104 * @crop         : crop information (AP-R, VPU-W)
    105 */
    106struct vdec_h264_vsi {
    107	unsigned char hdr_buf[HDR_PARSING_BUF_SZ];
    108	uint64_t pred_buf_dma;
    109	uint64_t mv_buf_dma[H264_MAX_FB_NUM];
    110	struct h264_ring_fb_list list_free;
    111	struct h264_ring_fb_list list_disp;
    112	struct vdec_h264_dec_info dec;
    113	struct vdec_pic_info pic;
    114	struct v4l2_rect crop;
    115};
    116
    117/**
    118 * struct vdec_h264_inst - h264 decoder instance
    119 * @num_nalu : how many nalus be decoded
    120 * @ctx      : point to mtk_vcodec_ctx
    121 * @pred_buf : HW working predication buffer
    122 * @mv_buf   : HW working motion vector buffer
    123 * @vpu      : VPU instance
    124 * @vsi      : VPU shared information
    125 */
    126struct vdec_h264_inst {
    127	unsigned int num_nalu;
    128	struct mtk_vcodec_ctx *ctx;
    129	struct mtk_vcodec_mem pred_buf;
    130	struct mtk_vcodec_mem mv_buf[H264_MAX_FB_NUM];
    131	struct vdec_vpu_inst vpu;
    132	struct vdec_h264_vsi *vsi;
    133};
    134
    135static unsigned int get_mv_buf_size(unsigned int width, unsigned int height)
    136{
    137	return HW_MB_STORE_SZ * (width/MB_UNIT_LEN) * (height/MB_UNIT_LEN);
    138}
    139
    140static int allocate_predication_buf(struct vdec_h264_inst *inst)
    141{
    142	int err = 0;
    143
    144	inst->pred_buf.size = BUF_PREDICTION_SZ;
    145	err = mtk_vcodec_mem_alloc(inst->ctx, &inst->pred_buf);
    146	if (err) {
    147		mtk_vcodec_err(inst, "failed to allocate ppl buf");
    148		return err;
    149	}
    150
    151	inst->vsi->pred_buf_dma = inst->pred_buf.dma_addr;
    152	return 0;
    153}
    154
    155static void free_predication_buf(struct vdec_h264_inst *inst)
    156{
    157	struct mtk_vcodec_mem *mem = NULL;
    158
    159	mtk_vcodec_debug_enter(inst);
    160
    161	inst->vsi->pred_buf_dma = 0;
    162	mem = &inst->pred_buf;
    163	if (mem->va)
    164		mtk_vcodec_mem_free(inst->ctx, mem);
    165}
    166
    167static int alloc_mv_buf(struct vdec_h264_inst *inst, struct vdec_pic_info *pic)
    168{
    169	int i;
    170	int err;
    171	struct mtk_vcodec_mem *mem = NULL;
    172	unsigned int buf_sz = get_mv_buf_size(pic->buf_w, pic->buf_h);
    173
    174	for (i = 0; i < H264_MAX_FB_NUM; i++) {
    175		mem = &inst->mv_buf[i];
    176		if (mem->va)
    177			mtk_vcodec_mem_free(inst->ctx, mem);
    178		mem->size = buf_sz;
    179		err = mtk_vcodec_mem_alloc(inst->ctx, mem);
    180		if (err) {
    181			mtk_vcodec_err(inst, "failed to allocate mv buf");
    182			return err;
    183		}
    184		inst->vsi->mv_buf_dma[i] = mem->dma_addr;
    185	}
    186
    187	return 0;
    188}
    189
    190static void free_mv_buf(struct vdec_h264_inst *inst)
    191{
    192	int i;
    193	struct mtk_vcodec_mem *mem = NULL;
    194
    195	for (i = 0; i < H264_MAX_FB_NUM; i++) {
    196		inst->vsi->mv_buf_dma[i] = 0;
    197		mem = &inst->mv_buf[i];
    198		if (mem->va)
    199			mtk_vcodec_mem_free(inst->ctx, mem);
    200	}
    201}
    202
    203static int check_list_validity(struct vdec_h264_inst *inst, bool disp_list)
    204{
    205	struct h264_ring_fb_list *list;
    206
    207	list = disp_list ? &inst->vsi->list_disp : &inst->vsi->list_free;
    208
    209	if (list->count > H264_MAX_FB_NUM ||
    210	    list->read_idx >= H264_MAX_FB_NUM ||
    211	    list->write_idx >= H264_MAX_FB_NUM) {
    212		mtk_vcodec_err(inst, "%s list err: cnt=%d r_idx=%d w_idx=%d",
    213			       disp_list ? "disp" : "free", list->count,
    214			       list->read_idx, list->write_idx);
    215		return -EINVAL;
    216	}
    217
    218	return 0;
    219}
    220
    221static void put_fb_to_free(struct vdec_h264_inst *inst, struct vdec_fb *fb)
    222{
    223	struct h264_ring_fb_list *list;
    224
    225	if (fb) {
    226		if (check_list_validity(inst, false))
    227			return;
    228
    229		list = &inst->vsi->list_free;
    230		if (list->count == H264_MAX_FB_NUM) {
    231			mtk_vcodec_err(inst, "[FB] put fb free_list full");
    232			return;
    233		}
    234
    235		mtk_vcodec_debug(inst, "[FB] put fb into free_list @(%p, %llx)",
    236				 fb->base_y.va, (u64)fb->base_y.dma_addr);
    237
    238		list->fb_list[list->write_idx].vdec_fb_va = (u64)(uintptr_t)fb;
    239		list->write_idx = (list->write_idx == H264_MAX_FB_NUM - 1) ?
    240				  0 : list->write_idx + 1;
    241		list->count++;
    242	}
    243}
    244
    245static void get_pic_info(struct vdec_h264_inst *inst,
    246			 struct vdec_pic_info *pic)
    247{
    248	*pic = inst->vsi->pic;
    249	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
    250			 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
    251	mtk_vcodec_debug(inst, "fb size: Y(%d), C(%d)",
    252			 pic->fb_sz[0], pic->fb_sz[1]);
    253}
    254
    255static void get_crop_info(struct vdec_h264_inst *inst, struct v4l2_rect *cr)
    256{
    257	cr->left = inst->vsi->crop.left;
    258	cr->top = inst->vsi->crop.top;
    259	cr->width = inst->vsi->crop.width;
    260	cr->height = inst->vsi->crop.height;
    261
    262	mtk_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d",
    263			 cr->left, cr->top, cr->width, cr->height);
    264}
    265
    266static void get_dpb_size(struct vdec_h264_inst *inst, unsigned int *dpb_sz)
    267{
    268	*dpb_sz = inst->vsi->dec.dpb_sz;
    269	mtk_vcodec_debug(inst, "sz=%d", *dpb_sz);
    270}
    271
    272static int vdec_h264_init(struct mtk_vcodec_ctx *ctx)
    273{
    274	struct vdec_h264_inst *inst = NULL;
    275	int err;
    276
    277	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
    278	if (!inst)
    279		return -ENOMEM;
    280
    281	inst->ctx = ctx;
    282
    283	inst->vpu.id = IPI_VDEC_H264;
    284	inst->vpu.ctx = ctx;
    285
    286	err = vpu_dec_init(&inst->vpu);
    287	if (err) {
    288		mtk_vcodec_err(inst, "vdec_h264 init err=%d", err);
    289		goto error_free_inst;
    290	}
    291
    292	inst->vsi = (struct vdec_h264_vsi *)inst->vpu.vsi;
    293	err = allocate_predication_buf(inst);
    294	if (err)
    295		goto error_deinit;
    296
    297	mtk_vcodec_debug(inst, "H264 Instance >> %p", inst);
    298
    299	ctx->drv_handle = inst;
    300	return 0;
    301
    302error_deinit:
    303	vpu_dec_deinit(&inst->vpu);
    304
    305error_free_inst:
    306	kfree(inst);
    307	return err;
    308}
    309
    310static void vdec_h264_deinit(void *h_vdec)
    311{
    312	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
    313
    314	mtk_vcodec_debug_enter(inst);
    315
    316	vpu_dec_deinit(&inst->vpu);
    317	free_predication_buf(inst);
    318	free_mv_buf(inst);
    319
    320	kfree(inst);
    321}
    322
    323static int find_start_code(unsigned char *data, unsigned int data_sz)
    324{
    325	if (data_sz > 3 && data[0] == 0 && data[1] == 0 && data[2] == 1)
    326		return 3;
    327
    328	if (data_sz > 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 &&
    329	    data[3] == 1)
    330		return 4;
    331
    332	return -1;
    333}
    334
    335static int vdec_h264_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
    336			    struct vdec_fb *fb, bool *res_chg)
    337{
    338	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
    339	struct vdec_vpu_inst *vpu = &inst->vpu;
    340	int nal_start_idx = 0;
    341	int err = 0;
    342	unsigned int nal_start;
    343	unsigned int nal_type;
    344	unsigned char *buf;
    345	unsigned int buf_sz;
    346	unsigned int data[2];
    347	uint64_t vdec_fb_va = (u64)(uintptr_t)fb;
    348	uint64_t y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
    349	uint64_t c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
    350
    351	mtk_vcodec_debug(inst, "+ [%d] FB y_dma=%llx c_dma=%llx va=%p",
    352			 ++inst->num_nalu, y_fb_dma, c_fb_dma, fb);
    353
    354	/* bs NULL means flush decoder */
    355	if (bs == NULL)
    356		return vpu_dec_reset(vpu);
    357
    358	buf = (unsigned char *)bs->va;
    359	buf_sz = bs->size;
    360	nal_start_idx = find_start_code(buf, buf_sz);
    361	if (nal_start_idx < 0) {
    362		mtk_vcodec_err(inst, "invalid nal start code");
    363		err = -EIO;
    364		goto err_free_fb_out;
    365	}
    366
    367	nal_start = buf[nal_start_idx];
    368	nal_type = NAL_TYPE(buf[nal_start_idx]);
    369	mtk_vcodec_debug(inst, "\n + NALU[%d] type %d +\n", inst->num_nalu,
    370			 nal_type);
    371
    372	if (nal_type == NAL_H264_PPS) {
    373		buf_sz -= nal_start_idx;
    374		if (buf_sz > HDR_PARSING_BUF_SZ) {
    375			err = -EILSEQ;
    376			goto err_free_fb_out;
    377		}
    378		memcpy(inst->vsi->hdr_buf, buf + nal_start_idx, buf_sz);
    379	}
    380
    381	inst->vsi->dec.bs_dma = (uint64_t)bs->dma_addr;
    382	inst->vsi->dec.y_fb_dma = y_fb_dma;
    383	inst->vsi->dec.c_fb_dma = c_fb_dma;
    384	inst->vsi->dec.vdec_fb_va = vdec_fb_va;
    385
    386	data[0] = buf_sz;
    387	data[1] = nal_start;
    388	err = vpu_dec_start(vpu, data, 2);
    389	if (err) {
    390		if (err > 0 && (DEC_ERR_RET(err) == H264_ERR_NOT_VALID)) {
    391			mtk_vcodec_err(inst, "- error bitstream - err = %d -",
    392				       err);
    393			err = -EIO;
    394		}
    395		goto err_free_fb_out;
    396	}
    397
    398	*res_chg = inst->vsi->dec.resolution_changed;
    399	if (*res_chg) {
    400		struct vdec_pic_info pic;
    401
    402		mtk_vcodec_debug(inst, "- resolution changed -");
    403		get_pic_info(inst, &pic);
    404
    405		if (inst->vsi->dec.realloc_mv_buf) {
    406			err = alloc_mv_buf(inst, &pic);
    407			if (err)
    408				goto err_free_fb_out;
    409		}
    410	}
    411
    412	if (nal_type == NAL_NON_IDR_SLICE || nal_type == NAL_IDR_SLICE) {
    413		/* wait decoder done interrupt */
    414		err = mtk_vcodec_wait_for_done_ctx(inst->ctx,
    415						   MTK_INST_IRQ_RECEIVED,
    416						   WAIT_INTR_TIMEOUT_MS, 0);
    417		if (err)
    418			goto err_free_fb_out;
    419
    420		vpu_dec_end(vpu);
    421	}
    422
    423	mtk_vcodec_debug(inst, "\n - NALU[%d] type=%d -\n", inst->num_nalu,
    424			 nal_type);
    425	return 0;
    426
    427err_free_fb_out:
    428	put_fb_to_free(inst, fb);
    429	mtk_vcodec_err(inst, "\n - NALU[%d] err=%d -\n", inst->num_nalu, err);
    430	return err;
    431}
    432
    433static void vdec_h264_get_fb(struct vdec_h264_inst *inst,
    434			     struct h264_ring_fb_list *list,
    435			     bool disp_list, struct vdec_fb **out_fb)
    436{
    437	struct vdec_fb *fb;
    438
    439	if (check_list_validity(inst, disp_list))
    440		return;
    441
    442	if (list->count == 0) {
    443		mtk_vcodec_debug(inst, "[FB] there is no %s fb",
    444				 disp_list ? "disp" : "free");
    445		*out_fb = NULL;
    446		return;
    447	}
    448
    449	fb = (struct vdec_fb *)
    450		(uintptr_t)list->fb_list[list->read_idx].vdec_fb_va;
    451	fb->status |= (disp_list ? FB_ST_DISPLAY : FB_ST_FREE);
    452
    453	*out_fb = fb;
    454	mtk_vcodec_debug(inst, "[FB] get %s fb st=%d poc=%d %llx",
    455			 disp_list ? "disp" : "free",
    456			 fb->status, list->fb_list[list->read_idx].poc,
    457			 list->fb_list[list->read_idx].vdec_fb_va);
    458
    459	list->read_idx = (list->read_idx == H264_MAX_FB_NUM - 1) ?
    460			 0 : list->read_idx + 1;
    461	list->count--;
    462}
    463
    464static int vdec_h264_get_param(void *h_vdec, enum vdec_get_param_type type,
    465			       void *out)
    466{
    467	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
    468
    469	switch (type) {
    470	case GET_PARAM_DISP_FRAME_BUFFER:
    471		vdec_h264_get_fb(inst, &inst->vsi->list_disp, true, out);
    472		break;
    473
    474	case GET_PARAM_FREE_FRAME_BUFFER:
    475		vdec_h264_get_fb(inst, &inst->vsi->list_free, false, out);
    476		break;
    477
    478	case GET_PARAM_PIC_INFO:
    479		get_pic_info(inst, out);
    480		break;
    481
    482	case GET_PARAM_DPB_SIZE:
    483		get_dpb_size(inst, out);
    484		break;
    485
    486	case GET_PARAM_CROP_INFO:
    487		get_crop_info(inst, out);
    488		break;
    489
    490	default:
    491		mtk_vcodec_err(inst, "invalid get parameter type=%d", type);
    492		return -EINVAL;
    493	}
    494
    495	return 0;
    496}
    497
    498const struct vdec_common_if vdec_h264_if = {
    499	.init		= vdec_h264_init,
    500	.decode		= vdec_h264_decode,
    501	.get_param	= vdec_h264_get_param,
    502	.deinit		= vdec_h264_deinit,
    503};