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};