| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2016 MediaTek Inc. |
|---|
| 3 | 4 | * Author: Jungchang Tsao <jungchang.tsao@mediatek.com> |
|---|
| 4 | 5 | * Daniel Hsiao <daniel.hsiao@mediatek.com> |
|---|
| 5 | 6 | * PoChun Lin <pochun.lin@mediatek.com> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or |
|---|
| 8 | | - * modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 10 | | - * published by the Free Software Foundation. |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 15 | | - * GNU General Public License for more details. |
|---|
| 16 | 7 | */ |
|---|
| 17 | 8 | |
|---|
| 18 | 9 | #include <linux/interrupt.h> |
|---|
| .. | .. |
|---|
| 27 | 18 | #include "../venc_drv_base.h" |
|---|
| 28 | 19 | #include "../venc_ipi_msg.h" |
|---|
| 29 | 20 | #include "../venc_vpu_if.h" |
|---|
| 30 | | -#include "mtk_vpu.h" |
|---|
| 31 | 21 | |
|---|
| 32 | 22 | static const char h264_filler_marker[] = {0x0, 0x0, 0x0, 0x1, 0xc}; |
|---|
| 33 | 23 | |
|---|
| 34 | 24 | #define H264_FILLER_MARKER_SIZE ARRAY_SIZE(h264_filler_marker) |
|---|
| 35 | 25 | #define VENC_PIC_BITSTREAM_BYTE_CNT 0x0098 |
|---|
| 26 | + |
|---|
| 27 | +/* |
|---|
| 28 | + * enum venc_h264_frame_type - h264 encoder output bitstream frame type |
|---|
| 29 | + */ |
|---|
| 30 | +enum 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 | 36 | |
|---|
| 37 | 37 | /* |
|---|
| 38 | 38 | * enum venc_h264_vpu_work_buf - h264 encoder buffer index |
|---|
| .. | .. |
|---|
| 148 | 148 | struct mtk_vcodec_mem pps_buf; |
|---|
| 149 | 149 | bool work_buf_allocated; |
|---|
| 150 | 150 | unsigned int frm_cnt; |
|---|
| 151 | + unsigned int skip_frm_cnt; |
|---|
| 151 | 152 | unsigned int prepend_hdr; |
|---|
| 152 | 153 | struct venc_vpu_inst vpu_inst; |
|---|
| 153 | 154 | struct venc_h264_vsi *vsi; |
|---|
| .. | .. |
|---|
| 266 | 267 | */ |
|---|
| 267 | 268 | inst->work_bufs[i].size = wb[i].size; |
|---|
| 268 | 269 | if (i == VENC_H264_VPU_WORK_BUF_SKIP_FRAME) { |
|---|
| 269 | | - inst->work_bufs[i].va = vpu_mapping_dm_addr( |
|---|
| 270 | | - inst->vpu_inst.dev, wb[i].vpua); |
|---|
| 270 | + struct mtk_vcodec_fw *handler; |
|---|
| 271 | + |
|---|
| 272 | + handler = inst->vpu_inst.ctx->dev->fw_handler; |
|---|
| 273 | + inst->work_bufs[i].va = |
|---|
| 274 | + mtk_vcodec_fw_map_dm_addr(handler, wb[i].vpua); |
|---|
| 271 | 275 | inst->work_bufs[i].dma_addr = 0; |
|---|
| 272 | 276 | } else { |
|---|
| 273 | 277 | ret = mtk_vcodec_mem_alloc(inst->ctx, |
|---|
| .. | .. |
|---|
| 284 | 288 | * setting in VPU side. |
|---|
| 285 | 289 | */ |
|---|
| 286 | 290 | if (i == VENC_H264_VPU_WORK_BUF_RC_CODE) { |
|---|
| 291 | + struct mtk_vcodec_fw *handler; |
|---|
| 287 | 292 | void *tmp_va; |
|---|
| 288 | 293 | |
|---|
| 289 | | - tmp_va = vpu_mapping_dm_addr(inst->vpu_inst.dev, |
|---|
| 290 | | - wb[i].vpua); |
|---|
| 294 | + handler = inst->vpu_inst.ctx->dev->fw_handler; |
|---|
| 295 | + tmp_va = mtk_vcodec_fw_map_dm_addr(handler, |
|---|
| 296 | + wb[i].vpua); |
|---|
| 291 | 297 | memcpy(inst->work_bufs[i].va, tmp_va, |
|---|
| 292 | 298 | wb[i].size); |
|---|
| 293 | 299 | } |
|---|
| .. | .. |
|---|
| 332 | 338 | return irq_status; |
|---|
| 333 | 339 | } |
|---|
| 334 | 340 | |
|---|
| 341 | +static int h264_frame_type(struct venc_h264_inst *inst) |
|---|
| 342 | +{ |
|---|
| 343 | + if ((inst->vsi->config.gop_size != 0 && |
|---|
| 344 | + (inst->frm_cnt % inst->vsi->config.gop_size) == 0) || |
|---|
| 345 | + (inst->frm_cnt == 0 && inst->vsi->config.gop_size == 0)) { |
|---|
| 346 | + /* IDR frame */ |
|---|
| 347 | + return VENC_H264_IDR_FRM; |
|---|
| 348 | + } else if ((inst->vsi->config.intra_period != 0 && |
|---|
| 349 | + (inst->frm_cnt % inst->vsi->config.intra_period) == 0) || |
|---|
| 350 | + (inst->frm_cnt == 0 && inst->vsi->config.intra_period == 0)) { |
|---|
| 351 | + /* I frame */ |
|---|
| 352 | + return VENC_H264_I_FRM; |
|---|
| 353 | + } else { |
|---|
| 354 | + return VENC_H264_P_FRM; /* Note: B frames are not supported */ |
|---|
| 355 | + } |
|---|
| 356 | +} |
|---|
| 335 | 357 | static int h264_encode_sps(struct venc_h264_inst *inst, |
|---|
| 336 | 358 | struct mtk_vcodec_mem *bs_buf, |
|---|
| 337 | 359 | unsigned int *bs_size) |
|---|
| .. | .. |
|---|
| 342 | 364 | mtk_vcodec_debug_enter(inst); |
|---|
| 343 | 365 | |
|---|
| 344 | 366 | ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_SPS, NULL, |
|---|
| 345 | | - bs_buf, bs_size); |
|---|
| 367 | + bs_buf, bs_size, NULL); |
|---|
| 346 | 368 | if (ret) |
|---|
| 347 | 369 | return ret; |
|---|
| 348 | 370 | |
|---|
| .. | .. |
|---|
| 369 | 391 | mtk_vcodec_debug_enter(inst); |
|---|
| 370 | 392 | |
|---|
| 371 | 393 | ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_PPS, NULL, |
|---|
| 372 | | - bs_buf, bs_size); |
|---|
| 394 | + bs_buf, bs_size, NULL); |
|---|
| 373 | 395 | if (ret) |
|---|
| 374 | 396 | return ret; |
|---|
| 375 | 397 | |
|---|
| .. | .. |
|---|
| 415 | 437 | { |
|---|
| 416 | 438 | int ret = 0; |
|---|
| 417 | 439 | unsigned int irq_status; |
|---|
| 440 | + struct venc_frame_info frame_info; |
|---|
| 418 | 441 | |
|---|
| 419 | 442 | mtk_vcodec_debug_enter(inst); |
|---|
| 420 | | - |
|---|
| 443 | + mtk_vcodec_debug(inst, "frm_cnt = %d\n ", inst->frm_cnt); |
|---|
| 444 | + frame_info.frm_count = inst->frm_cnt; |
|---|
| 445 | + frame_info.skip_frm_count = inst->skip_frm_cnt; |
|---|
| 446 | + frame_info.frm_type = h264_frame_type(inst); |
|---|
| 447 | + mtk_vcodec_debug(inst, "frm_count = %d,skip_frm_count =%d,frm_type=%d.\n", |
|---|
| 448 | + frame_info.frm_count, frame_info.skip_frm_count, |
|---|
| 449 | + frame_info.frm_type); |
|---|
| 421 | 450 | ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_FRAME, frm_buf, |
|---|
| 422 | | - bs_buf, bs_size); |
|---|
| 451 | + bs_buf, bs_size, &frame_info); |
|---|
| 423 | 452 | if (ret) |
|---|
| 424 | 453 | return ret; |
|---|
| 425 | 454 | |
|---|
| .. | .. |
|---|
| 433 | 462 | inst->work_bufs[VENC_H264_VPU_WORK_BUF_SKIP_FRAME].va, |
|---|
| 434 | 463 | *bs_size); |
|---|
| 435 | 464 | ++inst->frm_cnt; |
|---|
| 465 | + ++inst->skip_frm_cnt; |
|---|
| 436 | 466 | return ret; |
|---|
| 437 | 467 | } |
|---|
| 438 | 468 | |
|---|
| .. | .. |
|---|
| 467 | 497 | memset(p, 0xff, size); |
|---|
| 468 | 498 | } |
|---|
| 469 | 499 | |
|---|
| 470 | | -static int h264_enc_init(struct mtk_vcodec_ctx *ctx, unsigned long *handle) |
|---|
| 500 | +static int h264_enc_init(struct mtk_vcodec_ctx *ctx) |
|---|
| 471 | 501 | { |
|---|
| 502 | + const bool is_ext = MTK_ENC_CTX_IS_EXT(ctx); |
|---|
| 472 | 503 | int ret = 0; |
|---|
| 473 | 504 | struct venc_h264_inst *inst; |
|---|
| 474 | 505 | |
|---|
| .. | .. |
|---|
| 478 | 509 | |
|---|
| 479 | 510 | inst->ctx = ctx; |
|---|
| 480 | 511 | inst->vpu_inst.ctx = ctx; |
|---|
| 481 | | - inst->vpu_inst.dev = ctx->dev->vpu_plat_dev; |
|---|
| 482 | | - inst->vpu_inst.id = IPI_VENC_H264; |
|---|
| 512 | + inst->vpu_inst.id = is_ext ? SCP_IPI_VENC_H264 : IPI_VENC_H264; |
|---|
| 483 | 513 | inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx, VENC_SYS); |
|---|
| 484 | 514 | |
|---|
| 485 | 515 | mtk_vcodec_debug_enter(inst); |
|---|
| .. | .. |
|---|
| 493 | 523 | if (ret) |
|---|
| 494 | 524 | kfree(inst); |
|---|
| 495 | 525 | else |
|---|
| 496 | | - (*handle) = (unsigned long)inst; |
|---|
| 526 | + ctx->drv_handle = inst; |
|---|
| 497 | 527 | |
|---|
| 498 | 528 | return ret; |
|---|
| 499 | 529 | } |
|---|
| 500 | 530 | |
|---|
| 501 | | -static int h264_enc_encode(unsigned long handle, |
|---|
| 531 | +static int h264_enc_encode(void *handle, |
|---|
| 502 | 532 | enum venc_start_opt opt, |
|---|
| 503 | 533 | struct venc_frm_buf *frm_buf, |
|---|
| 504 | 534 | struct mtk_vcodec_mem *bs_buf, |
|---|
| .. | .. |
|---|
| 593 | 623 | return ret; |
|---|
| 594 | 624 | } |
|---|
| 595 | 625 | |
|---|
| 596 | | -static int h264_enc_set_param(unsigned long handle, |
|---|
| 626 | +static int h264_enc_set_param(void *handle, |
|---|
| 597 | 627 | enum venc_set_param_type type, |
|---|
| 598 | 628 | struct venc_enc_param *enc_prm) |
|---|
| 599 | 629 | { |
|---|
| .. | .. |
|---|
| 635 | 665 | inst->prepend_hdr = 1; |
|---|
| 636 | 666 | mtk_vcodec_debug(inst, "set prepend header mode"); |
|---|
| 637 | 667 | break; |
|---|
| 638 | | - |
|---|
| 668 | + case VENC_SET_PARAM_FORCE_INTRA: |
|---|
| 669 | + case VENC_SET_PARAM_GOP_SIZE: |
|---|
| 670 | + case VENC_SET_PARAM_INTRA_PERIOD: |
|---|
| 671 | + inst->frm_cnt = 0; |
|---|
| 672 | + inst->skip_frm_cnt = 0; |
|---|
| 673 | + fallthrough; |
|---|
| 639 | 674 | default: |
|---|
| 640 | 675 | ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm); |
|---|
| 641 | 676 | break; |
|---|
| .. | .. |
|---|
| 646 | 681 | return ret; |
|---|
| 647 | 682 | } |
|---|
| 648 | 683 | |
|---|
| 649 | | -static int h264_enc_deinit(unsigned long handle) |
|---|
| 684 | +static int h264_enc_deinit(void *handle) |
|---|
| 650 | 685 | { |
|---|
| 651 | 686 | int ret = 0; |
|---|
| 652 | 687 | struct venc_h264_inst *inst = (struct venc_h264_inst *)handle; |
|---|
| .. | .. |
|---|
| 664 | 699 | return ret; |
|---|
| 665 | 700 | } |
|---|
| 666 | 701 | |
|---|
| 667 | | -static const struct venc_common_if venc_h264_if = { |
|---|
| 702 | +const struct venc_common_if venc_h264_if = { |
|---|
| 668 | 703 | .init = h264_enc_init, |
|---|
| 669 | 704 | .encode = h264_enc_encode, |
|---|
| 670 | 705 | .set_param = h264_enc_set_param, |
|---|
| 671 | 706 | .deinit = h264_enc_deinit, |
|---|
| 672 | 707 | }; |
|---|
| 673 | | - |
|---|
| 674 | | -const struct venc_common_if *get_h264_enc_comm_if(void); |
|---|
| 675 | | - |
|---|
| 676 | | -const struct venc_common_if *get_h264_enc_comm_if(void) |
|---|
| 677 | | -{ |
|---|
| 678 | | - return &venc_h264_if; |
|---|
| 679 | | -} |
|---|