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