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