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

venc_h264_if.c (19343B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2016 MediaTek Inc.
      4 * Author: Jungchang Tsao <jungchang.tsao@mediatek.com>
      5 *         Daniel Hsiao <daniel.hsiao@mediatek.com>
      6 *         PoChun Lin <pochun.lin@mediatek.com>
      7 */
      8
      9#include <linux/interrupt.h>
     10#include <linux/kernel.h>
     11#include <linux/slab.h>
     12
     13#include "../mtk_vcodec_drv.h"
     14#include "../mtk_vcodec_util.h"
     15#include "../mtk_vcodec_intr.h"
     16#include "../mtk_vcodec_enc.h"
     17#include "../mtk_vcodec_enc_pm.h"
     18#include "../venc_drv_base.h"
     19#include "../venc_ipi_msg.h"
     20#include "../venc_vpu_if.h"
     21
     22static const char h264_filler_marker[] = {0x0, 0x0, 0x0, 0x1, 0xc};
     23
     24#define H264_FILLER_MARKER_SIZE ARRAY_SIZE(h264_filler_marker)
     25#define VENC_PIC_BITSTREAM_BYTE_CNT 0x0098
     26
     27/*
     28 * enum venc_h264_frame_type - h264 encoder output bitstream frame type
     29 */
     30enum venc_h264_frame_type {
     31	VENC_H264_IDR_FRM,
     32	VENC_H264_I_FRM,
     33	VENC_H264_P_FRM,
     34	VENC_H264_B_FRM,
     35};
     36
     37/*
     38 * enum venc_h264_vpu_work_buf - h264 encoder buffer index
     39 */
     40enum venc_h264_vpu_work_buf {
     41	VENC_H264_VPU_WORK_BUF_RC_INFO,
     42	VENC_H264_VPU_WORK_BUF_RC_CODE,
     43	VENC_H264_VPU_WORK_BUF_REC_LUMA,
     44	VENC_H264_VPU_WORK_BUF_REC_CHROMA,
     45	VENC_H264_VPU_WORK_BUF_REF_LUMA,
     46	VENC_H264_VPU_WORK_BUF_REF_CHROMA,
     47	VENC_H264_VPU_WORK_BUF_MV_INFO_1,
     48	VENC_H264_VPU_WORK_BUF_MV_INFO_2,
     49	VENC_H264_VPU_WORK_BUF_SKIP_FRAME,
     50	VENC_H264_VPU_WORK_BUF_MAX,
     51};
     52
     53/*
     54 * enum venc_h264_bs_mode - for bs_mode argument in h264_enc_vpu_encode
     55 */
     56enum venc_h264_bs_mode {
     57	H264_BS_MODE_SPS,
     58	H264_BS_MODE_PPS,
     59	H264_BS_MODE_FRAME,
     60};
     61
     62/*
     63 * struct venc_h264_vpu_config - Structure for h264 encoder configuration
     64 *                               AP-W/R : AP is writer/reader on this item
     65 *                               VPU-W/R: VPU is write/reader on this item
     66 * @input_fourcc: input fourcc
     67 * @bitrate: target bitrate (in bps)
     68 * @pic_w: picture width. Picture size is visible stream resolution, in pixels,
     69 *         to be used for display purposes; must be smaller or equal to buffer
     70 *         size.
     71 * @pic_h: picture height
     72 * @buf_w: buffer width. Buffer size is stream resolution in pixels aligned to
     73 *         hardware requirements.
     74 * @buf_h: buffer height
     75 * @gop_size: group of picture size (idr frame)
     76 * @intra_period: intra frame period
     77 * @framerate: frame rate in fps
     78 * @profile: as specified in standard
     79 * @level: as specified in standard
     80 * @wfd: WFD mode 1:on, 0:off
     81 */
     82struct venc_h264_vpu_config {
     83	u32 input_fourcc;
     84	u32 bitrate;
     85	u32 pic_w;
     86	u32 pic_h;
     87	u32 buf_w;
     88	u32 buf_h;
     89	u32 gop_size;
     90	u32 intra_period;
     91	u32 framerate;
     92	u32 profile;
     93	u32 level;
     94	u32 wfd;
     95};
     96
     97/*
     98 * struct venc_h264_vpu_buf - Structure for buffer information
     99 *                            AP-W/R : AP is writer/reader on this item
    100 *                            VPU-W/R: VPU is write/reader on this item
    101 * @iova: IO virtual address
    102 * @vpua: VPU side memory addr which is used by RC_CODE
    103 * @size: buffer size (in bytes)
    104 */
    105struct venc_h264_vpu_buf {
    106	u32 iova;
    107	u32 vpua;
    108	u32 size;
    109};
    110
    111/*
    112 * struct venc_h264_vsi - Structure for VPU driver control and info share
    113 *                        AP-W/R : AP is writer/reader on this item
    114 *                        VPU-W/R: VPU is write/reader on this item
    115 * This structure is allocated in VPU side and shared to AP side.
    116 * @config: h264 encoder configuration
    117 * @work_bufs: working buffer information in VPU side
    118 * The work_bufs here is for storing the 'size' info shared to AP side.
    119 * The similar item in struct venc_h264_inst is for memory allocation
    120 * in AP side. The AP driver will copy the 'size' from here to the one in
    121 * struct mtk_vcodec_mem, then invoke mtk_vcodec_mem_alloc to allocate
    122 * the buffer. After that, bypass the 'dma_addr' to the 'iova' field here for
    123 * register setting in VPU side.
    124 */
    125struct venc_h264_vsi {
    126	struct venc_h264_vpu_config config;
    127	struct venc_h264_vpu_buf work_bufs[VENC_H264_VPU_WORK_BUF_MAX];
    128};
    129
    130/*
    131 * struct venc_h264_inst - h264 encoder AP driver instance
    132 * @hw_base: h264 encoder hardware register base
    133 * @work_bufs: working buffer
    134 * @pps_buf: buffer to store the pps bitstream
    135 * @work_buf_allocated: working buffer allocated flag
    136 * @frm_cnt: encoded frame count
    137 * @prepend_hdr: when the v4l2 layer send VENC_SET_PARAM_PREPEND_HEADER cmd
    138 *  through h264_enc_set_param interface, it will set this flag and prepend the
    139 *  sps/pps in h264_enc_encode function.
    140 * @vpu_inst: VPU instance to exchange information between AP and VPU
    141 * @vsi: driver structure allocated by VPU side and shared to AP side for
    142 *	 control and info share
    143 * @ctx: context for v4l2 layer integration
    144 */
    145struct venc_h264_inst {
    146	void __iomem *hw_base;
    147	struct mtk_vcodec_mem work_bufs[VENC_H264_VPU_WORK_BUF_MAX];
    148	struct mtk_vcodec_mem pps_buf;
    149	bool work_buf_allocated;
    150	unsigned int frm_cnt;
    151	unsigned int skip_frm_cnt;
    152	unsigned int prepend_hdr;
    153	struct venc_vpu_inst vpu_inst;
    154	struct venc_h264_vsi *vsi;
    155	struct mtk_vcodec_ctx *ctx;
    156};
    157
    158static inline u32 h264_read_reg(struct venc_h264_inst *inst, u32 addr)
    159{
    160	return readl(inst->hw_base + addr);
    161}
    162
    163static unsigned int h264_get_profile(struct venc_h264_inst *inst,
    164				     unsigned int profile)
    165{
    166	switch (profile) {
    167	case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
    168		return 66;
    169	case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
    170		return 77;
    171	case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
    172		return 100;
    173	case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
    174		mtk_vcodec_err(inst, "unsupported CONSTRAINED_BASELINE");
    175		return 0;
    176	case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
    177		mtk_vcodec_err(inst, "unsupported EXTENDED");
    178		return 0;
    179	default:
    180		mtk_vcodec_debug(inst, "unsupported profile %d", profile);
    181		return 100;
    182	}
    183}
    184
    185static unsigned int h264_get_level(struct venc_h264_inst *inst,
    186				   unsigned int level)
    187{
    188	switch (level) {
    189	case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
    190		mtk_vcodec_err(inst, "unsupported 1B");
    191		return 0;
    192	case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
    193		return 10;
    194	case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
    195		return 11;
    196	case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
    197		return 12;
    198	case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
    199		return 13;
    200	case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
    201		return 20;
    202	case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
    203		return 21;
    204	case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
    205		return 22;
    206	case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
    207		return 30;
    208	case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
    209		return 31;
    210	case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
    211		return 32;
    212	case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
    213		return 40;
    214	case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
    215		return 41;
    216	case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
    217		return 42;
    218	case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
    219		return 50;
    220	case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
    221		return 51;
    222	default:
    223		mtk_vcodec_debug(inst, "unsupported level %d", level);
    224		return 31;
    225	}
    226}
    227
    228static void h264_enc_free_work_buf(struct venc_h264_inst *inst)
    229{
    230	int i;
    231
    232	mtk_vcodec_debug_enter(inst);
    233
    234	/* Except the SKIP_FRAME buffers,
    235	 * other buffers need to be freed by AP.
    236	 */
    237	for (i = 0; i < VENC_H264_VPU_WORK_BUF_MAX; i++) {
    238		if (i != VENC_H264_VPU_WORK_BUF_SKIP_FRAME)
    239			mtk_vcodec_mem_free(inst->ctx, &inst->work_bufs[i]);
    240	}
    241
    242	mtk_vcodec_mem_free(inst->ctx, &inst->pps_buf);
    243
    244	mtk_vcodec_debug_leave(inst);
    245}
    246
    247static int h264_enc_alloc_work_buf(struct venc_h264_inst *inst)
    248{
    249	int i;
    250	int ret = 0;
    251	struct venc_h264_vpu_buf *wb = inst->vsi->work_bufs;
    252
    253	mtk_vcodec_debug_enter(inst);
    254
    255	for (i = 0; i < VENC_H264_VPU_WORK_BUF_MAX; i++) {
    256		/*
    257		 * This 'wb' structure is set by VPU side and shared to AP for
    258		 * buffer allocation and IO virtual addr mapping. For most of
    259		 * the buffers, AP will allocate the buffer according to 'size'
    260		 * field and store the IO virtual addr in 'iova' field. There
    261		 * are two exceptions:
    262		 * (1) RC_CODE buffer, it's pre-allocated in the VPU side, and
    263		 * save the VPU addr in the 'vpua' field. The AP will translate
    264		 * the VPU addr to the corresponding IO virtual addr and store
    265		 * in 'iova' field for reg setting in VPU side.
    266		 * (2) SKIP_FRAME buffer, it's pre-allocated in the VPU side,
    267		 * and save the VPU addr in the 'vpua' field. The AP will
    268		 * translate the VPU addr to the corresponding AP side virtual
    269		 * address and do some memcpy access to move to bitstream buffer
    270		 * assigned by v4l2 layer.
    271		 */
    272		inst->work_bufs[i].size = wb[i].size;
    273		if (i == VENC_H264_VPU_WORK_BUF_SKIP_FRAME) {
    274			struct mtk_vcodec_fw *handler;
    275
    276			handler = inst->vpu_inst.ctx->dev->fw_handler;
    277			inst->work_bufs[i].va =
    278				mtk_vcodec_fw_map_dm_addr(handler, wb[i].vpua);
    279			inst->work_bufs[i].dma_addr = 0;
    280		} else {
    281			ret = mtk_vcodec_mem_alloc(inst->ctx,
    282						   &inst->work_bufs[i]);
    283			if (ret) {
    284				mtk_vcodec_err(inst,
    285					       "cannot allocate buf %d", i);
    286				goto err_alloc;
    287			}
    288			/*
    289			 * This RC_CODE is pre-allocated by VPU and saved in VPU
    290			 * addr. So we need use memcpy to copy RC_CODE from VPU
    291			 * addr into IO virtual addr in 'iova' field for reg
    292			 * setting in VPU side.
    293			 */
    294			if (i == VENC_H264_VPU_WORK_BUF_RC_CODE) {
    295				struct mtk_vcodec_fw *handler;
    296				void *tmp_va;
    297
    298				handler = inst->vpu_inst.ctx->dev->fw_handler;
    299				tmp_va = mtk_vcodec_fw_map_dm_addr(handler,
    300								   wb[i].vpua);
    301				memcpy(inst->work_bufs[i].va, tmp_va,
    302				       wb[i].size);
    303			}
    304		}
    305		wb[i].iova = inst->work_bufs[i].dma_addr;
    306
    307		mtk_vcodec_debug(inst,
    308				 "work_buf[%d] va=0x%p iova=%pad size=%zu",
    309				 i, inst->work_bufs[i].va,
    310				 &inst->work_bufs[i].dma_addr,
    311				 inst->work_bufs[i].size);
    312	}
    313
    314	/* the pps_buf is used by AP side only */
    315	inst->pps_buf.size = 128;
    316	ret = mtk_vcodec_mem_alloc(inst->ctx, &inst->pps_buf);
    317	if (ret) {
    318		mtk_vcodec_err(inst, "cannot allocate pps_buf");
    319		goto err_alloc;
    320	}
    321
    322	mtk_vcodec_debug_leave(inst);
    323
    324	return ret;
    325
    326err_alloc:
    327	h264_enc_free_work_buf(inst);
    328
    329	return ret;
    330}
    331
    332static unsigned int h264_enc_wait_venc_done(struct venc_h264_inst *inst)
    333{
    334	unsigned int irq_status = 0;
    335	struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)inst->ctx;
    336
    337	if (!mtk_vcodec_wait_for_done_ctx(ctx, MTK_INST_IRQ_RECEIVED,
    338					  WAIT_INTR_TIMEOUT_MS, 0)) {
    339		irq_status = ctx->irq_status;
    340		mtk_vcodec_debug(inst, "irq_status %x <-", irq_status);
    341	}
    342	return irq_status;
    343}
    344
    345static int h264_frame_type(struct venc_h264_inst *inst)
    346{
    347	if ((inst->vsi->config.gop_size != 0 &&
    348	     (inst->frm_cnt % inst->vsi->config.gop_size) == 0) ||
    349	    (inst->frm_cnt == 0 && inst->vsi->config.gop_size == 0)) {
    350		/* IDR frame */
    351		return VENC_H264_IDR_FRM;
    352	} else if ((inst->vsi->config.intra_period != 0 &&
    353		    (inst->frm_cnt % inst->vsi->config.intra_period) == 0) ||
    354		   (inst->frm_cnt == 0 && inst->vsi->config.intra_period == 0)) {
    355		/* I frame */
    356		return VENC_H264_I_FRM;
    357	} else {
    358		return VENC_H264_P_FRM;  /* Note: B frames are not supported */
    359	}
    360}
    361static int h264_encode_sps(struct venc_h264_inst *inst,
    362			   struct mtk_vcodec_mem *bs_buf,
    363			   unsigned int *bs_size)
    364{
    365	int ret = 0;
    366	unsigned int irq_status;
    367
    368	mtk_vcodec_debug_enter(inst);
    369
    370	ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_SPS, NULL, bs_buf, NULL);
    371	if (ret)
    372		return ret;
    373
    374	irq_status = h264_enc_wait_venc_done(inst);
    375	if (irq_status != MTK_VENC_IRQ_STATUS_SPS) {
    376		mtk_vcodec_err(inst, "expect irq status %d",
    377			       MTK_VENC_IRQ_STATUS_SPS);
    378		return -EINVAL;
    379	}
    380
    381	*bs_size = h264_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT);
    382	mtk_vcodec_debug(inst, "bs size %d <-", *bs_size);
    383
    384	return ret;
    385}
    386
    387static int h264_encode_pps(struct venc_h264_inst *inst,
    388			   struct mtk_vcodec_mem *bs_buf,
    389			   unsigned int *bs_size)
    390{
    391	int ret = 0;
    392	unsigned int irq_status;
    393
    394	mtk_vcodec_debug_enter(inst);
    395
    396	ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_PPS, NULL, bs_buf, NULL);
    397	if (ret)
    398		return ret;
    399
    400	irq_status = h264_enc_wait_venc_done(inst);
    401	if (irq_status != MTK_VENC_IRQ_STATUS_PPS) {
    402		mtk_vcodec_err(inst, "expect irq status %d",
    403			       MTK_VENC_IRQ_STATUS_PPS);
    404		return -EINVAL;
    405	}
    406
    407	*bs_size = h264_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT);
    408	mtk_vcodec_debug(inst, "bs size %d <-", *bs_size);
    409
    410	return ret;
    411}
    412
    413static int h264_encode_header(struct venc_h264_inst *inst,
    414			      struct mtk_vcodec_mem *bs_buf,
    415			      unsigned int *bs_size)
    416{
    417	int ret = 0;
    418	unsigned int bs_size_sps;
    419	unsigned int bs_size_pps;
    420
    421	ret = h264_encode_sps(inst, bs_buf, &bs_size_sps);
    422	if (ret)
    423		return ret;
    424
    425	ret = h264_encode_pps(inst, &inst->pps_buf, &bs_size_pps);
    426	if (ret)
    427		return ret;
    428
    429	memcpy(bs_buf->va + bs_size_sps, inst->pps_buf.va, bs_size_pps);
    430	*bs_size = bs_size_sps + bs_size_pps;
    431
    432	return ret;
    433}
    434
    435static int h264_encode_frame(struct venc_h264_inst *inst,
    436			     struct venc_frm_buf *frm_buf,
    437			     struct mtk_vcodec_mem *bs_buf,
    438			     unsigned int *bs_size)
    439{
    440	int ret = 0;
    441	unsigned int irq_status;
    442	struct venc_frame_info frame_info;
    443
    444	mtk_vcodec_debug_enter(inst);
    445	mtk_vcodec_debug(inst, "frm_cnt = %d\n ", inst->frm_cnt);
    446	frame_info.frm_count = inst->frm_cnt;
    447	frame_info.skip_frm_count = inst->skip_frm_cnt;
    448	frame_info.frm_type = h264_frame_type(inst);
    449	mtk_vcodec_debug(inst, "frm_count = %d,skip_frm_count =%d,frm_type=%d.\n",
    450			 frame_info.frm_count, frame_info.skip_frm_count,
    451			 frame_info.frm_type);
    452	ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_FRAME, frm_buf, bs_buf, &frame_info);
    453	if (ret)
    454		return ret;
    455
    456	/*
    457	 * skip frame case: The skip frame buffer is composed by vpu side only,
    458	 * it does not trigger the hw, so skip the wait interrupt operation.
    459	 */
    460	if (inst->vpu_inst.state == VEN_IPI_MSG_ENC_STATE_SKIP) {
    461		*bs_size = inst->vpu_inst.bs_size;
    462		memcpy(bs_buf->va,
    463		       inst->work_bufs[VENC_H264_VPU_WORK_BUF_SKIP_FRAME].va,
    464		       *bs_size);
    465		++inst->frm_cnt;
    466		++inst->skip_frm_cnt;
    467		return ret;
    468	}
    469
    470	irq_status = h264_enc_wait_venc_done(inst);
    471	if (irq_status != MTK_VENC_IRQ_STATUS_FRM) {
    472		mtk_vcodec_err(inst, "irq_status=%d failed", irq_status);
    473		return -EIO;
    474	}
    475
    476	*bs_size = h264_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT);
    477
    478	++inst->frm_cnt;
    479	mtk_vcodec_debug(inst, "frm %d bs_size %d key_frm %d <-",
    480			 inst->frm_cnt, *bs_size, inst->vpu_inst.is_key_frm);
    481
    482	return ret;
    483}
    484
    485static void h264_encode_filler(struct venc_h264_inst *inst, void *buf,
    486			       int size)
    487{
    488	unsigned char *p = buf;
    489
    490	if (size < H264_FILLER_MARKER_SIZE) {
    491		mtk_vcodec_err(inst, "filler size too small %d", size);
    492		return;
    493	}
    494
    495	memcpy(p, h264_filler_marker, ARRAY_SIZE(h264_filler_marker));
    496	size -= H264_FILLER_MARKER_SIZE;
    497	p += H264_FILLER_MARKER_SIZE;
    498	memset(p, 0xff, size);
    499}
    500
    501static int h264_enc_init(struct mtk_vcodec_ctx *ctx)
    502{
    503	const bool is_ext = MTK_ENC_CTX_IS_EXT(ctx);
    504	int ret = 0;
    505	struct venc_h264_inst *inst;
    506
    507	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
    508	if (!inst)
    509		return -ENOMEM;
    510
    511	inst->ctx = ctx;
    512	inst->vpu_inst.ctx = ctx;
    513	inst->vpu_inst.id = is_ext ? SCP_IPI_VENC_H264 : IPI_VENC_H264;
    514	inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx, VENC_SYS);
    515
    516	mtk_vcodec_debug_enter(inst);
    517
    518	ret = vpu_enc_init(&inst->vpu_inst);
    519
    520	inst->vsi = (struct venc_h264_vsi *)inst->vpu_inst.vsi;
    521
    522	mtk_vcodec_debug_leave(inst);
    523
    524	if (ret)
    525		kfree(inst);
    526	else
    527		ctx->drv_handle = inst;
    528
    529	return ret;
    530}
    531
    532static int h264_enc_encode(void *handle,
    533			   enum venc_start_opt opt,
    534			   struct venc_frm_buf *frm_buf,
    535			   struct mtk_vcodec_mem *bs_buf,
    536			   struct venc_done_result *result)
    537{
    538	int ret = 0;
    539	struct venc_h264_inst *inst = (struct venc_h264_inst *)handle;
    540	struct mtk_vcodec_ctx *ctx = inst->ctx;
    541
    542	mtk_vcodec_debug(inst, "opt %d ->", opt);
    543
    544	enable_irq(ctx->dev->enc_irq);
    545
    546	switch (opt) {
    547	case VENC_START_OPT_ENCODE_SEQUENCE_HEADER: {
    548		unsigned int bs_size_hdr;
    549
    550		ret = h264_encode_header(inst, bs_buf, &bs_size_hdr);
    551		if (ret)
    552			goto encode_err;
    553
    554		result->bs_size = bs_size_hdr;
    555		result->is_key_frm = false;
    556		break;
    557	}
    558
    559	case VENC_START_OPT_ENCODE_FRAME: {
    560		int hdr_sz;
    561		int hdr_sz_ext;
    562		int filler_sz = 0;
    563		const int bs_alignment = 128;
    564		struct mtk_vcodec_mem tmp_bs_buf;
    565		unsigned int bs_size_hdr;
    566		unsigned int bs_size_frm;
    567
    568		if (!inst->prepend_hdr) {
    569			ret = h264_encode_frame(inst, frm_buf, bs_buf,
    570						&result->bs_size);
    571			if (ret)
    572				goto encode_err;
    573			result->is_key_frm = inst->vpu_inst.is_key_frm;
    574			break;
    575		}
    576
    577		mtk_vcodec_debug(inst, "h264_encode_frame prepend SPS/PPS");
    578
    579		ret = h264_encode_header(inst, bs_buf, &bs_size_hdr);
    580		if (ret)
    581			goto encode_err;
    582
    583		hdr_sz = bs_size_hdr;
    584		hdr_sz_ext = (hdr_sz & (bs_alignment - 1));
    585		if (hdr_sz_ext) {
    586			filler_sz = bs_alignment - hdr_sz_ext;
    587			if (hdr_sz_ext + H264_FILLER_MARKER_SIZE > bs_alignment)
    588				filler_sz += bs_alignment;
    589			h264_encode_filler(inst, bs_buf->va + hdr_sz,
    590					   filler_sz);
    591		}
    592
    593		tmp_bs_buf.va = bs_buf->va + hdr_sz + filler_sz;
    594		tmp_bs_buf.dma_addr = bs_buf->dma_addr + hdr_sz + filler_sz;
    595		tmp_bs_buf.size = bs_buf->size - (hdr_sz + filler_sz);
    596
    597		ret = h264_encode_frame(inst, frm_buf, &tmp_bs_buf,
    598					&bs_size_frm);
    599		if (ret)
    600			goto encode_err;
    601
    602		result->bs_size = hdr_sz + filler_sz + bs_size_frm;
    603
    604		mtk_vcodec_debug(inst, "hdr %d filler %d frame %d bs %d",
    605				 hdr_sz, filler_sz, bs_size_frm,
    606				 result->bs_size);
    607
    608		inst->prepend_hdr = 0;
    609		result->is_key_frm = inst->vpu_inst.is_key_frm;
    610		break;
    611	}
    612
    613	default:
    614		mtk_vcodec_err(inst, "venc_start_opt %d not supported", opt);
    615		ret = -EINVAL;
    616		break;
    617	}
    618
    619encode_err:
    620
    621	disable_irq(ctx->dev->enc_irq);
    622	mtk_vcodec_debug(inst, "opt %d <-", opt);
    623
    624	return ret;
    625}
    626
    627static int h264_enc_set_param(void *handle,
    628			      enum venc_set_param_type type,
    629			      struct venc_enc_param *enc_prm)
    630{
    631	int ret = 0;
    632	struct venc_h264_inst *inst = (struct venc_h264_inst *)handle;
    633
    634	mtk_vcodec_debug(inst, "->type=%d", type);
    635
    636	switch (type) {
    637	case VENC_SET_PARAM_ENC:
    638		inst->vsi->config.input_fourcc = enc_prm->input_yuv_fmt;
    639		inst->vsi->config.bitrate = enc_prm->bitrate;
    640		inst->vsi->config.pic_w = enc_prm->width;
    641		inst->vsi->config.pic_h = enc_prm->height;
    642		inst->vsi->config.buf_w = enc_prm->buf_width;
    643		inst->vsi->config.buf_h = enc_prm->buf_height;
    644		inst->vsi->config.gop_size = enc_prm->gop_size;
    645		inst->vsi->config.framerate = enc_prm->frm_rate;
    646		inst->vsi->config.intra_period = enc_prm->intra_period;
    647		inst->vsi->config.profile =
    648			h264_get_profile(inst, enc_prm->h264_profile);
    649		inst->vsi->config.level =
    650			h264_get_level(inst, enc_prm->h264_level);
    651		inst->vsi->config.wfd = 0;
    652		ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
    653		if (ret)
    654			break;
    655		if (inst->work_buf_allocated) {
    656			h264_enc_free_work_buf(inst);
    657			inst->work_buf_allocated = false;
    658		}
    659		ret = h264_enc_alloc_work_buf(inst);
    660		if (ret)
    661			break;
    662		inst->work_buf_allocated = true;
    663		break;
    664
    665	case VENC_SET_PARAM_PREPEND_HEADER:
    666		inst->prepend_hdr = 1;
    667		mtk_vcodec_debug(inst, "set prepend header mode");
    668		break;
    669	case VENC_SET_PARAM_FORCE_INTRA:
    670	case VENC_SET_PARAM_GOP_SIZE:
    671	case VENC_SET_PARAM_INTRA_PERIOD:
    672		inst->frm_cnt = 0;
    673		inst->skip_frm_cnt = 0;
    674		fallthrough;
    675	default:
    676		ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
    677		break;
    678	}
    679
    680	mtk_vcodec_debug_leave(inst);
    681
    682	return ret;
    683}
    684
    685static int h264_enc_deinit(void *handle)
    686{
    687	int ret = 0;
    688	struct venc_h264_inst *inst = (struct venc_h264_inst *)handle;
    689
    690	mtk_vcodec_debug_enter(inst);
    691
    692	ret = vpu_enc_deinit(&inst->vpu_inst);
    693
    694	if (inst->work_buf_allocated)
    695		h264_enc_free_work_buf(inst);
    696
    697	mtk_vcodec_debug_leave(inst);
    698	kfree(inst);
    699
    700	return ret;
    701}
    702
    703const struct venc_common_if venc_h264_if = {
    704	.init = h264_enc_init,
    705	.encode = h264_enc_encode,
    706	.set_param = h264_enc_set_param,
    707	.deinit = h264_enc_deinit,
    708};