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"
22 #define VENC_BITSTREAM_FRAME_SIZE 0x0098
23 #define VENC_BITSTREAM_HEADER_LEN 0x00e8
25 /* This ac_tag is vp8 frame tag. */
26 #define MAX_AC_TAG_SIZE 10
29 * enum venc_vp8_vpu_work_buf - vp8 encoder buffer index
31 enum venc_vp8_vpu_work_buf
{
32 VENC_VP8_VPU_WORK_BUF_LUMA
,
33 VENC_VP8_VPU_WORK_BUF_LUMA2
,
34 VENC_VP8_VPU_WORK_BUF_LUMA3
,
35 VENC_VP8_VPU_WORK_BUF_CHROMA
,
36 VENC_VP8_VPU_WORK_BUF_CHROMA2
,
37 VENC_VP8_VPU_WORK_BUF_CHROMA3
,
38 VENC_VP8_VPU_WORK_BUF_MV_INFO
,
39 VENC_VP8_VPU_WORK_BUF_BS_HEADER
,
40 VENC_VP8_VPU_WORK_BUF_PROB_BUF
,
41 VENC_VP8_VPU_WORK_BUF_RC_INFO
,
42 VENC_VP8_VPU_WORK_BUF_RC_CODE
,
43 VENC_VP8_VPU_WORK_BUF_RC_CODE2
,
44 VENC_VP8_VPU_WORK_BUF_RC_CODE3
,
45 VENC_VP8_VPU_WORK_BUF_MAX
,
49 * struct venc_vp8_vpu_config - Structure for vp8 encoder configuration
50 * AP-W/R : AP is writer/reader on this item
51 * VPU-W/R: VPU is write/reader on this item
52 * @input_fourcc: input fourcc
53 * @bitrate: target bitrate (in bps)
54 * @pic_w: picture width. Picture size is visible stream resolution, in pixels,
55 * to be used for display purposes; must be smaller or equal to buffer
57 * @pic_h: picture height
58 * @buf_w: buffer width (with 16 alignment). Buffer size is stream resolution
59 * in pixels aligned to hardware requirements.
60 * @buf_h: buffer height (with 16 alignment)
61 * @gop_size: group of picture size (key frame)
62 * @framerate: frame rate in fps
63 * @ts_mode: temporal scalability mode (0: disable, 1: enable)
64 * support three temporal layers - 0: 7.5fps 1: 7.5fps 2: 15fps.
66 struct venc_vp8_vpu_config
{
79 * struct venc_vp8_vpu_buf - Structure for buffer information
80 * AP-W/R : AP is writer/reader on this item
81 * VPU-W/R: VPU is write/reader on this item
82 * @iova: IO virtual address
83 * @vpua: VPU side memory addr which is used by RC_CODE
84 * @size: buffer size (in bytes)
86 struct venc_vp8_vpu_buf
{
93 * struct venc_vp8_vsi - Structure for VPU driver control and info share
94 * AP-W/R : AP is writer/reader on this item
95 * VPU-W/R: VPU is write/reader on this item
96 * This structure is allocated in VPU side and shared to AP side.
97 * @config: vp8 encoder configuration
98 * @work_bufs: working buffer information in VPU side
99 * The work_bufs here is for storing the 'size' info shared to AP side.
100 * The similar item in struct venc_vp8_inst is for memory allocation
101 * in AP side. The AP driver will copy the 'size' from here to the one in
102 * struct mtk_vcodec_mem, then invoke mtk_vcodec_mem_alloc to allocate
103 * the buffer. After that, bypass the 'dma_addr' to the 'iova' field here for
104 * register setting in VPU side.
106 struct venc_vp8_vsi
{
107 struct venc_vp8_vpu_config config
;
108 struct venc_vp8_vpu_buf work_bufs
[VENC_VP8_VPU_WORK_BUF_MAX
];
112 * struct venc_vp8_inst - vp8 encoder AP driver instance
113 * @hw_base: vp8 encoder hardware register base
114 * @work_bufs: working buffer
115 * @work_buf_allocated: working buffer allocated flag
116 * @frm_cnt: encoded frame count, it's used for I-frame judgement and
117 * reset when force intra cmd received.
118 * @ts_mode: temporal scalability mode (0: disable, 1: enable)
119 * support three temporal layers - 0: 7.5fps 1: 7.5fps 2: 15fps.
120 * @vpu_inst: VPU instance to exchange information between AP and VPU
121 * @vsi: driver structure allocated by VPU side and shared to AP side for
122 * control and info share
123 * @ctx: context for v4l2 layer integration
125 struct venc_vp8_inst
{
126 void __iomem
*hw_base
;
127 struct mtk_vcodec_mem work_bufs
[VENC_VP8_VPU_WORK_BUF_MAX
];
128 bool work_buf_allocated
;
129 unsigned int frm_cnt
;
130 unsigned int ts_mode
;
131 struct venc_vpu_inst vpu_inst
;
132 struct venc_vp8_vsi
*vsi
;
133 struct mtk_vcodec_ctx
*ctx
;
136 static inline u32
vp8_enc_read_reg(struct venc_vp8_inst
*inst
, u32 addr
)
138 return readl(inst
->hw_base
+ addr
);
141 static void vp8_enc_free_work_buf(struct venc_vp8_inst
*inst
)
145 mtk_vcodec_debug_enter(inst
);
147 /* Buffers need to be freed by AP. */
148 for (i
= 0; i
< VENC_VP8_VPU_WORK_BUF_MAX
; i
++) {
149 if (inst
->work_bufs
[i
].size
== 0)
151 mtk_vcodec_mem_free(inst
->ctx
, &inst
->work_bufs
[i
]);
154 mtk_vcodec_debug_leave(inst
);
157 static int vp8_enc_alloc_work_buf(struct venc_vp8_inst
*inst
)
161 struct venc_vp8_vpu_buf
*wb
= inst
->vsi
->work_bufs
;
163 mtk_vcodec_debug_enter(inst
);
165 for (i
= 0; i
< VENC_VP8_VPU_WORK_BUF_MAX
; i
++) {
169 * This 'wb' structure is set by VPU side and shared to AP for
170 * buffer allocation and IO virtual addr mapping. For most of
171 * the buffers, AP will allocate the buffer according to 'size'
172 * field and store the IO virtual addr in 'iova' field. For the
173 * RC_CODEx buffers, they are pre-allocated in the VPU side
174 * because they are inside VPU SRAM, and save the VPU addr in
175 * the 'vpua' field. The AP will translate the VPU addr to the
176 * corresponding IO virtual addr and store in 'iova' field.
178 inst
->work_bufs
[i
].size
= wb
[i
].size
;
179 ret
= mtk_vcodec_mem_alloc(inst
->ctx
, &inst
->work_bufs
[i
]);
182 "cannot alloc work_bufs[%d]", i
);
186 * This RC_CODEx is pre-allocated by VPU and saved in VPU addr.
187 * So we need use memcpy to copy RC_CODEx from VPU addr into IO
188 * virtual addr in 'iova' field for reg setting in VPU side.
190 if (i
== VENC_VP8_VPU_WORK_BUF_RC_CODE
||
191 i
== VENC_VP8_VPU_WORK_BUF_RC_CODE2
||
192 i
== VENC_VP8_VPU_WORK_BUF_RC_CODE3
) {
195 tmp_va
= vpu_mapping_dm_addr(inst
->vpu_inst
.dev
,
197 memcpy(inst
->work_bufs
[i
].va
, tmp_va
, wb
[i
].size
);
199 wb
[i
].iova
= inst
->work_bufs
[i
].dma_addr
;
201 mtk_vcodec_debug(inst
,
202 "work_bufs[%d] va=0x%p,iova=%pad,size=%zu",
203 i
, inst
->work_bufs
[i
].va
,
204 &inst
->work_bufs
[i
].dma_addr
,
205 inst
->work_bufs
[i
].size
);
208 mtk_vcodec_debug_leave(inst
);
213 vp8_enc_free_work_buf(inst
);
218 static unsigned int vp8_enc_wait_venc_done(struct venc_vp8_inst
*inst
)
220 unsigned int irq_status
= 0;
221 struct mtk_vcodec_ctx
*ctx
= (struct mtk_vcodec_ctx
*)inst
->ctx
;
223 if (!mtk_vcodec_wait_for_done_ctx(ctx
, MTK_INST_IRQ_RECEIVED
,
224 WAIT_INTR_TIMEOUT_MS
)) {
225 irq_status
= ctx
->irq_status
;
226 mtk_vcodec_debug(inst
, "isr return %x", irq_status
);
232 * Compose ac_tag, bitstream header and bitstream payload into
233 * one bitstream buffer.
235 static int vp8_enc_compose_one_frame(struct venc_vp8_inst
*inst
,
236 struct mtk_vcodec_mem
*bs_buf
,
237 unsigned int *bs_size
)
239 unsigned int not_key
;
242 unsigned int ac_tag_size
;
243 u8 ac_tag
[MAX_AC_TAG_SIZE
];
246 bs_frm_size
= vp8_enc_read_reg(inst
, VENC_BITSTREAM_FRAME_SIZE
);
247 bs_hdr_len
= vp8_enc_read_reg(inst
, VENC_BITSTREAM_HEADER_LEN
);
249 /* if a frame is key frame, not_key is 0 */
250 not_key
= !inst
->vpu_inst
.is_key_frm
;
251 tag
= (bs_hdr_len
<< 5) | 0x10 | not_key
;
252 ac_tag
[0] = tag
& 0xff;
253 ac_tag
[1] = (tag
>> 8) & 0xff;
254 ac_tag
[2] = (tag
>> 16) & 0xff;
258 ac_tag_size
= MAX_AC_TAG_SIZE
;
262 ac_tag
[6] = inst
->vsi
->config
.pic_w
;
263 ac_tag
[7] = inst
->vsi
->config
.pic_w
>> 8;
264 ac_tag
[8] = inst
->vsi
->config
.pic_h
;
265 ac_tag
[9] = inst
->vsi
->config
.pic_h
>> 8;
270 if (bs_buf
->size
< bs_hdr_len
+ bs_frm_size
+ ac_tag_size
) {
271 mtk_vcodec_err(inst
, "bitstream buf size is too small(%zu)",
277 * (1) The vp8 bitstream header and body are generated by the HW vp8
278 * encoder separately at the same time. We cannot know the bitstream
279 * header length in advance.
280 * (2) From the vp8 spec, there is no stuffing byte allowed between the
281 * ac tag, bitstream header and bitstream body.
283 memmove(bs_buf
->va
+ bs_hdr_len
+ ac_tag_size
,
284 bs_buf
->va
, bs_frm_size
);
285 memcpy(bs_buf
->va
+ ac_tag_size
,
286 inst
->work_bufs
[VENC_VP8_VPU_WORK_BUF_BS_HEADER
].va
,
288 memcpy(bs_buf
->va
, ac_tag
, ac_tag_size
);
289 *bs_size
= bs_frm_size
+ bs_hdr_len
+ ac_tag_size
;
294 static int vp8_enc_encode_frame(struct venc_vp8_inst
*inst
,
295 struct venc_frm_buf
*frm_buf
,
296 struct mtk_vcodec_mem
*bs_buf
,
297 unsigned int *bs_size
)
300 unsigned int irq_status
;
302 mtk_vcodec_debug(inst
, "->frm_cnt=%d", inst
->frm_cnt
);
304 ret
= vpu_enc_encode(&inst
->vpu_inst
, 0, frm_buf
, bs_buf
, bs_size
);
308 irq_status
= vp8_enc_wait_venc_done(inst
);
309 if (irq_status
!= MTK_VENC_IRQ_STATUS_FRM
) {
310 mtk_vcodec_err(inst
, "irq_status=%d failed", irq_status
);
314 if (vp8_enc_compose_one_frame(inst
, bs_buf
, bs_size
)) {
315 mtk_vcodec_err(inst
, "vp8_enc_compose_one_frame failed");
320 mtk_vcodec_debug(inst
, "<-size=%d key_frm=%d", *bs_size
,
321 inst
->vpu_inst
.is_key_frm
);
326 static int vp8_enc_init(struct mtk_vcodec_ctx
*ctx
)
329 struct venc_vp8_inst
*inst
;
331 inst
= kzalloc(sizeof(*inst
), GFP_KERNEL
);
336 inst
->vpu_inst
.ctx
= ctx
;
337 inst
->vpu_inst
.dev
= ctx
->dev
->vpu_plat_dev
;
338 inst
->vpu_inst
.id
= IPI_VENC_VP8
;
339 inst
->hw_base
= mtk_vcodec_get_reg_addr(inst
->ctx
, VENC_LT_SYS
);
341 mtk_vcodec_debug_enter(inst
);
343 ret
= vpu_enc_init(&inst
->vpu_inst
);
345 inst
->vsi
= (struct venc_vp8_vsi
*)inst
->vpu_inst
.vsi
;
347 mtk_vcodec_debug_leave(inst
);
352 ctx
->drv_handle
= inst
;
357 static int vp8_enc_encode(void *handle
,
358 enum venc_start_opt opt
,
359 struct venc_frm_buf
*frm_buf
,
360 struct mtk_vcodec_mem
*bs_buf
,
361 struct venc_done_result
*result
)
364 struct venc_vp8_inst
*inst
= (struct venc_vp8_inst
*)handle
;
365 struct mtk_vcodec_ctx
*ctx
= inst
->ctx
;
367 mtk_vcodec_debug_enter(inst
);
369 enable_irq(ctx
->dev
->enc_lt_irq
);
372 case VENC_START_OPT_ENCODE_FRAME
:
373 ret
= vp8_enc_encode_frame(inst
, frm_buf
, bs_buf
,
377 result
->is_key_frm
= inst
->vpu_inst
.is_key_frm
;
381 mtk_vcodec_err(inst
, "opt not support:%d", opt
);
388 disable_irq(ctx
->dev
->enc_lt_irq
);
389 mtk_vcodec_debug_leave(inst
);
394 static int vp8_enc_set_param(void *handle
,
395 enum venc_set_param_type type
,
396 struct venc_enc_param
*enc_prm
)
399 struct venc_vp8_inst
*inst
= (struct venc_vp8_inst
*)handle
;
401 mtk_vcodec_debug(inst
, "->type=%d", type
);
404 case VENC_SET_PARAM_ENC
:
405 inst
->vsi
->config
.input_fourcc
= enc_prm
->input_yuv_fmt
;
406 inst
->vsi
->config
.bitrate
= enc_prm
->bitrate
;
407 inst
->vsi
->config
.pic_w
= enc_prm
->width
;
408 inst
->vsi
->config
.pic_h
= enc_prm
->height
;
409 inst
->vsi
->config
.buf_w
= enc_prm
->buf_width
;
410 inst
->vsi
->config
.buf_h
= enc_prm
->buf_height
;
411 inst
->vsi
->config
.gop_size
= enc_prm
->gop_size
;
412 inst
->vsi
->config
.framerate
= enc_prm
->frm_rate
;
413 inst
->vsi
->config
.ts_mode
= inst
->ts_mode
;
414 ret
= vpu_enc_set_param(&inst
->vpu_inst
, type
, enc_prm
);
417 if (inst
->work_buf_allocated
) {
418 vp8_enc_free_work_buf(inst
);
419 inst
->work_buf_allocated
= false;
421 ret
= vp8_enc_alloc_work_buf(inst
);
424 inst
->work_buf_allocated
= true;
428 * VENC_SET_PARAM_TS_MODE must be called before VENC_SET_PARAM_ENC
430 case VENC_SET_PARAM_TS_MODE
:
432 mtk_vcodec_debug(inst
, "set ts_mode");
436 ret
= vpu_enc_set_param(&inst
->vpu_inst
, type
, enc_prm
);
440 mtk_vcodec_debug_leave(inst
);
445 static int vp8_enc_deinit(void *handle
)
448 struct venc_vp8_inst
*inst
= (struct venc_vp8_inst
*)handle
;
450 mtk_vcodec_debug_enter(inst
);
452 ret
= vpu_enc_deinit(&inst
->vpu_inst
);
454 if (inst
->work_buf_allocated
)
455 vp8_enc_free_work_buf(inst
);
457 mtk_vcodec_debug_leave(inst
);
463 const struct venc_common_if venc_vp8_if
= {
464 .init
= vp8_enc_init
,
465 .encode
= vp8_enc_encode
,
466 .set_param
= vp8_enc_set_param
,
467 .deinit
= vp8_enc_deinit
,