2 * Copyright (c) 2016 MediaTek Inc.
3 * Author: Daniel Hsiao <daniel.hsiao@mediatek.com>
4 * Kai-Sean Yang <kai-sean.yang@mediatek.com>
5 * Tiffany Lin <tiffany.lin@mediatek.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
18 #include <linux/slab.h>
19 #include <linux/syscalls.h>
20 #include <linux/delay.h>
21 #include <linux/time.h>
23 #include "../mtk_vcodec_intr.h"
24 #include "../vdec_drv_base.h"
25 #include "../vdec_vpu_if.h"
27 #define VP9_SUPER_FRAME_BS_SZ 64
28 #define MAX_VP9_DPB_SIZE 9
30 #define REFS_PER_FRAME 3
31 #define MAX_NUM_REF_FRAMES 8
32 #define VP9_MAX_FRM_BUF_NUM 9
33 #define VP9_MAX_FRM_BUF_NODE_NUM (VP9_MAX_FRM_BUF_NUM * 2)
34 #define VP9_SEG_ID_SZ 0x12000
37 * struct vp9_dram_buf - contains buffer info for vpu
41 * @padding : for 64 bytes alignment
51 * struct vp9_fb_info - contains frame buffer info
53 * @reserved : reserved field used by vpu
57 unsigned int reserved
[32];
61 * struct vp9_ref_cnt_buf - contains reference buffer information
62 * @buf : referenced frame buffer
63 * @ref_cnt : referenced frame buffer's reference count.
64 * When reference count=0, remove it from reference list
66 struct vp9_ref_cnt_buf
{
67 struct vp9_fb_info buf
;
72 * struct vp9_fb_info - contains current frame's reference buffer information
73 * @buf : reference buffer
74 * @idx : reference buffer index to frm_bufs
75 * @reserved : reserved field used by vpu
78 struct vp9_fb_info
*buf
;
80 unsigned int reserved
[6];
84 * struct vp9_fb_info - contains frame buffer info
85 * @fb : super frame reference frame buffer
86 * @used : this reference frame info entry is used
87 * @padding : for 64 bytes size align
89 struct vp9_sf_ref_fb
{
96 * struct vdec_vp9_vsi - shared buffer between host and VPU firmware
97 * AP-W/R : AP is writer/reader on this item
98 * VPU-W/R: VPU is write/reader on this item
99 * @sf_bs_buf : super frame backup buffer (AP-W, VPU-R)
100 * @sf_ref_fb : record supoer frame reference buffer information
102 * @sf_next_ref_fb_idx : next available super frame (AP-W, VPU-R)
103 * @sf_frm_cnt : super frame count, filled by vpu (AP-R, VPU-W)
104 * @sf_frm_offset : super frame offset, filled by vpu (AP-R, VPU-W)
105 * @sf_frm_sz : super frame size, filled by vpu (AP-R, VPU-W)
106 * @sf_frm_idx : current super frame (AP-R, VPU-W)
107 * @sf_init : inform super frame info already parsed by vpu (AP-R, VPU-W)
108 * @fb : capture buffer (AP-W, VPU-R)
109 * @bs : bs buffer (AP-W, VPU-R)
110 * @cur_fb : current show capture buffer (AP-R/W, VPU-R/W)
111 * @pic_w : picture width (AP-R, VPU-W)
112 * @pic_h : picture height (AP-R, VPU-W)
113 * @buf_w : codec width (AP-R, VPU-W)
114 * @buf_h : coded height (AP-R, VPU-W)
115 * @buf_sz_y_bs : ufo compressed y plane size (AP-R, VPU-W)
116 * @buf_sz_c_bs : ufo compressed cbcr plane size (AP-R, VPU-W)
117 * @buf_len_sz_y : size used to store y plane ufo info (AP-R, VPU-W)
118 * @buf_len_sz_c : size used to store cbcr plane ufo info (AP-R, VPU-W)
120 * @profile : profile sparsed from vpu (AP-R, VPU-W)
121 * @show_frame : display this frame or not (AP-R, VPU-W)
122 * @show_existing_frame : inform this frame is show existing frame
124 * @frm_to_show_idx : index to show frame (AP-R, VPU-W)
126 * @refresh_frm_flags : indicate when frame need to refine reference count
128 * @resolution_changed : resolution change in this frame (AP-R, VPU-W)
130 * @frm_bufs : maintain reference buffer info (AP-R/W, VPU-R/W)
131 * @ref_frm_map : maintain reference buffer map info (AP-R/W, VPU-R/W)
132 * @new_fb_idx : index to frm_bufs array (AP-R, VPU-W)
133 * @frm_num : decoded frame number, include sub-frame count (AP-R, VPU-W)
134 * @mv_buf : motion vector working buffer (AP-W, VPU-R)
135 * @frm_refs : maintain three reference buffer info (AP-R/W, VPU-R/W)
136 * @seg_id_buf : segmentation map working buffer (AP-W, VPU-R)
138 struct vdec_vp9_vsi
{
139 unsigned char sf_bs_buf
[VP9_SUPER_FRAME_BS_SZ
];
140 struct vp9_sf_ref_fb sf_ref_fb
[VP9_MAX_FRM_BUF_NUM
-1];
141 int sf_next_ref_fb_idx
;
142 unsigned int sf_frm_cnt
;
143 unsigned int sf_frm_offset
[VP9_MAX_FRM_BUF_NUM
-1];
144 unsigned int sf_frm_sz
[VP9_MAX_FRM_BUF_NUM
-1];
145 unsigned int sf_frm_idx
;
146 unsigned int sf_init
;
148 struct mtk_vcodec_mem bs
;
149 struct vdec_fb cur_fb
;
154 unsigned int buf_sz_y_bs
;
155 unsigned int buf_sz_c_bs
;
156 unsigned int buf_len_sz_y
;
157 unsigned int buf_len_sz_c
;
158 unsigned int profile
;
159 unsigned int show_frame
;
160 unsigned int show_existing_frame
;
161 unsigned int frm_to_show_idx
;
162 unsigned int refresh_frm_flags
;
163 unsigned int resolution_changed
;
165 struct vp9_ref_cnt_buf frm_bufs
[VP9_MAX_FRM_BUF_NUM
];
166 int ref_frm_map
[MAX_NUM_REF_FRAMES
];
167 unsigned int new_fb_idx
;
168 unsigned int frm_num
;
169 struct vp9_dram_buf mv_buf
;
171 struct vp9_ref_buf frm_refs
[REFS_PER_FRAME
];
172 struct vp9_dram_buf seg_id_buf
;
177 * struct vdec_vp9_inst - vp9 decode instance
178 * @mv_buf : working buffer for mv
179 * @seg_id_buf : working buffer for segmentation map
180 * @dec_fb : vdec_fb node to link fb to different fb_xxx_list
181 * @available_fb_node_list : current available vdec_fb node
182 * @fb_use_list : current used or referenced vdec_fb
183 * @fb_free_list : current available to free vdec_fb
184 * @fb_disp_list : current available to display vdec_fb
185 * @cur_fb : current frame buffer
186 * @ctx : current decode context
187 * @vpu : vpu instance information
188 * @vsi : shared buffer between host and VPU firmware
189 * @total_frm_cnt : total frame count, it do not include sub-frames in super
191 * @mem : instance memory information
193 struct vdec_vp9_inst
{
194 struct mtk_vcodec_mem mv_buf
;
195 struct mtk_vcodec_mem seg_id_buf
;
197 struct vdec_fb_node dec_fb
[VP9_MAX_FRM_BUF_NODE_NUM
];
198 struct list_head available_fb_node_list
;
199 struct list_head fb_use_list
;
200 struct list_head fb_free_list
;
201 struct list_head fb_disp_list
;
202 struct vdec_fb
*cur_fb
;
203 struct mtk_vcodec_ctx
*ctx
;
204 struct vdec_vpu_inst vpu
;
205 struct vdec_vp9_vsi
*vsi
;
206 unsigned int total_frm_cnt
;
207 struct mtk_vcodec_mem mem
;
210 static bool vp9_is_sf_ref_fb(struct vdec_vp9_inst
*inst
, struct vdec_fb
*fb
)
213 struct vdec_vp9_vsi
*vsi
= inst
->vsi
;
215 for (i
= 0; i
< ARRAY_SIZE(vsi
->sf_ref_fb
); i
++) {
216 if (fb
== &vsi
->sf_ref_fb
[i
].fb
)
222 static struct vdec_fb
*vp9_rm_from_fb_use_list(struct vdec_vp9_inst
225 struct vdec_fb
*fb
= NULL
;
226 struct vdec_fb_node
*node
;
228 list_for_each_entry(node
, &inst
->fb_use_list
, list
) {
229 fb
= (struct vdec_fb
*)node
->fb
;
230 if (fb
->base_y
.va
== addr
) {
231 list_move_tail(&node
->list
,
232 &inst
->available_fb_node_list
);
239 static void vp9_add_to_fb_free_list(struct vdec_vp9_inst
*inst
,
242 struct vdec_fb_node
*node
;
245 node
= list_first_entry_or_null(&inst
->available_fb_node_list
,
246 struct vdec_fb_node
, list
);
250 list_move_tail(&node
->list
, &inst
->fb_free_list
);
253 mtk_vcodec_debug(inst
, "No free fb node");
257 static void vp9_free_sf_ref_fb(struct vdec_fb
*fb
)
259 struct vp9_sf_ref_fb
*sf_ref_fb
=
260 container_of(fb
, struct vp9_sf_ref_fb
, fb
);
265 static void vp9_ref_cnt_fb(struct vdec_vp9_inst
*inst
, int *idx
,
268 struct vdec_vp9_vsi
*vsi
= inst
->vsi
;
271 if (ref_idx
>= 0 && vsi
->frm_bufs
[ref_idx
].ref_cnt
> 0) {
272 vsi
->frm_bufs
[ref_idx
].ref_cnt
--;
274 if (vsi
->frm_bufs
[ref_idx
].ref_cnt
== 0) {
275 if (!vp9_is_sf_ref_fb(inst
,
276 vsi
->frm_bufs
[ref_idx
].buf
.fb
)) {
279 fb
= vp9_rm_from_fb_use_list(inst
,
280 vsi
->frm_bufs
[ref_idx
].buf
.fb
->base_y
.va
);
281 vp9_add_to_fb_free_list(inst
, fb
);
284 vsi
->frm_bufs
[ref_idx
].buf
.fb
);
289 vsi
->frm_bufs
[new_idx
].ref_cnt
++;
292 static void vp9_free_all_sf_ref_fb(struct vdec_vp9_inst
*inst
)
295 struct vdec_vp9_vsi
*vsi
= inst
->vsi
;
297 for (i
= 0; i
< ARRAY_SIZE(vsi
->sf_ref_fb
); i
++) {
298 if (vsi
->sf_ref_fb
[i
].fb
.base_y
.va
) {
299 mtk_vcodec_mem_free(inst
->ctx
,
300 &vsi
->sf_ref_fb
[i
].fb
.base_y
);
301 mtk_vcodec_mem_free(inst
->ctx
,
302 &vsi
->sf_ref_fb
[i
].fb
.base_c
);
303 vsi
->sf_ref_fb
[i
].used
= 0;
308 /* For each sub-frame except the last one, the driver will dynamically
309 * allocate reference buffer by calling vp9_get_sf_ref_fb()
310 * The last sub-frame will use the original fb provided by the
311 * vp9_dec_decode() interface
313 static int vp9_get_sf_ref_fb(struct vdec_vp9_inst
*inst
)
316 struct mtk_vcodec_mem
*mem_basy_y
;
317 struct mtk_vcodec_mem
*mem_basy_c
;
318 struct vdec_vp9_vsi
*vsi
= inst
->vsi
;
321 idx
< ARRAY_SIZE(vsi
->sf_ref_fb
);
323 if (vsi
->sf_ref_fb
[idx
].fb
.base_y
.va
&&
324 vsi
->sf_ref_fb
[idx
].used
== 0) {
330 idx
< ARRAY_SIZE(vsi
->sf_ref_fb
);
332 if (vsi
->sf_ref_fb
[idx
].fb
.base_y
.va
== NULL
)
336 if (idx
== ARRAY_SIZE(vsi
->sf_ref_fb
)) {
337 mtk_vcodec_err(inst
, "List Full");
341 mem_basy_y
= &vsi
->sf_ref_fb
[idx
].fb
.base_y
;
342 mem_basy_y
->size
= vsi
->buf_sz_y_bs
+
345 if (mtk_vcodec_mem_alloc(inst
->ctx
, mem_basy_y
)) {
346 mtk_vcodec_err(inst
, "Cannot allocate sf_ref_buf y_buf");
350 mem_basy_c
= &vsi
->sf_ref_fb
[idx
].fb
.base_c
;
351 mem_basy_c
->size
= vsi
->buf_sz_c_bs
+
354 if (mtk_vcodec_mem_alloc(inst
->ctx
, mem_basy_c
)) {
355 mtk_vcodec_err(inst
, "Cannot allocate sf_ref_fb c_buf");
358 vsi
->sf_ref_fb
[idx
].used
= 0;
363 static bool vp9_alloc_work_buf(struct vdec_vp9_inst
*inst
)
365 struct vdec_vp9_vsi
*vsi
= inst
->vsi
;
367 struct mtk_vcodec_mem
*mem
;
369 unsigned int max_pic_w
;
370 unsigned int max_pic_h
;
373 if (!(inst
->ctx
->dev
->dec_capability
&
374 VCODEC_CAPABILITY_4K_DISABLED
)) {
375 max_pic_w
= VCODEC_DEC_4K_CODED_WIDTH
;
376 max_pic_h
= VCODEC_DEC_4K_CODED_HEIGHT
;
378 max_pic_w
= MTK_VDEC_MAX_W
;
379 max_pic_h
= MTK_VDEC_MAX_H
;
382 if ((vsi
->pic_w
> max_pic_w
) ||
383 (vsi
->pic_h
> max_pic_h
)) {
384 mtk_vcodec_err(inst
, "Invalid w/h %d/%d",
385 vsi
->pic_w
, vsi
->pic_h
);
389 mtk_vcodec_debug(inst
, "BUF CHG(%d): w/h/sb_w/sb_h=%d/%d/%d/%d",
390 vsi
->resolution_changed
,
398 mtk_vcodec_mem_free(inst
->ctx
, mem
);
400 mem
->size
= ((vsi
->buf_w
/ 64) *
401 (vsi
->buf_h
/ 64) + 2) * 36 * 16;
402 result
= mtk_vcodec_mem_alloc(inst
->ctx
, mem
);
405 mtk_vcodec_err(inst
, "Cannot allocate mv_buf");
408 /* Set the va again */
409 vsi
->mv_buf
.va
= (unsigned long)mem
->va
;
410 vsi
->mv_buf
.pa
= (unsigned long)mem
->dma_addr
;
411 vsi
->mv_buf
.sz
= (unsigned int)mem
->size
;
414 mem
= &inst
->seg_id_buf
;
416 mtk_vcodec_mem_free(inst
->ctx
, mem
);
418 mem
->size
= VP9_SEG_ID_SZ
;
419 result
= mtk_vcodec_mem_alloc(inst
->ctx
, mem
);
422 mtk_vcodec_err(inst
, "Cannot allocate seg_id_buf");
425 /* Set the va again */
426 vsi
->seg_id_buf
.va
= (unsigned long)mem
->va
;
427 vsi
->seg_id_buf
.pa
= (unsigned long)mem
->dma_addr
;
428 vsi
->seg_id_buf
.sz
= (unsigned int)mem
->size
;
431 vp9_free_all_sf_ref_fb(inst
);
432 vsi
->sf_next_ref_fb_idx
= vp9_get_sf_ref_fb(inst
);
437 static bool vp9_add_to_fb_disp_list(struct vdec_vp9_inst
*inst
,
440 struct vdec_fb_node
*node
;
443 mtk_vcodec_err(inst
, "fb == NULL");
447 node
= list_first_entry_or_null(&inst
->available_fb_node_list
,
448 struct vdec_fb_node
, list
);
451 list_move_tail(&node
->list
, &inst
->fb_disp_list
);
453 mtk_vcodec_err(inst
, "No available fb node");
460 /* If any buffer updating is signaled it should be done here. */
461 static void vp9_swap_frm_bufs(struct vdec_vp9_inst
*inst
)
463 struct vdec_vp9_vsi
*vsi
= inst
->vsi
;
464 struct vp9_fb_info
*frm_to_show
;
465 int ref_index
= 0, mask
;
467 for (mask
= vsi
->refresh_frm_flags
; mask
; mask
>>= 1) {
469 vp9_ref_cnt_fb(inst
, &vsi
->ref_frm_map
[ref_index
],
474 frm_to_show
= &vsi
->frm_bufs
[vsi
->new_fb_idx
].buf
;
475 vsi
->frm_bufs
[vsi
->new_fb_idx
].ref_cnt
--;
477 if (frm_to_show
->fb
!= inst
->cur_fb
) {
478 /* This frame is show exist frame and no decode output
479 * copy frame data from frm_to_show to current CAPTURE
482 if ((frm_to_show
->fb
!= NULL
) &&
483 (inst
->cur_fb
->base_y
.size
>=
484 frm_to_show
->fb
->base_y
.size
)) {
485 memcpy((void *)inst
->cur_fb
->base_y
.va
,
486 (void *)frm_to_show
->fb
->base_y
.va
,
489 memcpy((void *)inst
->cur_fb
->base_c
.va
,
490 (void *)frm_to_show
->fb
->base_c
.va
,
494 /* After resolution change case, current CAPTURE buffer
495 * may have less buffer size than frm_to_show buffer
498 if (frm_to_show
->fb
!= NULL
)
500 "inst->cur_fb->base_y.size=%zu, frm_to_show->fb.base_y.size=%zu",
501 inst
->cur_fb
->base_y
.size
,
502 frm_to_show
->fb
->base_y
.size
);
504 if (!vp9_is_sf_ref_fb(inst
, inst
->cur_fb
)) {
506 vp9_add_to_fb_disp_list(inst
, inst
->cur_fb
);
509 if (!vp9_is_sf_ref_fb(inst
, inst
->cur_fb
)) {
511 vp9_add_to_fb_disp_list(inst
, frm_to_show
->fb
);
515 /* when ref_cnt ==0, move this fb to fb_free_list. v4l2 driver will
518 if (vsi
->frm_bufs
[vsi
->new_fb_idx
].ref_cnt
== 0) {
519 if (!vp9_is_sf_ref_fb(
520 inst
, vsi
->frm_bufs
[vsi
->new_fb_idx
].buf
.fb
)) {
523 fb
= vp9_rm_from_fb_use_list(inst
,
524 vsi
->frm_bufs
[vsi
->new_fb_idx
].buf
.fb
->base_y
.va
);
526 vp9_add_to_fb_free_list(inst
, fb
);
529 vsi
->frm_bufs
[vsi
->new_fb_idx
].buf
.fb
);
533 /* if this super frame and it is not last sub-frame, get next fb for
536 if (vsi
->sf_frm_cnt
> 0 && vsi
->sf_frm_idx
!= vsi
->sf_frm_cnt
- 1)
537 vsi
->sf_next_ref_fb_idx
= vp9_get_sf_ref_fb(inst
);
540 static bool vp9_wait_dec_end(struct vdec_vp9_inst
*inst
)
542 struct mtk_vcodec_ctx
*ctx
= inst
->ctx
;
544 mtk_vcodec_wait_for_done_ctx(inst
->ctx
,
545 MTK_INST_IRQ_RECEIVED
,
546 WAIT_INTR_TIMEOUT_MS
);
548 if (ctx
->irq_status
& MTK_VDEC_IRQ_STATUS_DEC_SUCCESS
)
554 static struct vdec_vp9_inst
*vp9_alloc_inst(struct mtk_vcodec_ctx
*ctx
)
557 struct mtk_vcodec_mem mem
;
558 struct vdec_vp9_inst
*inst
;
560 memset(&mem
, 0, sizeof(mem
));
561 mem
.size
= sizeof(struct vdec_vp9_inst
);
562 result
= mtk_vcodec_mem_alloc(ctx
, &mem
);
572 static void vp9_free_inst(struct vdec_vp9_inst
*inst
)
574 struct mtk_vcodec_mem mem
;
578 mtk_vcodec_mem_free(inst
->ctx
, &mem
);
581 static bool vp9_decode_end_proc(struct vdec_vp9_inst
*inst
)
583 struct vdec_vp9_vsi
*vsi
= inst
->vsi
;
586 if (!vsi
->show_existing_frame
) {
587 ret
= vp9_wait_dec_end(inst
);
589 mtk_vcodec_err(inst
, "Decode failed, Decode Timeout @[%d]",
594 if (vpu_dec_end(&inst
->vpu
)) {
595 mtk_vcodec_err(inst
, "vp9_dec_vpu_end failed");
598 mtk_vcodec_debug(inst
, "Decode Ok @%d (%d/%d)", vsi
->frm_num
,
599 vsi
->pic_w
, vsi
->pic_h
);
601 mtk_vcodec_debug(inst
, "Decode Ok @%d (show_existing_frame)",
605 vp9_swap_frm_bufs(inst
);
610 static bool vp9_is_last_sub_frm(struct vdec_vp9_inst
*inst
)
612 struct vdec_vp9_vsi
*vsi
= inst
->vsi
;
614 if (vsi
->sf_frm_cnt
<= 0 || vsi
->sf_frm_idx
== vsi
->sf_frm_cnt
)
620 static struct vdec_fb
*vp9_rm_from_fb_disp_list(struct vdec_vp9_inst
*inst
)
622 struct vdec_fb_node
*node
;
623 struct vdec_fb
*fb
= NULL
;
625 node
= list_first_entry_or_null(&inst
->fb_disp_list
,
626 struct vdec_fb_node
, list
);
628 fb
= (struct vdec_fb
*)node
->fb
;
629 fb
->status
|= FB_ST_DISPLAY
;
630 list_move_tail(&node
->list
, &inst
->available_fb_node_list
);
631 mtk_vcodec_debug(inst
, "[FB] get disp fb %p st=%d",
632 node
->fb
, fb
->status
);
634 mtk_vcodec_debug(inst
, "[FB] there is no disp fb");
639 static bool vp9_add_to_fb_use_list(struct vdec_vp9_inst
*inst
,
642 struct vdec_fb_node
*node
;
645 mtk_vcodec_debug(inst
, "fb == NULL");
649 node
= list_first_entry_or_null(&inst
->available_fb_node_list
,
650 struct vdec_fb_node
, list
);
653 list_move_tail(&node
->list
, &inst
->fb_use_list
);
655 mtk_vcodec_err(inst
, "No free fb node");
661 static void vp9_reset(struct vdec_vp9_inst
*inst
)
663 struct vdec_fb_node
*node
, *tmp
;
665 list_for_each_entry_safe(node
, tmp
, &inst
->fb_use_list
, list
)
666 list_move_tail(&node
->list
, &inst
->fb_free_list
);
668 vp9_free_all_sf_ref_fb(inst
);
669 inst
->vsi
->sf_next_ref_fb_idx
= vp9_get_sf_ref_fb(inst
);
671 if (vpu_dec_reset(&inst
->vpu
))
672 mtk_vcodec_err(inst
, "vp9_dec_vpu_reset failed");
674 /* Set the va again, since vpu_dec_reset will clear mv_buf in vpu */
675 inst
->vsi
->mv_buf
.va
= (unsigned long)inst
->mv_buf
.va
;
676 inst
->vsi
->mv_buf
.pa
= (unsigned long)inst
->mv_buf
.dma_addr
;
677 inst
->vsi
->mv_buf
.sz
= (unsigned long)inst
->mv_buf
.size
;
679 /* Set the va again, since vpu_dec_reset will clear seg_id_buf in vpu */
680 inst
->vsi
->seg_id_buf
.va
= (unsigned long)inst
->seg_id_buf
.va
;
681 inst
->vsi
->seg_id_buf
.pa
= (unsigned long)inst
->seg_id_buf
.dma_addr
;
682 inst
->vsi
->seg_id_buf
.sz
= (unsigned long)inst
->seg_id_buf
.size
;
686 static void init_all_fb_lists(struct vdec_vp9_inst
*inst
)
690 INIT_LIST_HEAD(&inst
->available_fb_node_list
);
691 INIT_LIST_HEAD(&inst
->fb_use_list
);
692 INIT_LIST_HEAD(&inst
->fb_free_list
);
693 INIT_LIST_HEAD(&inst
->fb_disp_list
);
695 for (i
= 0; i
< ARRAY_SIZE(inst
->dec_fb
); i
++) {
696 INIT_LIST_HEAD(&inst
->dec_fb
[i
].list
);
697 inst
->dec_fb
[i
].fb
= NULL
;
698 list_add_tail(&inst
->dec_fb
[i
].list
,
699 &inst
->available_fb_node_list
);
703 static void get_pic_info(struct vdec_vp9_inst
*inst
, struct vdec_pic_info
*pic
)
705 pic
->y_bs_sz
= inst
->vsi
->buf_sz_y_bs
;
706 pic
->c_bs_sz
= inst
->vsi
->buf_sz_c_bs
;
707 pic
->y_len_sz
= inst
->vsi
->buf_len_sz_y
;
708 pic
->c_len_sz
= inst
->vsi
->buf_len_sz_c
;
710 pic
->pic_w
= inst
->vsi
->pic_w
;
711 pic
->pic_h
= inst
->vsi
->pic_h
;
712 pic
->buf_w
= inst
->vsi
->buf_w
;
713 pic
->buf_h
= inst
->vsi
->buf_h
;
715 mtk_vcodec_debug(inst
, "pic(%d, %d), buf(%d, %d)",
716 pic
->pic_w
, pic
->pic_h
, pic
->buf_w
, pic
->buf_h
);
717 mtk_vcodec_debug(inst
, "Y(%d, %d), C(%d, %d)", pic
->y_bs_sz
,
718 pic
->y_len_sz
, pic
->c_bs_sz
, pic
->c_len_sz
);
721 static void get_disp_fb(struct vdec_vp9_inst
*inst
, struct vdec_fb
**out_fb
)
724 *out_fb
= vp9_rm_from_fb_disp_list(inst
);
726 (*out_fb
)->status
|= FB_ST_DISPLAY
;
729 static void get_free_fb(struct vdec_vp9_inst
*inst
, struct vdec_fb
**out_fb
)
731 struct vdec_fb_node
*node
;
732 struct vdec_fb
*fb
= NULL
;
734 node
= list_first_entry_or_null(&inst
->fb_free_list
,
735 struct vdec_fb_node
, list
);
737 list_move_tail(&node
->list
, &inst
->available_fb_node_list
);
738 fb
= (struct vdec_fb
*)node
->fb
;
739 fb
->status
|= FB_ST_FREE
;
740 mtk_vcodec_debug(inst
, "[FB] get free fb %p st=%d",
741 node
->fb
, fb
->status
);
743 mtk_vcodec_debug(inst
, "[FB] there is no free fb");
749 static int validate_vsi_array_indexes(struct vdec_vp9_inst
*inst
,
750 struct vdec_vp9_vsi
*vsi
) {
751 if (vsi
->sf_frm_idx
>= VP9_MAX_FRM_BUF_NUM
- 1) {
752 mtk_vcodec_err(inst
, "Invalid vsi->sf_frm_idx=%u.",
756 if (vsi
->frm_to_show_idx
>= VP9_MAX_FRM_BUF_NUM
) {
757 mtk_vcodec_err(inst
, "Invalid vsi->frm_to_show_idx=%u.",
758 vsi
->frm_to_show_idx
);
761 if (vsi
->new_fb_idx
>= VP9_MAX_FRM_BUF_NUM
) {
762 mtk_vcodec_err(inst
, "Invalid vsi->new_fb_idx=%u.",
769 static void vdec_vp9_deinit(unsigned long h_vdec
)
771 struct vdec_vp9_inst
*inst
= (struct vdec_vp9_inst
*)h_vdec
;
772 struct mtk_vcodec_mem
*mem
;
775 ret
= vpu_dec_deinit(&inst
->vpu
);
777 mtk_vcodec_err(inst
, "vpu_dec_deinit failed");
781 mtk_vcodec_mem_free(inst
->ctx
, mem
);
783 mem
= &inst
->seg_id_buf
;
785 mtk_vcodec_mem_free(inst
->ctx
, mem
);
787 vp9_free_all_sf_ref_fb(inst
);
791 static int vdec_vp9_init(struct mtk_vcodec_ctx
*ctx
, unsigned long *h_vdec
)
793 struct vdec_vp9_inst
*inst
;
795 inst
= vp9_alloc_inst(ctx
);
799 inst
->total_frm_cnt
= 0;
802 inst
->vpu
.id
= IPI_VDEC_VP9
;
803 inst
->vpu
.dev
= ctx
->dev
->vpu_plat_dev
;
805 inst
->vpu
.handler
= vpu_dec_ipi_handler
;
807 if (vpu_dec_init(&inst
->vpu
)) {
808 mtk_vcodec_err(inst
, "vp9_dec_vpu_init failed");
809 goto err_deinit_inst
;
812 inst
->vsi
= (struct vdec_vp9_vsi
*)inst
->vpu
.vsi
;
813 init_all_fb_lists(inst
);
815 (*h_vdec
) = (unsigned long)inst
;
824 static int vdec_vp9_decode(unsigned long h_vdec
, struct mtk_vcodec_mem
*bs
,
825 struct vdec_fb
*fb
, bool *res_chg
)
828 struct vdec_vp9_inst
*inst
= (struct vdec_vp9_inst
*)h_vdec
;
829 struct vdec_vp9_vsi
*vsi
= inst
->vsi
;
835 if ((bs
== NULL
) && (fb
== NULL
)) {
836 mtk_vcodec_debug(inst
, "[EOS]");
842 mtk_vcodec_err(inst
, "bs == NULL");
846 mtk_vcodec_debug(inst
, "Input BS Size = %zu", bs
->size
);
849 struct vdec_fb
*cur_fb
= NULL
;
851 data
[0] = *((unsigned int *)bs
->va
);
852 data
[1] = *((unsigned int *)(bs
->va
+ 4));
853 data
[2] = *((unsigned int *)(bs
->va
+ 8));
861 unsigned int sf_bs_sz
;
862 unsigned int sf_bs_off
;
863 unsigned char *sf_bs_src
;
864 unsigned char *sf_bs_dst
;
866 sf_bs_sz
= bs
->size
> VP9_SUPER_FRAME_BS_SZ
?
867 VP9_SUPER_FRAME_BS_SZ
: bs
->size
;
868 sf_bs_off
= VP9_SUPER_FRAME_BS_SZ
- sf_bs_sz
;
869 sf_bs_src
= bs
->va
+ bs
->size
- sf_bs_sz
;
870 sf_bs_dst
= vsi
->sf_bs_buf
+ sf_bs_off
;
871 memcpy(sf_bs_dst
, sf_bs_src
, sf_bs_sz
);
873 if ((vsi
->sf_frm_cnt
> 0) &&
874 (vsi
->sf_frm_idx
< vsi
->sf_frm_cnt
)) {
875 unsigned int idx
= vsi
->sf_frm_idx
;
877 memcpy((void *)bs
->va
,
879 vsi
->sf_frm_offset
[idx
]),
880 vsi
->sf_frm_sz
[idx
]);
883 memset(inst
->seg_id_buf
.va
, 0, inst
->seg_id_buf
.size
);
884 ret
= vpu_dec_start(&inst
->vpu
, data
, 3);
886 mtk_vcodec_err(inst
, "vpu_dec_start failed");
890 ret
= validate_vsi_array_indexes(inst
, vsi
);
892 mtk_vcodec_err(inst
, "Invalid values from VPU.");
896 if (vsi
->resolution_changed
) {
897 if (!vp9_alloc_work_buf(inst
)) {
903 if (vsi
->sf_frm_cnt
> 0) {
904 cur_fb
= &vsi
->sf_ref_fb
[vsi
->sf_next_ref_fb_idx
].fb
;
906 if (vsi
->sf_frm_idx
< vsi
->sf_frm_cnt
)
907 inst
->cur_fb
= cur_fb
;
914 vsi
->frm_bufs
[vsi
->new_fb_idx
].buf
.fb
= inst
->cur_fb
;
915 if (!vp9_is_sf_ref_fb(inst
, inst
->cur_fb
))
916 vp9_add_to_fb_use_list(inst
, inst
->cur_fb
);
918 mtk_vcodec_debug(inst
, "[#pic %d]", vsi
->frm_num
);
920 if (vsi
->show_existing_frame
)
921 mtk_vcodec_debug(inst
,
922 "drv->new_fb_idx=%d, drv->frm_to_show_idx=%d",
923 vsi
->new_fb_idx
, vsi
->frm_to_show_idx
);
925 if (vsi
->show_existing_frame
&& (vsi
->frm_to_show_idx
<
926 VP9_MAX_FRM_BUF_NUM
)) {
928 "Skip Decode drv->new_fb_idx=%d, drv->frm_to_show_idx=%d",
929 vsi
->new_fb_idx
, vsi
->frm_to_show_idx
);
931 vp9_ref_cnt_fb(inst
, &vsi
->new_fb_idx
,
932 vsi
->frm_to_show_idx
);
937 /* VPU assign the buffer pointer in its address space,
940 for (i
= 0; i
< ARRAY_SIZE(vsi
->frm_refs
); i
++) {
941 unsigned int idx
= vsi
->frm_refs
[i
].idx
;
943 vsi
->frm_refs
[i
].buf
= &vsi
->frm_bufs
[idx
].buf
;
946 if (vsi
->resolution_changed
) {
948 mtk_vcodec_debug(inst
, "VDEC_ST_RESOLUTION_CHANGED");
954 if (vp9_decode_end_proc(inst
) != true) {
955 mtk_vcodec_err(inst
, "vp9_decode_end_proc");
960 if (vp9_is_last_sub_frm(inst
))
964 inst
->total_frm_cnt
++;
968 vp9_add_to_fb_free_list(inst
, fb
);
973 static void get_crop_info(struct vdec_vp9_inst
*inst
, struct v4l2_rect
*cr
)
977 cr
->width
= inst
->vsi
->pic_w
;
978 cr
->height
= inst
->vsi
->pic_h
;
979 mtk_vcodec_debug(inst
, "get crop info l=%d, t=%d, w=%d, h=%d\n",
980 cr
->left
, cr
->top
, cr
->width
, cr
->height
);
983 static int vdec_vp9_get_param(unsigned long h_vdec
,
984 enum vdec_get_param_type type
, void *out
)
986 struct vdec_vp9_inst
*inst
= (struct vdec_vp9_inst
*)h_vdec
;
990 case GET_PARAM_DISP_FRAME_BUFFER
:
991 get_disp_fb(inst
, out
);
993 case GET_PARAM_FREE_FRAME_BUFFER
:
994 get_free_fb(inst
, out
);
996 case GET_PARAM_PIC_INFO
:
997 get_pic_info(inst
, out
);
999 case GET_PARAM_DPB_SIZE
:
1000 *((unsigned int *)out
) = MAX_VP9_DPB_SIZE
;
1002 case GET_PARAM_CROP_INFO
:
1003 get_crop_info(inst
, out
);
1006 mtk_vcodec_err(inst
, "not supported param type %d", type
);
1014 static struct vdec_common_if vdec_vp9_if
= {
1015 .init
= vdec_vp9_init
,
1016 .decode
= vdec_vp9_decode
,
1017 .get_param
= vdec_vp9_get_param
,
1018 .deinit
= vdec_vp9_deinit
,
1021 struct vdec_common_if
*get_vp9_dec_comm_if(void);
1023 struct vdec_common_if
*get_vp9_dec_comm_if(void)
1025 return &vdec_vp9_if
;