Commit | Line | Data |
---|---|---|
9293e39c | 1 | // SPDX-License-Identifier: GPL-2.0 |
f77e8985 TL |
2 | /* |
3 | * Copyright (c) 2016 MediaTek Inc. | |
4 | * Author: Daniel Hsiao <daniel.hsiao@mediatek.com> | |
5 | * Kai-Sean Yang <kai-sean.yang@mediatek.com> | |
6 | * Tiffany Lin <tiffany.lin@mediatek.com> | |
f77e8985 TL |
7 | */ |
8 | ||
9 | #include <linux/fs.h> | |
10 | #include <linux/slab.h> | |
11 | #include <linux/syscalls.h> | |
12 | #include <linux/delay.h> | |
13 | #include <linux/time.h> | |
14 | ||
0934d375 | 15 | #include "../../common/mtk_vcodec_intr.h" |
f77e8985 TL |
16 | #include "../vdec_drv_base.h" |
17 | #include "../vdec_vpu_if.h" | |
18 | ||
502892bb | 19 | #define VP9_MAX_SUPER_FRAMES_NUM 8 |
f77e8985 TL |
20 | #define VP9_SUPER_FRAME_BS_SZ 64 |
21 | #define MAX_VP9_DPB_SIZE 9 | |
22 | ||
23 | #define REFS_PER_FRAME 3 | |
24 | #define MAX_NUM_REF_FRAMES 8 | |
25 | #define VP9_MAX_FRM_BUF_NUM 9 | |
26 | #define VP9_MAX_FRM_BUF_NODE_NUM (VP9_MAX_FRM_BUF_NUM * 2) | |
e706b9ed | 27 | #define VP9_SEG_ID_SZ 0x12000 |
f77e8985 TL |
28 | |
29 | /** | |
30 | * struct vp9_dram_buf - contains buffer info for vpu | |
31 | * @va : cpu address | |
32 | * @pa : iova address | |
33 | * @sz : buffer size | |
34 | * @padding : for 64 bytes alignment | |
35 | */ | |
36 | struct vp9_dram_buf { | |
37 | unsigned long va; | |
38 | unsigned long pa; | |
39 | unsigned int sz; | |
40 | unsigned int padding; | |
41 | }; | |
42 | ||
43 | /** | |
44 | * struct vp9_fb_info - contains frame buffer info | |
45 | * @fb : frmae buffer | |
46 | * @reserved : reserved field used by vpu | |
47 | */ | |
48 | struct vp9_fb_info { | |
49 | struct vdec_fb *fb; | |
50 | unsigned int reserved[32]; | |
51 | }; | |
52 | ||
53 | /** | |
54 | * struct vp9_ref_cnt_buf - contains reference buffer information | |
55 | * @buf : referenced frame buffer | |
56 | * @ref_cnt : referenced frame buffer's reference count. | |
57 | * When reference count=0, remove it from reference list | |
58 | */ | |
59 | struct vp9_ref_cnt_buf { | |
60 | struct vp9_fb_info buf; | |
61 | unsigned int ref_cnt; | |
62 | }; | |
63 | ||
64 | /** | |
a4184b4f | 65 | * struct vp9_ref_buf - contains current frame's reference buffer information |
f77e8985 TL |
66 | * @buf : reference buffer |
67 | * @idx : reference buffer index to frm_bufs | |
68 | * @reserved : reserved field used by vpu | |
69 | */ | |
70 | struct vp9_ref_buf { | |
71 | struct vp9_fb_info *buf; | |
72 | unsigned int idx; | |
73 | unsigned int reserved[6]; | |
74 | }; | |
75 | ||
76 | /** | |
a4184b4f | 77 | * struct vp9_sf_ref_fb - contains frame buffer info |
f77e8985 TL |
78 | * @fb : super frame reference frame buffer |
79 | * @used : this reference frame info entry is used | |
80 | * @padding : for 64 bytes size align | |
81 | */ | |
82 | struct vp9_sf_ref_fb { | |
83 | struct vdec_fb fb; | |
84 | int used; | |
85 | int padding; | |
86 | }; | |
87 | ||
88 | /* | |
89 | * struct vdec_vp9_vsi - shared buffer between host and VPU firmware | |
90 | * AP-W/R : AP is writer/reader on this item | |
91 | * VPU-W/R: VPU is write/reader on this item | |
92 | * @sf_bs_buf : super frame backup buffer (AP-W, VPU-R) | |
93 | * @sf_ref_fb : record supoer frame reference buffer information | |
94 | * (AP-R/W, VPU-R/W) | |
95 | * @sf_next_ref_fb_idx : next available super frame (AP-W, VPU-R) | |
96 | * @sf_frm_cnt : super frame count, filled by vpu (AP-R, VPU-W) | |
97 | * @sf_frm_offset : super frame offset, filled by vpu (AP-R, VPU-W) | |
98 | * @sf_frm_sz : super frame size, filled by vpu (AP-R, VPU-W) | |
99 | * @sf_frm_idx : current super frame (AP-R, VPU-W) | |
100 | * @sf_init : inform super frame info already parsed by vpu (AP-R, VPU-W) | |
101 | * @fb : capture buffer (AP-W, VPU-R) | |
102 | * @bs : bs buffer (AP-W, VPU-R) | |
103 | * @cur_fb : current show capture buffer (AP-R/W, VPU-R/W) | |
104 | * @pic_w : picture width (AP-R, VPU-W) | |
105 | * @pic_h : picture height (AP-R, VPU-W) | |
106 | * @buf_w : codec width (AP-R, VPU-W) | |
107 | * @buf_h : coded height (AP-R, VPU-W) | |
108 | * @buf_sz_y_bs : ufo compressed y plane size (AP-R, VPU-W) | |
109 | * @buf_sz_c_bs : ufo compressed cbcr plane size (AP-R, VPU-W) | |
110 | * @buf_len_sz_y : size used to store y plane ufo info (AP-R, VPU-W) | |
111 | * @buf_len_sz_c : size used to store cbcr plane ufo info (AP-R, VPU-W) | |
112 | ||
113 | * @profile : profile sparsed from vpu (AP-R, VPU-W) | |
dea42fb7 RW |
114 | * @show_frame : [BIT(0)] display this frame or not (AP-R, VPU-W) |
115 | * [BIT(1)] reset segment data or not (AP-R, VPU-W) | |
116 | * [BIT(2)] trig decoder hardware or not (AP-R, VPU-W) | |
117 | * [BIT(3)] ask VPU to set bits(0~4) accordingly (AP-W, VPU-R) | |
118 | * [BIT(4)] do not reset segment data before every frame (AP-R, VPU-W) | |
f77e8985 TL |
119 | * @show_existing_frame : inform this frame is show existing frame |
120 | * (AP-R, VPU-W) | |
121 | * @frm_to_show_idx : index to show frame (AP-R, VPU-W) | |
122 | ||
123 | * @refresh_frm_flags : indicate when frame need to refine reference count | |
124 | * (AP-R, VPU-W) | |
125 | * @resolution_changed : resolution change in this frame (AP-R, VPU-W) | |
126 | ||
127 | * @frm_bufs : maintain reference buffer info (AP-R/W, VPU-R/W) | |
128 | * @ref_frm_map : maintain reference buffer map info (AP-R/W, VPU-R/W) | |
129 | * @new_fb_idx : index to frm_bufs array (AP-R, VPU-W) | |
130 | * @frm_num : decoded frame number, include sub-frame count (AP-R, VPU-W) | |
131 | * @mv_buf : motion vector working buffer (AP-W, VPU-R) | |
132 | * @frm_refs : maintain three reference buffer info (AP-R/W, VPU-R/W) | |
e706b9ed | 133 | * @seg_id_buf : segmentation map working buffer (AP-W, VPU-R) |
f77e8985 TL |
134 | */ |
135 | struct vdec_vp9_vsi { | |
136 | unsigned char sf_bs_buf[VP9_SUPER_FRAME_BS_SZ]; | |
502892bb | 137 | struct vp9_sf_ref_fb sf_ref_fb[VP9_MAX_SUPER_FRAMES_NUM]; |
f77e8985 TL |
138 | int sf_next_ref_fb_idx; |
139 | unsigned int sf_frm_cnt; | |
502892bb IW |
140 | unsigned int sf_frm_offset[VP9_MAX_SUPER_FRAMES_NUM]; |
141 | unsigned int sf_frm_sz[VP9_MAX_SUPER_FRAMES_NUM]; | |
f77e8985 TL |
142 | unsigned int sf_frm_idx; |
143 | unsigned int sf_init; | |
144 | struct vdec_fb fb; | |
145 | struct mtk_vcodec_mem bs; | |
146 | struct vdec_fb cur_fb; | |
147 | unsigned int pic_w; | |
148 | unsigned int pic_h; | |
149 | unsigned int buf_w; | |
150 | unsigned int buf_h; | |
151 | unsigned int buf_sz_y_bs; | |
152 | unsigned int buf_sz_c_bs; | |
153 | unsigned int buf_len_sz_y; | |
154 | unsigned int buf_len_sz_c; | |
155 | unsigned int profile; | |
156 | unsigned int show_frame; | |
157 | unsigned int show_existing_frame; | |
158 | unsigned int frm_to_show_idx; | |
159 | unsigned int refresh_frm_flags; | |
160 | unsigned int resolution_changed; | |
161 | ||
162 | struct vp9_ref_cnt_buf frm_bufs[VP9_MAX_FRM_BUF_NUM]; | |
163 | int ref_frm_map[MAX_NUM_REF_FRAMES]; | |
164 | unsigned int new_fb_idx; | |
165 | unsigned int frm_num; | |
166 | struct vp9_dram_buf mv_buf; | |
167 | ||
168 | struct vp9_ref_buf frm_refs[REFS_PER_FRAME]; | |
e706b9ed TL |
169 | struct vp9_dram_buf seg_id_buf; |
170 | ||
f77e8985 TL |
171 | }; |
172 | ||
173 | /* | |
174 | * struct vdec_vp9_inst - vp9 decode instance | |
175 | * @mv_buf : working buffer for mv | |
e706b9ed | 176 | * @seg_id_buf : working buffer for segmentation map |
f77e8985 TL |
177 | * @dec_fb : vdec_fb node to link fb to different fb_xxx_list |
178 | * @available_fb_node_list : current available vdec_fb node | |
179 | * @fb_use_list : current used or referenced vdec_fb | |
180 | * @fb_free_list : current available to free vdec_fb | |
181 | * @fb_disp_list : current available to display vdec_fb | |
182 | * @cur_fb : current frame buffer | |
183 | * @ctx : current decode context | |
184 | * @vpu : vpu instance information | |
185 | * @vsi : shared buffer between host and VPU firmware | |
186 | * @total_frm_cnt : total frame count, it do not include sub-frames in super | |
187 | * frame | |
188 | * @mem : instance memory information | |
189 | */ | |
190 | struct vdec_vp9_inst { | |
191 | struct mtk_vcodec_mem mv_buf; | |
e706b9ed | 192 | struct mtk_vcodec_mem seg_id_buf; |
f77e8985 TL |
193 | |
194 | struct vdec_fb_node dec_fb[VP9_MAX_FRM_BUF_NODE_NUM]; | |
195 | struct list_head available_fb_node_list; | |
196 | struct list_head fb_use_list; | |
197 | struct list_head fb_free_list; | |
198 | struct list_head fb_disp_list; | |
199 | struct vdec_fb *cur_fb; | |
01abf5fb | 200 | struct mtk_vcodec_dec_ctx *ctx; |
f77e8985 TL |
201 | struct vdec_vpu_inst vpu; |
202 | struct vdec_vp9_vsi *vsi; | |
203 | unsigned int total_frm_cnt; | |
204 | struct mtk_vcodec_mem mem; | |
205 | }; | |
206 | ||
207 | static bool vp9_is_sf_ref_fb(struct vdec_vp9_inst *inst, struct vdec_fb *fb) | |
208 | { | |
209 | int i; | |
210 | struct vdec_vp9_vsi *vsi = inst->vsi; | |
211 | ||
212 | for (i = 0; i < ARRAY_SIZE(vsi->sf_ref_fb); i++) { | |
213 | if (fb == &vsi->sf_ref_fb[i].fb) | |
214 | return true; | |
215 | } | |
216 | return false; | |
217 | } | |
218 | ||
219 | static struct vdec_fb *vp9_rm_from_fb_use_list(struct vdec_vp9_inst | |
220 | *inst, void *addr) | |
221 | { | |
222 | struct vdec_fb *fb = NULL; | |
223 | struct vdec_fb_node *node; | |
224 | ||
225 | list_for_each_entry(node, &inst->fb_use_list, list) { | |
226 | fb = (struct vdec_fb *)node->fb; | |
227 | if (fb->base_y.va == addr) { | |
228 | list_move_tail(&node->list, | |
229 | &inst->available_fb_node_list); | |
dfa2d6e0 | 230 | return fb; |
f77e8985 TL |
231 | } |
232 | } | |
dfa2d6e0 IW |
233 | |
234 | return NULL; | |
f77e8985 TL |
235 | } |
236 | ||
237 | static void vp9_add_to_fb_free_list(struct vdec_vp9_inst *inst, | |
238 | struct vdec_fb *fb) | |
239 | { | |
240 | struct vdec_fb_node *node; | |
241 | ||
242 | if (fb) { | |
243 | node = list_first_entry_or_null(&inst->available_fb_node_list, | |
244 | struct vdec_fb_node, list); | |
245 | ||
246 | if (node) { | |
247 | node->fb = fb; | |
248 | list_move_tail(&node->list, &inst->fb_free_list); | |
249 | } | |
250 | } else { | |
0db2fc4e | 251 | mtk_vdec_debug(inst->ctx, "No free fb node"); |
f77e8985 TL |
252 | } |
253 | } | |
254 | ||
255 | static void vp9_free_sf_ref_fb(struct vdec_fb *fb) | |
256 | { | |
257 | struct vp9_sf_ref_fb *sf_ref_fb = | |
258 | container_of(fb, struct vp9_sf_ref_fb, fb); | |
259 | ||
260 | sf_ref_fb->used = 0; | |
261 | } | |
262 | ||
263 | static void vp9_ref_cnt_fb(struct vdec_vp9_inst *inst, int *idx, | |
264 | int new_idx) | |
265 | { | |
266 | struct vdec_vp9_vsi *vsi = inst->vsi; | |
267 | int ref_idx = *idx; | |
268 | ||
269 | if (ref_idx >= 0 && vsi->frm_bufs[ref_idx].ref_cnt > 0) { | |
270 | vsi->frm_bufs[ref_idx].ref_cnt--; | |
271 | ||
272 | if (vsi->frm_bufs[ref_idx].ref_cnt == 0) { | |
273 | if (!vp9_is_sf_ref_fb(inst, | |
274 | vsi->frm_bufs[ref_idx].buf.fb)) { | |
275 | struct vdec_fb *fb; | |
276 | ||
277 | fb = vp9_rm_from_fb_use_list(inst, | |
278 | vsi->frm_bufs[ref_idx].buf.fb->base_y.va); | |
279 | vp9_add_to_fb_free_list(inst, fb); | |
280 | } else | |
281 | vp9_free_sf_ref_fb( | |
282 | vsi->frm_bufs[ref_idx].buf.fb); | |
283 | } | |
284 | } | |
285 | ||
286 | *idx = new_idx; | |
287 | vsi->frm_bufs[new_idx].ref_cnt++; | |
288 | } | |
289 | ||
290 | static void vp9_free_all_sf_ref_fb(struct vdec_vp9_inst *inst) | |
291 | { | |
292 | int i; | |
293 | struct vdec_vp9_vsi *vsi = inst->vsi; | |
294 | ||
295 | for (i = 0; i < ARRAY_SIZE(vsi->sf_ref_fb); i++) { | |
296 | if (vsi->sf_ref_fb[i].fb.base_y.va) { | |
297 | mtk_vcodec_mem_free(inst->ctx, | |
298 | &vsi->sf_ref_fb[i].fb.base_y); | |
299 | mtk_vcodec_mem_free(inst->ctx, | |
300 | &vsi->sf_ref_fb[i].fb.base_c); | |
301 | vsi->sf_ref_fb[i].used = 0; | |
302 | } | |
303 | } | |
304 | } | |
305 | ||
306 | /* For each sub-frame except the last one, the driver will dynamically | |
307 | * allocate reference buffer by calling vp9_get_sf_ref_fb() | |
308 | * The last sub-frame will use the original fb provided by the | |
309 | * vp9_dec_decode() interface | |
310 | */ | |
311 | static int vp9_get_sf_ref_fb(struct vdec_vp9_inst *inst) | |
312 | { | |
313 | int idx; | |
314 | struct mtk_vcodec_mem *mem_basy_y; | |
315 | struct mtk_vcodec_mem *mem_basy_c; | |
316 | struct vdec_vp9_vsi *vsi = inst->vsi; | |
317 | ||
318 | for (idx = 0; | |
319 | idx < ARRAY_SIZE(vsi->sf_ref_fb); | |
320 | idx++) { | |
321 | if (vsi->sf_ref_fb[idx].fb.base_y.va && | |
322 | vsi->sf_ref_fb[idx].used == 0) { | |
323 | return idx; | |
324 | } | |
325 | } | |
326 | ||
327 | for (idx = 0; | |
328 | idx < ARRAY_SIZE(vsi->sf_ref_fb); | |
329 | idx++) { | |
330 | if (vsi->sf_ref_fb[idx].fb.base_y.va == NULL) | |
331 | break; | |
332 | } | |
333 | ||
334 | if (idx == ARRAY_SIZE(vsi->sf_ref_fb)) { | |
0db2fc4e | 335 | mtk_vdec_err(inst->ctx, "List Full"); |
f77e8985 TL |
336 | return -1; |
337 | } | |
338 | ||
339 | mem_basy_y = &vsi->sf_ref_fb[idx].fb.base_y; | |
340 | mem_basy_y->size = vsi->buf_sz_y_bs + | |
341 | vsi->buf_len_sz_y; | |
342 | ||
343 | if (mtk_vcodec_mem_alloc(inst->ctx, mem_basy_y)) { | |
0db2fc4e | 344 | mtk_vdec_err(inst->ctx, "Cannot allocate sf_ref_buf y_buf"); |
f77e8985 TL |
345 | return -1; |
346 | } | |
347 | ||
348 | mem_basy_c = &vsi->sf_ref_fb[idx].fb.base_c; | |
349 | mem_basy_c->size = vsi->buf_sz_c_bs + | |
350 | vsi->buf_len_sz_c; | |
351 | ||
352 | if (mtk_vcodec_mem_alloc(inst->ctx, mem_basy_c)) { | |
0db2fc4e | 353 | mtk_vdec_err(inst->ctx, "Cannot allocate sf_ref_fb c_buf"); |
f77e8985 TL |
354 | return -1; |
355 | } | |
356 | vsi->sf_ref_fb[idx].used = 0; | |
357 | ||
358 | return idx; | |
359 | } | |
360 | ||
361 | static bool vp9_alloc_work_buf(struct vdec_vp9_inst *inst) | |
362 | { | |
363 | struct vdec_vp9_vsi *vsi = inst->vsi; | |
364 | int result; | |
365 | struct mtk_vcodec_mem *mem; | |
366 | ||
367 | unsigned int max_pic_w; | |
368 | unsigned int max_pic_h; | |
369 | ||
370 | ||
371 | if (!(inst->ctx->dev->dec_capability & | |
372 | VCODEC_CAPABILITY_4K_DISABLED)) { | |
373 | max_pic_w = VCODEC_DEC_4K_CODED_WIDTH; | |
374 | max_pic_h = VCODEC_DEC_4K_CODED_HEIGHT; | |
375 | } else { | |
376 | max_pic_w = MTK_VDEC_MAX_W; | |
377 | max_pic_h = MTK_VDEC_MAX_H; | |
378 | } | |
379 | ||
380 | if ((vsi->pic_w > max_pic_w) || | |
381 | (vsi->pic_h > max_pic_h)) { | |
0db2fc4e | 382 | mtk_vdec_err(inst->ctx, "Invalid w/h %d/%d", vsi->pic_w, vsi->pic_h); |
f77e8985 TL |
383 | return false; |
384 | } | |
385 | ||
0db2fc4e YD |
386 | mtk_vdec_debug(inst->ctx, "BUF CHG(%d): w/h/sb_w/sb_h=%d/%d/%d/%d", |
387 | vsi->resolution_changed, vsi->pic_w, | |
388 | vsi->pic_h, vsi->buf_w, vsi->buf_h); | |
f77e8985 TL |
389 | |
390 | mem = &inst->mv_buf; | |
f77e8985 TL |
391 | if (mem->va) |
392 | mtk_vcodec_mem_free(inst->ctx, mem); | |
393 | ||
394 | mem->size = ((vsi->buf_w / 64) * | |
395 | (vsi->buf_h / 64) + 2) * 36 * 16; | |
f77e8985 TL |
396 | result = mtk_vcodec_mem_alloc(inst->ctx, mem); |
397 | if (result) { | |
398 | mem->size = 0; | |
0db2fc4e | 399 | mtk_vdec_err(inst->ctx, "Cannot allocate mv_buf"); |
f77e8985 TL |
400 | return false; |
401 | } | |
402 | /* Set the va again */ | |
403 | vsi->mv_buf.va = (unsigned long)mem->va; | |
404 | vsi->mv_buf.pa = (unsigned long)mem->dma_addr; | |
405 | vsi->mv_buf.sz = (unsigned int)mem->size; | |
406 | ||
e706b9ed TL |
407 | |
408 | mem = &inst->seg_id_buf; | |
409 | if (mem->va) | |
410 | mtk_vcodec_mem_free(inst->ctx, mem); | |
411 | ||
412 | mem->size = VP9_SEG_ID_SZ; | |
413 | result = mtk_vcodec_mem_alloc(inst->ctx, mem); | |
414 | if (result) { | |
415 | mem->size = 0; | |
0db2fc4e | 416 | mtk_vdec_err(inst->ctx, "Cannot allocate seg_id_buf"); |
e706b9ed TL |
417 | return false; |
418 | } | |
419 | /* Set the va again */ | |
420 | vsi->seg_id_buf.va = (unsigned long)mem->va; | |
421 | vsi->seg_id_buf.pa = (unsigned long)mem->dma_addr; | |
422 | vsi->seg_id_buf.sz = (unsigned int)mem->size; | |
423 | ||
424 | ||
f77e8985 TL |
425 | vp9_free_all_sf_ref_fb(inst); |
426 | vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst); | |
427 | ||
428 | return true; | |
429 | } | |
430 | ||
431 | static bool vp9_add_to_fb_disp_list(struct vdec_vp9_inst *inst, | |
432 | struct vdec_fb *fb) | |
433 | { | |
434 | struct vdec_fb_node *node; | |
435 | ||
436 | if (!fb) { | |
0db2fc4e | 437 | mtk_vdec_err(inst->ctx, "fb == NULL"); |
f77e8985 TL |
438 | return false; |
439 | } | |
440 | ||
441 | node = list_first_entry_or_null(&inst->available_fb_node_list, | |
442 | struct vdec_fb_node, list); | |
443 | if (node) { | |
444 | node->fb = fb; | |
445 | list_move_tail(&node->list, &inst->fb_disp_list); | |
446 | } else { | |
0db2fc4e | 447 | mtk_vdec_err(inst->ctx, "No available fb node"); |
f77e8985 TL |
448 | return false; |
449 | } | |
450 | ||
451 | return true; | |
452 | } | |
453 | ||
454 | /* If any buffer updating is signaled it should be done here. */ | |
455 | static void vp9_swap_frm_bufs(struct vdec_vp9_inst *inst) | |
456 | { | |
457 | struct vdec_vp9_vsi *vsi = inst->vsi; | |
458 | struct vp9_fb_info *frm_to_show; | |
459 | int ref_index = 0, mask; | |
460 | ||
461 | for (mask = vsi->refresh_frm_flags; mask; mask >>= 1) { | |
462 | if (mask & 1) | |
463 | vp9_ref_cnt_fb(inst, &vsi->ref_frm_map[ref_index], | |
464 | vsi->new_fb_idx); | |
465 | ++ref_index; | |
466 | } | |
467 | ||
468 | frm_to_show = &vsi->frm_bufs[vsi->new_fb_idx].buf; | |
469 | vsi->frm_bufs[vsi->new_fb_idx].ref_cnt--; | |
470 | ||
471 | if (frm_to_show->fb != inst->cur_fb) { | |
472 | /* This frame is show exist frame and no decode output | |
473 | * copy frame data from frm_to_show to current CAPTURE | |
474 | * buffer | |
475 | */ | |
476 | if ((frm_to_show->fb != NULL) && | |
477 | (inst->cur_fb->base_y.size >= | |
411a414b MM |
478 | frm_to_show->fb->base_y.size) && |
479 | (inst->cur_fb->base_c.size >= | |
480 | frm_to_show->fb->base_c.size)) { | |
f77e8985 TL |
481 | memcpy((void *)inst->cur_fb->base_y.va, |
482 | (void *)frm_to_show->fb->base_y.va, | |
411a414b | 483 | frm_to_show->fb->base_y.size); |
f77e8985 TL |
484 | memcpy((void *)inst->cur_fb->base_c.va, |
485 | (void *)frm_to_show->fb->base_c.va, | |
411a414b | 486 | frm_to_show->fb->base_c.size); |
f77e8985 TL |
487 | } else { |
488 | /* After resolution change case, current CAPTURE buffer | |
489 | * may have less buffer size than frm_to_show buffer | |
490 | * size | |
491 | */ | |
492 | if (frm_to_show->fb != NULL) | |
0db2fc4e YD |
493 | mtk_vdec_err(inst->ctx, |
494 | "base_y.size=%zu, frm_to_show: base_y.size=%zu", | |
495 | inst->cur_fb->base_y.size, | |
496 | frm_to_show->fb->base_y.size); | |
f77e8985 TL |
497 | } |
498 | if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) { | |
dea42fb7 | 499 | if (vsi->show_frame & BIT(0)) |
f77e8985 TL |
500 | vp9_add_to_fb_disp_list(inst, inst->cur_fb); |
501 | } | |
502 | } else { | |
503 | if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) { | |
dea42fb7 | 504 | if (vsi->show_frame & BIT(0)) |
f77e8985 TL |
505 | vp9_add_to_fb_disp_list(inst, frm_to_show->fb); |
506 | } | |
507 | } | |
508 | ||
509 | /* when ref_cnt ==0, move this fb to fb_free_list. v4l2 driver will | |
510 | * clean fb_free_list | |
511 | */ | |
512 | if (vsi->frm_bufs[vsi->new_fb_idx].ref_cnt == 0) { | |
513 | if (!vp9_is_sf_ref_fb( | |
514 | inst, vsi->frm_bufs[vsi->new_fb_idx].buf.fb)) { | |
515 | struct vdec_fb *fb; | |
516 | ||
517 | fb = vp9_rm_from_fb_use_list(inst, | |
518 | vsi->frm_bufs[vsi->new_fb_idx].buf.fb->base_y.va); | |
519 | ||
520 | vp9_add_to_fb_free_list(inst, fb); | |
521 | } else { | |
522 | vp9_free_sf_ref_fb( | |
523 | vsi->frm_bufs[vsi->new_fb_idx].buf.fb); | |
524 | } | |
525 | } | |
526 | ||
527 | /* if this super frame and it is not last sub-frame, get next fb for | |
528 | * sub-frame decode | |
529 | */ | |
502892bb | 530 | if (vsi->sf_frm_cnt > 0 && vsi->sf_frm_idx != vsi->sf_frm_cnt) |
f77e8985 TL |
531 | vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst); |
532 | } | |
533 | ||
534 | static bool vp9_wait_dec_end(struct vdec_vp9_inst *inst) | |
535 | { | |
01abf5fb | 536 | struct mtk_vcodec_dec_ctx *ctx = inst->ctx; |
f77e8985 TL |
537 | |
538 | mtk_vcodec_wait_for_done_ctx(inst->ctx, | |
539 | MTK_INST_IRQ_RECEIVED, | |
770eb47f | 540 | WAIT_INTR_TIMEOUT_MS, 0); |
f77e8985 TL |
541 | |
542 | if (ctx->irq_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS) | |
543 | return true; | |
544 | else | |
545 | return false; | |
546 | } | |
547 | ||
01abf5fb | 548 | static struct vdec_vp9_inst *vp9_alloc_inst(struct mtk_vcodec_dec_ctx *ctx) |
f77e8985 TL |
549 | { |
550 | int result; | |
551 | struct mtk_vcodec_mem mem; | |
552 | struct vdec_vp9_inst *inst; | |
553 | ||
554 | memset(&mem, 0, sizeof(mem)); | |
555 | mem.size = sizeof(struct vdec_vp9_inst); | |
556 | result = mtk_vcodec_mem_alloc(ctx, &mem); | |
557 | if (result) | |
558 | return NULL; | |
559 | ||
560 | inst = mem.va; | |
561 | inst->mem = mem; | |
562 | ||
563 | return inst; | |
564 | } | |
565 | ||
566 | static void vp9_free_inst(struct vdec_vp9_inst *inst) | |
567 | { | |
568 | struct mtk_vcodec_mem mem; | |
569 | ||
570 | mem = inst->mem; | |
571 | if (mem.va) | |
572 | mtk_vcodec_mem_free(inst->ctx, &mem); | |
573 | } | |
574 | ||
575 | static bool vp9_decode_end_proc(struct vdec_vp9_inst *inst) | |
576 | { | |
577 | struct vdec_vp9_vsi *vsi = inst->vsi; | |
578 | bool ret = false; | |
579 | ||
580 | if (!vsi->show_existing_frame) { | |
581 | ret = vp9_wait_dec_end(inst); | |
582 | if (!ret) { | |
0db2fc4e YD |
583 | mtk_vdec_err(inst->ctx, "Decode failed, Decode Timeout @[%d]", |
584 | vsi->frm_num); | |
f77e8985 TL |
585 | return false; |
586 | } | |
587 | ||
588 | if (vpu_dec_end(&inst->vpu)) { | |
0db2fc4e | 589 | mtk_vdec_err(inst->ctx, "vp9_dec_vpu_end failed"); |
f77e8985 TL |
590 | return false; |
591 | } | |
0db2fc4e YD |
592 | mtk_vdec_debug(inst->ctx, "Decode Ok @%d (%d/%d)", vsi->frm_num, |
593 | vsi->pic_w, vsi->pic_h); | |
f77e8985 | 594 | } else { |
0db2fc4e | 595 | mtk_vdec_debug(inst->ctx, "Decode Ok @%d (show_existing_frame)", vsi->frm_num); |
f77e8985 TL |
596 | } |
597 | ||
598 | vp9_swap_frm_bufs(inst); | |
599 | vsi->frm_num++; | |
600 | return true; | |
601 | } | |
602 | ||
603 | static bool vp9_is_last_sub_frm(struct vdec_vp9_inst *inst) | |
604 | { | |
605 | struct vdec_vp9_vsi *vsi = inst->vsi; | |
606 | ||
607 | if (vsi->sf_frm_cnt <= 0 || vsi->sf_frm_idx == vsi->sf_frm_cnt) | |
608 | return true; | |
609 | ||
610 | return false; | |
611 | } | |
612 | ||
613 | static struct vdec_fb *vp9_rm_from_fb_disp_list(struct vdec_vp9_inst *inst) | |
614 | { | |
615 | struct vdec_fb_node *node; | |
616 | struct vdec_fb *fb = NULL; | |
617 | ||
618 | node = list_first_entry_or_null(&inst->fb_disp_list, | |
619 | struct vdec_fb_node, list); | |
620 | if (node) { | |
621 | fb = (struct vdec_fb *)node->fb; | |
622 | fb->status |= FB_ST_DISPLAY; | |
623 | list_move_tail(&node->list, &inst->available_fb_node_list); | |
0db2fc4e | 624 | mtk_vdec_debug(inst->ctx, "[FB] get disp fb %p st=%d", node->fb, fb->status); |
f77e8985 | 625 | } else |
0db2fc4e | 626 | mtk_vdec_debug(inst->ctx, "[FB] there is no disp fb"); |
f77e8985 TL |
627 | |
628 | return fb; | |
629 | } | |
630 | ||
631 | static bool vp9_add_to_fb_use_list(struct vdec_vp9_inst *inst, | |
632 | struct vdec_fb *fb) | |
633 | { | |
634 | struct vdec_fb_node *node; | |
635 | ||
636 | if (!fb) { | |
0db2fc4e | 637 | mtk_vdec_debug(inst->ctx, "fb == NULL"); |
f77e8985 TL |
638 | return false; |
639 | } | |
640 | ||
641 | node = list_first_entry_or_null(&inst->available_fb_node_list, | |
642 | struct vdec_fb_node, list); | |
643 | if (node) { | |
644 | node->fb = fb; | |
645 | list_move_tail(&node->list, &inst->fb_use_list); | |
646 | } else { | |
0db2fc4e | 647 | mtk_vdec_err(inst->ctx, "No free fb node"); |
f77e8985 TL |
648 | return false; |
649 | } | |
650 | return true; | |
651 | } | |
652 | ||
653 | static void vp9_reset(struct vdec_vp9_inst *inst) | |
654 | { | |
655 | struct vdec_fb_node *node, *tmp; | |
656 | ||
657 | list_for_each_entry_safe(node, tmp, &inst->fb_use_list, list) | |
658 | list_move_tail(&node->list, &inst->fb_free_list); | |
659 | ||
660 | vp9_free_all_sf_ref_fb(inst); | |
661 | inst->vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst); | |
662 | ||
663 | if (vpu_dec_reset(&inst->vpu)) | |
0db2fc4e | 664 | mtk_vdec_err(inst->ctx, "vp9_dec_vpu_reset failed"); |
f77e8985 TL |
665 | |
666 | /* Set the va again, since vpu_dec_reset will clear mv_buf in vpu */ | |
667 | inst->vsi->mv_buf.va = (unsigned long)inst->mv_buf.va; | |
668 | inst->vsi->mv_buf.pa = (unsigned long)inst->mv_buf.dma_addr; | |
669 | inst->vsi->mv_buf.sz = (unsigned long)inst->mv_buf.size; | |
e706b9ed TL |
670 | |
671 | /* Set the va again, since vpu_dec_reset will clear seg_id_buf in vpu */ | |
672 | inst->vsi->seg_id_buf.va = (unsigned long)inst->seg_id_buf.va; | |
673 | inst->vsi->seg_id_buf.pa = (unsigned long)inst->seg_id_buf.dma_addr; | |
674 | inst->vsi->seg_id_buf.sz = (unsigned long)inst->seg_id_buf.size; | |
675 | ||
f77e8985 TL |
676 | } |
677 | ||
678 | static void init_all_fb_lists(struct vdec_vp9_inst *inst) | |
679 | { | |
680 | int i; | |
681 | ||
682 | INIT_LIST_HEAD(&inst->available_fb_node_list); | |
683 | INIT_LIST_HEAD(&inst->fb_use_list); | |
684 | INIT_LIST_HEAD(&inst->fb_free_list); | |
685 | INIT_LIST_HEAD(&inst->fb_disp_list); | |
686 | ||
687 | for (i = 0; i < ARRAY_SIZE(inst->dec_fb); i++) { | |
688 | INIT_LIST_HEAD(&inst->dec_fb[i].list); | |
689 | inst->dec_fb[i].fb = NULL; | |
690 | list_add_tail(&inst->dec_fb[i].list, | |
691 | &inst->available_fb_node_list); | |
692 | } | |
693 | } | |
694 | ||
695 | static void get_pic_info(struct vdec_vp9_inst *inst, struct vdec_pic_info *pic) | |
696 | { | |
b105581a YD |
697 | pic->fb_sz[0] = inst->vsi->buf_sz_y_bs + inst->vsi->buf_len_sz_y; |
698 | pic->fb_sz[1] = inst->vsi->buf_sz_c_bs + inst->vsi->buf_len_sz_c; | |
f77e8985 TL |
699 | |
700 | pic->pic_w = inst->vsi->pic_w; | |
701 | pic->pic_h = inst->vsi->pic_h; | |
702 | pic->buf_w = inst->vsi->buf_w; | |
703 | pic->buf_h = inst->vsi->buf_h; | |
704 | ||
0db2fc4e YD |
705 | mtk_vdec_debug(inst->ctx, "pic(%d, %d), buf(%d, %d)", |
706 | pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h); | |
707 | mtk_vdec_debug(inst->ctx, "fb size: Y(%d), C(%d)", pic->fb_sz[0], pic->fb_sz[1]); | |
f77e8985 TL |
708 | } |
709 | ||
710 | static void get_disp_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb) | |
711 | { | |
712 | ||
713 | *out_fb = vp9_rm_from_fb_disp_list(inst); | |
714 | if (*out_fb) | |
715 | (*out_fb)->status |= FB_ST_DISPLAY; | |
716 | } | |
717 | ||
718 | static void get_free_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb) | |
719 | { | |
720 | struct vdec_fb_node *node; | |
721 | struct vdec_fb *fb = NULL; | |
722 | ||
723 | node = list_first_entry_or_null(&inst->fb_free_list, | |
724 | struct vdec_fb_node, list); | |
725 | if (node) { | |
726 | list_move_tail(&node->list, &inst->available_fb_node_list); | |
727 | fb = (struct vdec_fb *)node->fb; | |
728 | fb->status |= FB_ST_FREE; | |
0db2fc4e | 729 | mtk_vdec_debug(inst->ctx, "[FB] get free fb %p st=%d", node->fb, fb->status); |
f77e8985 | 730 | } else { |
0db2fc4e | 731 | mtk_vdec_debug(inst->ctx, "[FB] there is no free fb"); |
f77e8985 TL |
732 | } |
733 | ||
734 | *out_fb = fb; | |
735 | } | |
736 | ||
e8a2a41e WCL |
737 | static int validate_vsi_array_indexes(struct vdec_vp9_inst *inst, |
738 | struct vdec_vp9_vsi *vsi) { | |
502892bb | 739 | if (vsi->sf_frm_idx > VP9_MAX_SUPER_FRAMES_NUM) { |
0db2fc4e | 740 | mtk_vdec_err(inst->ctx, "Invalid vsi->sf_frm_idx=%u.", vsi->sf_frm_idx); |
e8a2a41e WCL |
741 | return -EIO; |
742 | } | |
743 | if (vsi->frm_to_show_idx >= VP9_MAX_FRM_BUF_NUM) { | |
0db2fc4e | 744 | mtk_vdec_err(inst->ctx, "Invalid vsi->frm_to_show_idx=%u.", vsi->frm_to_show_idx); |
e8a2a41e WCL |
745 | return -EIO; |
746 | } | |
747 | if (vsi->new_fb_idx >= VP9_MAX_FRM_BUF_NUM) { | |
0db2fc4e | 748 | mtk_vdec_err(inst->ctx, "Invalid vsi->new_fb_idx=%u.", vsi->new_fb_idx); |
e8a2a41e WCL |
749 | return -EIO; |
750 | } | |
751 | return 0; | |
752 | } | |
753 | ||
86aed3f5 | 754 | static void vdec_vp9_deinit(void *h_vdec) |
f77e8985 TL |
755 | { |
756 | struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec; | |
757 | struct mtk_vcodec_mem *mem; | |
758 | int ret = 0; | |
759 | ||
760 | ret = vpu_dec_deinit(&inst->vpu); | |
761 | if (ret) | |
0db2fc4e | 762 | mtk_vdec_err(inst->ctx, "vpu_dec_deinit failed"); |
f77e8985 TL |
763 | |
764 | mem = &inst->mv_buf; | |
765 | if (mem->va) | |
766 | mtk_vcodec_mem_free(inst->ctx, mem); | |
767 | ||
e706b9ed TL |
768 | mem = &inst->seg_id_buf; |
769 | if (mem->va) | |
770 | mtk_vcodec_mem_free(inst->ctx, mem); | |
771 | ||
f77e8985 TL |
772 | vp9_free_all_sf_ref_fb(inst); |
773 | vp9_free_inst(inst); | |
774 | } | |
775 | ||
01abf5fb | 776 | static int vdec_vp9_init(struct mtk_vcodec_dec_ctx *ctx) |
f77e8985 TL |
777 | { |
778 | struct vdec_vp9_inst *inst; | |
779 | ||
780 | inst = vp9_alloc_inst(ctx); | |
781 | if (!inst) | |
782 | return -ENOMEM; | |
783 | ||
784 | inst->total_frm_cnt = 0; | |
785 | inst->ctx = ctx; | |
786 | ||
787 | inst->vpu.id = IPI_VDEC_VP9; | |
f77e8985 | 788 | inst->vpu.ctx = ctx; |
f77e8985 TL |
789 | |
790 | if (vpu_dec_init(&inst->vpu)) { | |
0db2fc4e | 791 | mtk_vdec_err(inst->ctx, "vp9_dec_vpu_init failed"); |
f77e8985 TL |
792 | goto err_deinit_inst; |
793 | } | |
794 | ||
795 | inst->vsi = (struct vdec_vp9_vsi *)inst->vpu.vsi; | |
dea42fb7 RW |
796 | |
797 | inst->vsi->show_frame |= BIT(3); | |
798 | ||
f77e8985 TL |
799 | init_all_fb_lists(inst); |
800 | ||
86aed3f5 | 801 | ctx->drv_handle = inst; |
f77e8985 TL |
802 | return 0; |
803 | ||
804 | err_deinit_inst: | |
805 | vp9_free_inst(inst); | |
806 | ||
807 | return -EINVAL; | |
808 | } | |
809 | ||
86aed3f5 AC |
810 | static int vdec_vp9_decode(void *h_vdec, struct mtk_vcodec_mem *bs, |
811 | struct vdec_fb *fb, bool *res_chg) | |
f77e8985 TL |
812 | { |
813 | int ret = 0; | |
814 | struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec; | |
815 | struct vdec_vp9_vsi *vsi = inst->vsi; | |
816 | u32 data[3]; | |
817 | int i; | |
818 | ||
819 | *res_chg = false; | |
820 | ||
821 | if ((bs == NULL) && (fb == NULL)) { | |
0db2fc4e | 822 | mtk_vdec_debug(inst->ctx, "[EOS]"); |
f77e8985 TL |
823 | vp9_reset(inst); |
824 | return ret; | |
825 | } | |
826 | ||
827 | if (bs == NULL) { | |
0db2fc4e | 828 | mtk_vdec_err(inst->ctx, "bs == NULL"); |
f77e8985 TL |
829 | return -EINVAL; |
830 | } | |
831 | ||
0db2fc4e | 832 | mtk_vdec_debug(inst->ctx, "Input BS Size = %zu", bs->size); |
f77e8985 TL |
833 | |
834 | while (1) { | |
835 | struct vdec_fb *cur_fb = NULL; | |
836 | ||
837 | data[0] = *((unsigned int *)bs->va); | |
838 | data[1] = *((unsigned int *)(bs->va + 4)); | |
839 | data[2] = *((unsigned int *)(bs->va + 8)); | |
840 | ||
841 | vsi->bs = *bs; | |
842 | ||
843 | if (fb) | |
844 | vsi->fb = *fb; | |
845 | ||
846 | if (!vsi->sf_init) { | |
847 | unsigned int sf_bs_sz; | |
848 | unsigned int sf_bs_off; | |
849 | unsigned char *sf_bs_src; | |
850 | unsigned char *sf_bs_dst; | |
851 | ||
852 | sf_bs_sz = bs->size > VP9_SUPER_FRAME_BS_SZ ? | |
853 | VP9_SUPER_FRAME_BS_SZ : bs->size; | |
854 | sf_bs_off = VP9_SUPER_FRAME_BS_SZ - sf_bs_sz; | |
855 | sf_bs_src = bs->va + bs->size - sf_bs_sz; | |
856 | sf_bs_dst = vsi->sf_bs_buf + sf_bs_off; | |
857 | memcpy(sf_bs_dst, sf_bs_src, sf_bs_sz); | |
858 | } else { | |
859 | if ((vsi->sf_frm_cnt > 0) && | |
860 | (vsi->sf_frm_idx < vsi->sf_frm_cnt)) { | |
861 | unsigned int idx = vsi->sf_frm_idx; | |
862 | ||
863 | memcpy((void *)bs->va, | |
864 | (void *)(bs->va + | |
865 | vsi->sf_frm_offset[idx]), | |
866 | vsi->sf_frm_sz[idx]); | |
867 | } | |
868 | } | |
dea42fb7 RW |
869 | |
870 | if (!(vsi->show_frame & BIT(4))) | |
871 | memset(inst->seg_id_buf.va, 0, inst->seg_id_buf.size); | |
872 | ||
f77e8985 TL |
873 | ret = vpu_dec_start(&inst->vpu, data, 3); |
874 | if (ret) { | |
0db2fc4e | 875 | mtk_vdec_err(inst->ctx, "vpu_dec_start failed"); |
f77e8985 TL |
876 | goto DECODE_ERROR; |
877 | } | |
878 | ||
dea42fb7 RW |
879 | if (vsi->show_frame & BIT(1)) { |
880 | memset(inst->seg_id_buf.va, 0, inst->seg_id_buf.size); | |
881 | ||
882 | if (vsi->show_frame & BIT(2)) { | |
4397efeb ZC |
883 | ret = vpu_dec_start(&inst->vpu, NULL, 0); |
884 | if (ret) { | |
0db2fc4e | 885 | mtk_vdec_err(inst->ctx, "vpu trig decoder failed"); |
dea42fb7 RW |
886 | goto DECODE_ERROR; |
887 | } | |
888 | } | |
889 | } | |
890 | ||
e8a2a41e WCL |
891 | ret = validate_vsi_array_indexes(inst, vsi); |
892 | if (ret) { | |
0db2fc4e | 893 | mtk_vdec_err(inst->ctx, "Invalid values from VPU."); |
e8a2a41e WCL |
894 | goto DECODE_ERROR; |
895 | } | |
896 | ||
f77e8985 TL |
897 | if (vsi->resolution_changed) { |
898 | if (!vp9_alloc_work_buf(inst)) { | |
411a414b | 899 | ret = -EIO; |
f77e8985 TL |
900 | goto DECODE_ERROR; |
901 | } | |
902 | } | |
903 | ||
904 | if (vsi->sf_frm_cnt > 0) { | |
905 | cur_fb = &vsi->sf_ref_fb[vsi->sf_next_ref_fb_idx].fb; | |
906 | ||
907 | if (vsi->sf_frm_idx < vsi->sf_frm_cnt) | |
908 | inst->cur_fb = cur_fb; | |
909 | else | |
910 | inst->cur_fb = fb; | |
911 | } else { | |
912 | inst->cur_fb = fb; | |
913 | } | |
914 | ||
915 | vsi->frm_bufs[vsi->new_fb_idx].buf.fb = inst->cur_fb; | |
916 | if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) | |
917 | vp9_add_to_fb_use_list(inst, inst->cur_fb); | |
918 | ||
0db2fc4e | 919 | mtk_vdec_debug(inst->ctx, "[#pic %d]", vsi->frm_num); |
f77e8985 TL |
920 | |
921 | if (vsi->show_existing_frame) | |
0db2fc4e YD |
922 | mtk_vdec_debug(inst->ctx, |
923 | "drv->new_fb_idx=%d, drv->frm_to_show_idx=%d", | |
924 | vsi->new_fb_idx, vsi->frm_to_show_idx); | |
f77e8985 TL |
925 | |
926 | if (vsi->show_existing_frame && (vsi->frm_to_show_idx < | |
927 | VP9_MAX_FRM_BUF_NUM)) { | |
0db2fc4e YD |
928 | mtk_vdec_debug(inst->ctx, |
929 | "Skip Decode drv->new_fb_idx=%d, drv->frm_to_show_idx=%d", | |
930 | vsi->new_fb_idx, vsi->frm_to_show_idx); | |
f77e8985 TL |
931 | |
932 | vp9_ref_cnt_fb(inst, &vsi->new_fb_idx, | |
933 | vsi->frm_to_show_idx); | |
f77e8985 TL |
934 | } |
935 | ||
936 | /* VPU assign the buffer pointer in its address space, | |
937 | * reassign here | |
938 | */ | |
939 | for (i = 0; i < ARRAY_SIZE(vsi->frm_refs); i++) { | |
940 | unsigned int idx = vsi->frm_refs[i].idx; | |
941 | ||
942 | vsi->frm_refs[i].buf = &vsi->frm_bufs[idx].buf; | |
943 | } | |
944 | ||
945 | if (vsi->resolution_changed) { | |
946 | *res_chg = true; | |
0db2fc4e | 947 | mtk_vdec_debug(inst->ctx, "VDEC_ST_RESOLUTION_CHANGED"); |
f77e8985 TL |
948 | |
949 | ret = 0; | |
950 | goto DECODE_ERROR; | |
951 | } | |
952 | ||
fd1a97a2 | 953 | if (!vp9_decode_end_proc(inst)) { |
0db2fc4e | 954 | mtk_vdec_err(inst->ctx, "vp9_decode_end_proc"); |
f77e8985 TL |
955 | ret = -EINVAL; |
956 | goto DECODE_ERROR; | |
957 | } | |
958 | ||
959 | if (vp9_is_last_sub_frm(inst)) | |
960 | break; | |
961 | ||
962 | } | |
963 | inst->total_frm_cnt++; | |
964 | ||
965 | DECODE_ERROR: | |
966 | if (ret < 0) | |
967 | vp9_add_to_fb_free_list(inst, fb); | |
968 | ||
969 | return ret; | |
970 | } | |
971 | ||
972 | static void get_crop_info(struct vdec_vp9_inst *inst, struct v4l2_rect *cr) | |
973 | { | |
974 | cr->left = 0; | |
975 | cr->top = 0; | |
976 | cr->width = inst->vsi->pic_w; | |
977 | cr->height = inst->vsi->pic_h; | |
0db2fc4e YD |
978 | mtk_vdec_debug(inst->ctx, "get crop info l=%d, t=%d, w=%d, h=%d\n", |
979 | cr->left, cr->top, cr->width, cr->height); | |
f77e8985 TL |
980 | } |
981 | ||
86aed3f5 AC |
982 | static int vdec_vp9_get_param(void *h_vdec, enum vdec_get_param_type type, |
983 | void *out) | |
f77e8985 TL |
984 | { |
985 | struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec; | |
986 | int ret = 0; | |
987 | ||
988 | switch (type) { | |
989 | case GET_PARAM_DISP_FRAME_BUFFER: | |
990 | get_disp_fb(inst, out); | |
991 | break; | |
992 | case GET_PARAM_FREE_FRAME_BUFFER: | |
993 | get_free_fb(inst, out); | |
994 | break; | |
995 | case GET_PARAM_PIC_INFO: | |
996 | get_pic_info(inst, out); | |
997 | break; | |
998 | case GET_PARAM_DPB_SIZE: | |
999 | *((unsigned int *)out) = MAX_VP9_DPB_SIZE; | |
1000 | break; | |
1001 | case GET_PARAM_CROP_INFO: | |
1002 | get_crop_info(inst, out); | |
1003 | break; | |
1004 | default: | |
0db2fc4e | 1005 | mtk_vdec_err(inst->ctx, "not supported param type %d", type); |
f77e8985 TL |
1006 | ret = -EINVAL; |
1007 | break; | |
1008 | } | |
1009 | ||
1010 | return ret; | |
1011 | } | |
1012 | ||
9fcb242b | 1013 | const struct vdec_common_if vdec_vp9_if = { |
243dd05d KC |
1014 | .init = vdec_vp9_init, |
1015 | .decode = vdec_vp9_decode, | |
1016 | .get_param = vdec_vp9_get_param, | |
1017 | .deinit = vdec_vp9_deinit, | |
f77e8985 | 1018 | }; |