1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2016 MediaTek Inc.
4 * Author: Daniel Hsiao <daniel.hsiao@mediatek.com>
5 * PoChun Lin <pochun.lin@mediatek.com>
8 #include <linux/interrupt.h>
9 #include <linux/kernel.h>
10 #include <linux/slab.h>
12 #include "../mtk_vcodec_drv.h"
13 #include "../mtk_vcodec_util.h"
14 #include "../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"
21 #define VENC_BITSTREAM_FRAME_SIZE 0x0098
22 #define VENC_BITSTREAM_HEADER_LEN 0x00e8
24 /* This ac_tag is vp8 frame tag. */
25 #define MAX_AC_TAG_SIZE 10
28 * enum venc_vp8_vpu_work_buf - vp8 encoder buffer index
30 enum venc_vp8_vpu_work_buf
{
31 VENC_VP8_VPU_WORK_BUF_LUMA
,
32 VENC_VP8_VPU_WORK_BUF_LUMA2
,
33 VENC_VP8_VPU_WORK_BUF_LUMA3
,
34 VENC_VP8_VPU_WORK_BUF_CHROMA
,
35 VENC_VP8_VPU_WORK_BUF_CHROMA2
,
36 VENC_VP8_VPU_WORK_BUF_CHROMA3
,
37 VENC_VP8_VPU_WORK_BUF_MV_INFO
,
38 VENC_VP8_VPU_WORK_BUF_BS_HEADER
,
39 VENC_VP8_VPU_WORK_BUF_PROB_BUF
,
40 VENC_VP8_VPU_WORK_BUF_RC_INFO
,
41 VENC_VP8_VPU_WORK_BUF_RC_CODE
,
42 VENC_VP8_VPU_WORK_BUF_RC_CODE2
,
43 VENC_VP8_VPU_WORK_BUF_RC_CODE3
,
44 VENC_VP8_VPU_WORK_BUF_MAX
,
48 * struct venc_vp8_vpu_config - Structure for vp8 encoder configuration
49 * AP-W/R : AP is writer/reader on this item
50 * VPU-W/R: VPU is write/reader on this item
51 * @input_fourcc: input fourcc
52 * @bitrate: target bitrate (in bps)
53 * @pic_w: picture width. Picture size is visible stream resolution, in pixels,
54 * to be used for display purposes; must be smaller or equal to buffer
56 * @pic_h: picture height
57 * @buf_w: buffer width (with 16 alignment). Buffer size is stream resolution
58 * in pixels aligned to hardware requirements.
59 * @buf_h: buffer height (with 16 alignment)
60 * @gop_size: group of picture size (key frame)
61 * @framerate: frame rate in fps
62 * @ts_mode: temporal scalability mode (0: disable, 1: enable)
63 * support three temporal layers - 0: 7.5fps 1: 7.5fps 2: 15fps.
65 struct venc_vp8_vpu_config
{
78 * struct venc_vp8_vpu_buf - Structure for buffer information
79 * AP-W/R : AP is writer/reader on this item
80 * VPU-W/R: VPU is write/reader on this item
81 * @iova: IO virtual address
82 * @vpua: VPU side memory addr which is used by RC_CODE
83 * @size: buffer size (in bytes)
85 struct venc_vp8_vpu_buf
{
92 * struct venc_vp8_vsi - Structure for VPU driver control and info share
93 * AP-W/R : AP is writer/reader on this item
94 * VPU-W/R: VPU is write/reader on this item
95 * This structure is allocated in VPU side and shared to AP side.
96 * @config: vp8 encoder configuration
97 * @work_bufs: working buffer information in VPU side
98 * The work_bufs here is for storing the 'size' info shared to AP side.
99 * The similar item in struct venc_vp8_inst is for memory allocation
100 * in AP side. The AP driver will copy the 'size' from here to the one in
101 * struct mtk_vcodec_mem, then invoke mtk_vcodec_mem_alloc to allocate
102 * the buffer. After that, bypass the 'dma_addr' to the 'iova' field here for
103 * register setting in VPU side.
105 struct venc_vp8_vsi
{
106 struct venc_vp8_vpu_config config
;
107 struct venc_vp8_vpu_buf work_bufs
[VENC_VP8_VPU_WORK_BUF_MAX
];
111 * struct venc_vp8_inst - vp8 encoder AP driver instance
112 * @hw_base: vp8 encoder hardware register base
113 * @work_bufs: working buffer
114 * @work_buf_allocated: working buffer allocated flag
115 * @frm_cnt: encoded frame count, it's used for I-frame judgement and
116 * reset when force intra cmd received.
117 * @ts_mode: temporal scalability mode (0: disable, 1: enable)
118 * support three temporal layers - 0: 7.5fps 1: 7.5fps 2: 15fps.
119 * @vpu_inst: VPU instance to exchange information between AP and VPU
120 * @vsi: driver structure allocated by VPU side and shared to AP side for
121 * control and info share
122 * @ctx: context for v4l2 layer integration
124 struct venc_vp8_inst
{
125 void __iomem
*hw_base
;
126 struct mtk_vcodec_mem work_bufs
[VENC_VP8_VPU_WORK_BUF_MAX
];
127 bool work_buf_allocated
;
128 unsigned int frm_cnt
;
129 unsigned int ts_mode
;
130 struct venc_vpu_inst vpu_inst
;
131 struct venc_vp8_vsi
*vsi
;
132 struct mtk_vcodec_ctx
*ctx
;
135 static inline u32
vp8_enc_read_reg(struct venc_vp8_inst
*inst
, u32 addr
)
137 return readl(inst
->hw_base
+ addr
);
140 static void vp8_enc_free_work_buf(struct venc_vp8_inst
*inst
)
144 mtk_vcodec_debug_enter(inst
);
146 /* Buffers need to be freed by AP. */
147 for (i
= 0; i
< VENC_VP8_VPU_WORK_BUF_MAX
; i
++) {
148 if (inst
->work_bufs
[i
].size
== 0)
150 mtk_vcodec_mem_free(inst
->ctx
, &inst
->work_bufs
[i
]);
153 mtk_vcodec_debug_leave(inst
);
156 static int vp8_enc_alloc_work_buf(struct venc_vp8_inst
*inst
)
160 struct venc_vp8_vpu_buf
*wb
= inst
->vsi
->work_bufs
;
162 mtk_vcodec_debug_enter(inst
);
164 for (i
= 0; i
< VENC_VP8_VPU_WORK_BUF_MAX
; i
++) {
168 * This 'wb' structure is set by VPU side and shared to AP for
169 * buffer allocation and IO virtual addr mapping. For most of
170 * the buffers, AP will allocate the buffer according to 'size'
171 * field and store the IO virtual addr in 'iova' field. For the
172 * RC_CODEx buffers, they are pre-allocated in the VPU side
173 * because they are inside VPU SRAM, and save the VPU addr in
174 * the 'vpua' field. The AP will translate the VPU addr to the
175 * corresponding IO virtual addr and store in 'iova' field.
177 inst
->work_bufs
[i
].size
= wb
[i
].size
;
178 ret
= mtk_vcodec_mem_alloc(inst
->ctx
, &inst
->work_bufs
[i
]);
181 "cannot alloc work_bufs[%d]", i
);
185 * This RC_CODEx is pre-allocated by VPU and saved in VPU addr.
186 * So we need use memcpy to copy RC_CODEx from VPU addr into IO
187 * virtual addr in 'iova' field for reg setting in VPU side.
189 if (i
== VENC_VP8_VPU_WORK_BUF_RC_CODE
||
190 i
== VENC_VP8_VPU_WORK_BUF_RC_CODE2
||
191 i
== VENC_VP8_VPU_WORK_BUF_RC_CODE3
) {
192 struct mtk_vcodec_fw
*handler
;
195 handler
= inst
->vpu_inst
.ctx
->dev
->fw_handler
;
196 tmp_va
= mtk_vcodec_fw_map_dm_addr(handler
,
198 memcpy(inst
->work_bufs
[i
].va
, tmp_va
, wb
[i
].size
);
200 wb
[i
].iova
= inst
->work_bufs
[i
].dma_addr
;
202 mtk_vcodec_debug(inst
,
203 "work_bufs[%d] va=0x%p,iova=%pad,size=%zu",
204 i
, inst
->work_bufs
[i
].va
,
205 &inst
->work_bufs
[i
].dma_addr
,
206 inst
->work_bufs
[i
].size
);
209 mtk_vcodec_debug_leave(inst
);
214 vp8_enc_free_work_buf(inst
);
219 static unsigned int vp8_enc_wait_venc_done(struct venc_vp8_inst
*inst
)
221 unsigned int irq_status
= 0;
222 struct mtk_vcodec_ctx
*ctx
= (struct mtk_vcodec_ctx
*)inst
->ctx
;
224 if (!mtk_vcodec_wait_for_done_ctx(ctx
, MTK_INST_IRQ_RECEIVED
,
225 WAIT_INTR_TIMEOUT_MS
)) {
226 irq_status
= ctx
->irq_status
;
227 mtk_vcodec_debug(inst
, "isr return %x", irq_status
);
233 * Compose ac_tag, bitstream header and bitstream payload into
234 * one bitstream buffer.
236 static int vp8_enc_compose_one_frame(struct venc_vp8_inst
*inst
,
237 struct mtk_vcodec_mem
*bs_buf
,
238 unsigned int *bs_size
)
240 unsigned int not_key
;
243 unsigned int ac_tag_size
;
244 u8 ac_tag
[MAX_AC_TAG_SIZE
];
247 bs_frm_size
= vp8_enc_read_reg(inst
, VENC_BITSTREAM_FRAME_SIZE
);
248 bs_hdr_len
= vp8_enc_read_reg(inst
, VENC_BITSTREAM_HEADER_LEN
);
250 /* if a frame is key frame, not_key is 0 */
251 not_key
= !inst
->vpu_inst
.is_key_frm
;
252 tag
= (bs_hdr_len
<< 5) | 0x10 | not_key
;
253 ac_tag
[0] = tag
& 0xff;
254 ac_tag
[1] = (tag
>> 8) & 0xff;
255 ac_tag
[2] = (tag
>> 16) & 0xff;
259 ac_tag_size
= MAX_AC_TAG_SIZE
;
263 ac_tag
[6] = inst
->vsi
->config
.pic_w
;
264 ac_tag
[7] = inst
->vsi
->config
.pic_w
>> 8;
265 ac_tag
[8] = inst
->vsi
->config
.pic_h
;
266 ac_tag
[9] = inst
->vsi
->config
.pic_h
>> 8;
271 if (bs_buf
->size
< bs_hdr_len
+ bs_frm_size
+ ac_tag_size
) {
272 mtk_vcodec_err(inst
, "bitstream buf size is too small(%zu)",
278 * (1) The vp8 bitstream header and body are generated by the HW vp8
279 * encoder separately at the same time. We cannot know the bitstream
280 * header length in advance.
281 * (2) From the vp8 spec, there is no stuffing byte allowed between the
282 * ac tag, bitstream header and bitstream body.
284 memmove(bs_buf
->va
+ bs_hdr_len
+ ac_tag_size
,
285 bs_buf
->va
, bs_frm_size
);
286 memcpy(bs_buf
->va
+ ac_tag_size
,
287 inst
->work_bufs
[VENC_VP8_VPU_WORK_BUF_BS_HEADER
].va
,
289 memcpy(bs_buf
->va
, ac_tag
, ac_tag_size
);
290 *bs_size
= bs_frm_size
+ bs_hdr_len
+ ac_tag_size
;
295 static int vp8_enc_encode_frame(struct venc_vp8_inst
*inst
,
296 struct venc_frm_buf
*frm_buf
,
297 struct mtk_vcodec_mem
*bs_buf
,
298 unsigned int *bs_size
)
301 unsigned int irq_status
;
303 mtk_vcodec_debug(inst
, "->frm_cnt=%d", inst
->frm_cnt
);
305 ret
= vpu_enc_encode(&inst
->vpu_inst
, 0, frm_buf
, bs_buf
, bs_size
,
310 irq_status
= vp8_enc_wait_venc_done(inst
);
311 if (irq_status
!= MTK_VENC_IRQ_STATUS_FRM
) {
312 mtk_vcodec_err(inst
, "irq_status=%d failed", irq_status
);
316 if (vp8_enc_compose_one_frame(inst
, bs_buf
, bs_size
)) {
317 mtk_vcodec_err(inst
, "vp8_enc_compose_one_frame failed");
322 mtk_vcodec_debug(inst
, "<-size=%d key_frm=%d", *bs_size
,
323 inst
->vpu_inst
.is_key_frm
);
328 static int vp8_enc_init(struct mtk_vcodec_ctx
*ctx
)
331 struct venc_vp8_inst
*inst
;
333 inst
= kzalloc(sizeof(*inst
), GFP_KERNEL
);
338 inst
->vpu_inst
.ctx
= ctx
;
339 inst
->vpu_inst
.id
= IPI_VENC_VP8
;
340 inst
->hw_base
= mtk_vcodec_get_reg_addr(inst
->ctx
, VENC_LT_SYS
);
342 mtk_vcodec_debug_enter(inst
);
344 ret
= vpu_enc_init(&inst
->vpu_inst
);
346 inst
->vsi
= (struct venc_vp8_vsi
*)inst
->vpu_inst
.vsi
;
348 mtk_vcodec_debug_leave(inst
);
353 ctx
->drv_handle
= inst
;
358 static int vp8_enc_encode(void *handle
,
359 enum venc_start_opt opt
,
360 struct venc_frm_buf
*frm_buf
,
361 struct mtk_vcodec_mem
*bs_buf
,
362 struct venc_done_result
*result
)
365 struct venc_vp8_inst
*inst
= (struct venc_vp8_inst
*)handle
;
366 struct mtk_vcodec_ctx
*ctx
= inst
->ctx
;
368 mtk_vcodec_debug_enter(inst
);
370 enable_irq(ctx
->dev
->enc_lt_irq
);
373 case VENC_START_OPT_ENCODE_FRAME
:
374 ret
= vp8_enc_encode_frame(inst
, frm_buf
, bs_buf
,
378 result
->is_key_frm
= inst
->vpu_inst
.is_key_frm
;
382 mtk_vcodec_err(inst
, "opt not support:%d", opt
);
389 disable_irq(ctx
->dev
->enc_lt_irq
);
390 mtk_vcodec_debug_leave(inst
);
395 static int vp8_enc_set_param(void *handle
,
396 enum venc_set_param_type type
,
397 struct venc_enc_param
*enc_prm
)
400 struct venc_vp8_inst
*inst
= (struct venc_vp8_inst
*)handle
;
402 mtk_vcodec_debug(inst
, "->type=%d", type
);
405 case VENC_SET_PARAM_ENC
:
406 inst
->vsi
->config
.input_fourcc
= enc_prm
->input_yuv_fmt
;
407 inst
->vsi
->config
.bitrate
= enc_prm
->bitrate
;
408 inst
->vsi
->config
.pic_w
= enc_prm
->width
;
409 inst
->vsi
->config
.pic_h
= enc_prm
->height
;
410 inst
->vsi
->config
.buf_w
= enc_prm
->buf_width
;
411 inst
->vsi
->config
.buf_h
= enc_prm
->buf_height
;
412 inst
->vsi
->config
.gop_size
= enc_prm
->gop_size
;
413 inst
->vsi
->config
.framerate
= enc_prm
->frm_rate
;
414 inst
->vsi
->config
.ts_mode
= inst
->ts_mode
;
415 ret
= vpu_enc_set_param(&inst
->vpu_inst
, type
, enc_prm
);
418 if (inst
->work_buf_allocated
) {
419 vp8_enc_free_work_buf(inst
);
420 inst
->work_buf_allocated
= false;
422 ret
= vp8_enc_alloc_work_buf(inst
);
425 inst
->work_buf_allocated
= true;
429 * VENC_SET_PARAM_TS_MODE must be called before VENC_SET_PARAM_ENC
431 case VENC_SET_PARAM_TS_MODE
:
433 mtk_vcodec_debug(inst
, "set ts_mode");
437 ret
= vpu_enc_set_param(&inst
->vpu_inst
, type
, enc_prm
);
441 mtk_vcodec_debug_leave(inst
);
446 static int vp8_enc_deinit(void *handle
)
449 struct venc_vp8_inst
*inst
= (struct venc_vp8_inst
*)handle
;
451 mtk_vcodec_debug_enter(inst
);
453 ret
= vpu_enc_deinit(&inst
->vpu_inst
);
455 if (inst
->work_buf_allocated
)
456 vp8_enc_free_work_buf(inst
);
458 mtk_vcodec_debug_leave(inst
);
464 const struct venc_common_if venc_vp8_if
= {
465 .init
= vp8_enc_init
,
466 .encode
= vp8_enc_encode
,
467 .set_param
= vp8_enc_set_param
,
468 .deinit
= vp8_enc_deinit
,