• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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>
6  *
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.
10  *
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.
15  */
16 
17 #include <linux/fs.h>
18 #include <linux/slab.h>
19 #include <linux/syscalls.h>
20 #include <linux/delay.h>
21 #include <linux/time.h>
22 
23 #include "../mtk_vcodec_intr.h"
24 #include "../vdec_drv_base.h"
25 #include "../vdec_vpu_if.h"
26 
27 #define VP9_SUPER_FRAME_BS_SZ 64
28 #define MAX_VP9_DPB_SIZE	9
29 
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
35 
36 /**
37  * struct vp9_dram_buf - contains buffer info for vpu
38  * @va : cpu address
39  * @pa : iova address
40  * @sz : buffer size
41  * @padding : for 64 bytes alignment
42  */
43 struct vp9_dram_buf {
44 	unsigned long va;
45 	unsigned long pa;
46 	unsigned int sz;
47 	unsigned int padding;
48 };
49 
50 /**
51  * struct vp9_fb_info - contains frame buffer info
52  * @fb : frmae buffer
53  * @reserved : reserved field used by vpu
54  */
55 struct vp9_fb_info {
56 	struct vdec_fb *fb;
57 	unsigned int reserved[32];
58 };
59 
60 /**
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
65  */
66 struct vp9_ref_cnt_buf {
67 	struct vp9_fb_info buf;
68 	unsigned int ref_cnt;
69 };
70 
71 /**
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
76  */
77 struct vp9_ref_buf {
78 	struct vp9_fb_info *buf;
79 	unsigned int idx;
80 	unsigned int reserved[6];
81 };
82 
83 /**
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
88  */
89 struct vp9_sf_ref_fb {
90 	struct vdec_fb fb;
91 	int used;
92 	int padding;
93 };
94 
95 /*
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
101  *	(AP-R/W, VPU-R/W)
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)
119 
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
123  *	(AP-R, VPU-W)
124  * @frm_to_show_idx : index to show frame (AP-R, VPU-W)
125 
126  * @refresh_frm_flags : indicate when frame need to refine reference count
127  *	(AP-R, VPU-W)
128  * @resolution_changed : resolution change in this frame (AP-R, VPU-W)
129 
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)
137  */
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;
147 	struct vdec_fb fb;
148 	struct mtk_vcodec_mem bs;
149 	struct vdec_fb cur_fb;
150 	unsigned int pic_w;
151 	unsigned int pic_h;
152 	unsigned int buf_w;
153 	unsigned int buf_h;
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;
164 
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;
170 
171 	struct vp9_ref_buf frm_refs[REFS_PER_FRAME];
172 	struct vp9_dram_buf seg_id_buf;
173 
174 };
175 
176 /*
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
190  *	    frame
191  * @mem : instance memory information
192  */
193 struct vdec_vp9_inst {
194 	struct mtk_vcodec_mem mv_buf;
195 	struct mtk_vcodec_mem seg_id_buf;
196 
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;
208 };
209 
vp9_is_sf_ref_fb(struct vdec_vp9_inst * inst,struct vdec_fb * fb)210 static bool vp9_is_sf_ref_fb(struct vdec_vp9_inst *inst, struct vdec_fb *fb)
211 {
212 	int i;
213 	struct vdec_vp9_vsi *vsi = inst->vsi;
214 
215 	for (i = 0; i < ARRAY_SIZE(vsi->sf_ref_fb); i++) {
216 		if (fb == &vsi->sf_ref_fb[i].fb)
217 			return true;
218 	}
219 	return false;
220 }
221 
vp9_rm_from_fb_use_list(struct vdec_vp9_inst * inst,void * addr)222 static struct vdec_fb *vp9_rm_from_fb_use_list(struct vdec_vp9_inst
223 					*inst, void *addr)
224 {
225 	struct vdec_fb *fb = NULL;
226 	struct vdec_fb_node *node;
227 
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);
233 			break;
234 		}
235 	}
236 	return fb;
237 }
238 
vp9_add_to_fb_free_list(struct vdec_vp9_inst * inst,struct vdec_fb * fb)239 static void vp9_add_to_fb_free_list(struct vdec_vp9_inst *inst,
240 			     struct vdec_fb *fb)
241 {
242 	struct vdec_fb_node *node;
243 
244 	if (fb) {
245 		node = list_first_entry_or_null(&inst->available_fb_node_list,
246 					struct vdec_fb_node, list);
247 
248 		if (node) {
249 			node->fb = fb;
250 			list_move_tail(&node->list, &inst->fb_free_list);
251 		}
252 	} else {
253 		mtk_vcodec_debug(inst, "No free fb node");
254 	}
255 }
256 
vp9_free_sf_ref_fb(struct vdec_fb * fb)257 static void vp9_free_sf_ref_fb(struct vdec_fb *fb)
258 {
259 	struct vp9_sf_ref_fb *sf_ref_fb =
260 		container_of(fb, struct vp9_sf_ref_fb, fb);
261 
262 	sf_ref_fb->used = 0;
263 }
264 
vp9_ref_cnt_fb(struct vdec_vp9_inst * inst,int * idx,int new_idx)265 static void vp9_ref_cnt_fb(struct vdec_vp9_inst *inst, int *idx,
266 			   int new_idx)
267 {
268 	struct vdec_vp9_vsi *vsi = inst->vsi;
269 	int ref_idx = *idx;
270 
271 	if (ref_idx >= 0 && vsi->frm_bufs[ref_idx].ref_cnt > 0) {
272 		vsi->frm_bufs[ref_idx].ref_cnt--;
273 
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)) {
277 				struct vdec_fb *fb;
278 
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);
282 			} else
283 				vp9_free_sf_ref_fb(
284 					vsi->frm_bufs[ref_idx].buf.fb);
285 		}
286 	}
287 
288 	*idx = new_idx;
289 	vsi->frm_bufs[new_idx].ref_cnt++;
290 }
291 
vp9_free_all_sf_ref_fb(struct vdec_vp9_inst * inst)292 static void vp9_free_all_sf_ref_fb(struct vdec_vp9_inst *inst)
293 {
294 	int i;
295 	struct vdec_vp9_vsi *vsi = inst->vsi;
296 
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;
304 		}
305 	}
306 }
307 
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
312  */
vp9_get_sf_ref_fb(struct vdec_vp9_inst * inst)313 static int vp9_get_sf_ref_fb(struct vdec_vp9_inst *inst)
314 {
315 	int idx;
316 	struct mtk_vcodec_mem *mem_basy_y;
317 	struct mtk_vcodec_mem *mem_basy_c;
318 	struct vdec_vp9_vsi *vsi = inst->vsi;
319 
320 	for (idx = 0;
321 		idx < ARRAY_SIZE(vsi->sf_ref_fb);
322 		idx++) {
323 		if (vsi->sf_ref_fb[idx].fb.base_y.va &&
324 		    vsi->sf_ref_fb[idx].used == 0) {
325 			return idx;
326 		}
327 	}
328 
329 	for (idx = 0;
330 		idx < ARRAY_SIZE(vsi->sf_ref_fb);
331 		idx++) {
332 		if (vsi->sf_ref_fb[idx].fb.base_y.va == NULL)
333 			break;
334 	}
335 
336 	if (idx == ARRAY_SIZE(vsi->sf_ref_fb)) {
337 		mtk_vcodec_err(inst, "List Full");
338 		return -1;
339 	}
340 
341 	mem_basy_y = &vsi->sf_ref_fb[idx].fb.base_y;
342 	mem_basy_y->size = vsi->buf_sz_y_bs +
343 		vsi->buf_len_sz_y;
344 
345 	if (mtk_vcodec_mem_alloc(inst->ctx, mem_basy_y)) {
346 		mtk_vcodec_err(inst, "Cannot allocate sf_ref_buf y_buf");
347 		return -1;
348 	}
349 
350 	mem_basy_c = &vsi->sf_ref_fb[idx].fb.base_c;
351 	mem_basy_c->size = vsi->buf_sz_c_bs +
352 		vsi->buf_len_sz_c;
353 
354 	if (mtk_vcodec_mem_alloc(inst->ctx, mem_basy_c)) {
355 		mtk_vcodec_err(inst, "Cannot allocate sf_ref_fb c_buf");
356 		return -1;
357 	}
358 	vsi->sf_ref_fb[idx].used = 0;
359 
360 	return idx;
361 }
362 
vp9_alloc_work_buf(struct vdec_vp9_inst * inst)363 static bool vp9_alloc_work_buf(struct vdec_vp9_inst *inst)
364 {
365 	struct vdec_vp9_vsi *vsi = inst->vsi;
366 	int result;
367 	struct mtk_vcodec_mem *mem;
368 
369 	unsigned int max_pic_w;
370 	unsigned int max_pic_h;
371 
372 
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;
377 	} else {
378 		max_pic_w = MTK_VDEC_MAX_W;
379 		max_pic_h = MTK_VDEC_MAX_H;
380 	}
381 
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);
386 		return false;
387 	}
388 
389 	mtk_vcodec_debug(inst, "BUF CHG(%d): w/h/sb_w/sb_h=%d/%d/%d/%d",
390 			vsi->resolution_changed,
391 			vsi->pic_w,
392 			vsi->pic_h,
393 			vsi->buf_w,
394 			vsi->buf_h);
395 
396 	mem = &inst->mv_buf;
397 	if (mem->va)
398 		mtk_vcodec_mem_free(inst->ctx, mem);
399 
400 	mem->size = ((vsi->buf_w / 64) *
401 		    (vsi->buf_h / 64) + 2) * 36 * 16;
402 	result = mtk_vcodec_mem_alloc(inst->ctx, mem);
403 	if (result) {
404 		mem->size = 0;
405 		mtk_vcodec_err(inst, "Cannot allocate mv_buf");
406 		return false;
407 	}
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;
412 
413 
414 	mem = &inst->seg_id_buf;
415 	if (mem->va)
416 		mtk_vcodec_mem_free(inst->ctx, mem);
417 
418 	mem->size = VP9_SEG_ID_SZ;
419 	result = mtk_vcodec_mem_alloc(inst->ctx, mem);
420 	if (result) {
421 		mem->size = 0;
422 		mtk_vcodec_err(inst, "Cannot allocate seg_id_buf");
423 		return false;
424 	}
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;
429 
430 
431 	vp9_free_all_sf_ref_fb(inst);
432 	vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
433 
434 	return true;
435 }
436 
vp9_add_to_fb_disp_list(struct vdec_vp9_inst * inst,struct vdec_fb * fb)437 static bool vp9_add_to_fb_disp_list(struct vdec_vp9_inst *inst,
438 			     struct vdec_fb *fb)
439 {
440 	struct vdec_fb_node *node;
441 
442 	if (!fb) {
443 		mtk_vcodec_err(inst, "fb == NULL");
444 		return false;
445 	}
446 
447 	node = list_first_entry_or_null(&inst->available_fb_node_list,
448 					struct vdec_fb_node, list);
449 	if (node) {
450 		node->fb = fb;
451 		list_move_tail(&node->list, &inst->fb_disp_list);
452 	} else {
453 		mtk_vcodec_err(inst, "No available fb node");
454 		return false;
455 	}
456 
457 	return true;
458 }
459 
460 /* If any buffer updating is signaled it should be done here. */
vp9_swap_frm_bufs(struct vdec_vp9_inst * inst)461 static void vp9_swap_frm_bufs(struct vdec_vp9_inst *inst)
462 {
463 	struct vdec_vp9_vsi *vsi = inst->vsi;
464 	struct vp9_fb_info *frm_to_show;
465 	int ref_index = 0, mask;
466 
467 	for (mask = vsi->refresh_frm_flags; mask; mask >>= 1) {
468 		if (mask & 1)
469 			vp9_ref_cnt_fb(inst, &vsi->ref_frm_map[ref_index],
470 				       vsi->new_fb_idx);
471 		++ref_index;
472 	}
473 
474 	frm_to_show = &vsi->frm_bufs[vsi->new_fb_idx].buf;
475 	vsi->frm_bufs[vsi->new_fb_idx].ref_cnt--;
476 
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
480 		 * buffer
481 		 */
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,
487 				vsi->buf_w *
488 				vsi->buf_h);
489 			memcpy((void *)inst->cur_fb->base_c.va,
490 				(void *)frm_to_show->fb->base_c.va,
491 				vsi->buf_w *
492 				vsi->buf_h / 2);
493 		} else {
494 			/* After resolution change case, current CAPTURE buffer
495 			 * may have less buffer size than frm_to_show buffer
496 			 * size
497 			 */
498 			if (frm_to_show->fb != NULL)
499 				mtk_vcodec_err(inst,
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);
503 		}
504 		if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) {
505 			if (vsi->show_frame)
506 				vp9_add_to_fb_disp_list(inst, inst->cur_fb);
507 		}
508 	} else {
509 		if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) {
510 			if (vsi->show_frame)
511 				vp9_add_to_fb_disp_list(inst, frm_to_show->fb);
512 		}
513 	}
514 
515 	/* when ref_cnt ==0, move this fb to fb_free_list. v4l2 driver will
516 	 * clean fb_free_list
517 	 */
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)) {
521 			struct vdec_fb *fb;
522 
523 			fb = vp9_rm_from_fb_use_list(inst,
524 			vsi->frm_bufs[vsi->new_fb_idx].buf.fb->base_y.va);
525 
526 			vp9_add_to_fb_free_list(inst, fb);
527 		} else {
528 			vp9_free_sf_ref_fb(
529 				vsi->frm_bufs[vsi->new_fb_idx].buf.fb);
530 		}
531 	}
532 
533 	/* if this super frame and it is not last sub-frame, get next fb for
534 	 * sub-frame decode
535 	 */
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);
538 }
539 
vp9_wait_dec_end(struct vdec_vp9_inst * inst)540 static bool vp9_wait_dec_end(struct vdec_vp9_inst *inst)
541 {
542 	struct mtk_vcodec_ctx *ctx = inst->ctx;
543 
544 	mtk_vcodec_wait_for_done_ctx(inst->ctx,
545 			MTK_INST_IRQ_RECEIVED,
546 			WAIT_INTR_TIMEOUT_MS);
547 
548 	if (ctx->irq_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
549 		return true;
550 	else
551 		return false;
552 }
553 
vp9_alloc_inst(struct mtk_vcodec_ctx * ctx)554 static struct vdec_vp9_inst *vp9_alloc_inst(struct mtk_vcodec_ctx *ctx)
555 {
556 	int result;
557 	struct mtk_vcodec_mem mem;
558 	struct vdec_vp9_inst *inst;
559 
560 	memset(&mem, 0, sizeof(mem));
561 	mem.size = sizeof(struct vdec_vp9_inst);
562 	result = mtk_vcodec_mem_alloc(ctx, &mem);
563 	if (result)
564 		return NULL;
565 
566 	inst = mem.va;
567 	inst->mem = mem;
568 
569 	return inst;
570 }
571 
vp9_free_inst(struct vdec_vp9_inst * inst)572 static void vp9_free_inst(struct vdec_vp9_inst *inst)
573 {
574 	struct mtk_vcodec_mem mem;
575 
576 	mem = inst->mem;
577 	if (mem.va)
578 		mtk_vcodec_mem_free(inst->ctx, &mem);
579 }
580 
vp9_decode_end_proc(struct vdec_vp9_inst * inst)581 static bool vp9_decode_end_proc(struct vdec_vp9_inst *inst)
582 {
583 	struct vdec_vp9_vsi *vsi = inst->vsi;
584 	bool ret = false;
585 
586 	if (!vsi->show_existing_frame) {
587 		ret = vp9_wait_dec_end(inst);
588 		if (!ret) {
589 			mtk_vcodec_err(inst, "Decode failed, Decode Timeout @[%d]",
590 				vsi->frm_num);
591 			return false;
592 		}
593 
594 		if (vpu_dec_end(&inst->vpu)) {
595 			mtk_vcodec_err(inst, "vp9_dec_vpu_end failed");
596 			return false;
597 		}
598 		mtk_vcodec_debug(inst, "Decode Ok @%d (%d/%d)", vsi->frm_num,
599 				vsi->pic_w, vsi->pic_h);
600 	} else {
601 		mtk_vcodec_debug(inst, "Decode Ok @%d (show_existing_frame)",
602 				vsi->frm_num);
603 	}
604 
605 	vp9_swap_frm_bufs(inst);
606 	vsi->frm_num++;
607 	return true;
608 }
609 
vp9_is_last_sub_frm(struct vdec_vp9_inst * inst)610 static bool vp9_is_last_sub_frm(struct vdec_vp9_inst *inst)
611 {
612 	struct vdec_vp9_vsi *vsi = inst->vsi;
613 
614 	if (vsi->sf_frm_cnt <= 0 || vsi->sf_frm_idx == vsi->sf_frm_cnt)
615 		return true;
616 
617 	return false;
618 }
619 
vp9_rm_from_fb_disp_list(struct vdec_vp9_inst * inst)620 static struct vdec_fb *vp9_rm_from_fb_disp_list(struct vdec_vp9_inst *inst)
621 {
622 	struct vdec_fb_node *node;
623 	struct vdec_fb *fb = NULL;
624 
625 	node = list_first_entry_or_null(&inst->fb_disp_list,
626 					struct vdec_fb_node, list);
627 	if (node) {
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);
633 	} else
634 		mtk_vcodec_debug(inst, "[FB] there is no disp fb");
635 
636 	return fb;
637 }
638 
vp9_add_to_fb_use_list(struct vdec_vp9_inst * inst,struct vdec_fb * fb)639 static bool vp9_add_to_fb_use_list(struct vdec_vp9_inst *inst,
640 			    struct vdec_fb *fb)
641 {
642 	struct vdec_fb_node *node;
643 
644 	if (!fb) {
645 		mtk_vcodec_debug(inst, "fb == NULL");
646 		return false;
647 	}
648 
649 	node = list_first_entry_or_null(&inst->available_fb_node_list,
650 					struct vdec_fb_node, list);
651 	if (node) {
652 		node->fb = fb;
653 		list_move_tail(&node->list, &inst->fb_use_list);
654 	} else {
655 		mtk_vcodec_err(inst, "No free fb node");
656 		return false;
657 	}
658 	return true;
659 }
660 
vp9_reset(struct vdec_vp9_inst * inst)661 static void vp9_reset(struct vdec_vp9_inst *inst)
662 {
663 	struct vdec_fb_node *node, *tmp;
664 
665 	list_for_each_entry_safe(node, tmp, &inst->fb_use_list, list)
666 		list_move_tail(&node->list, &inst->fb_free_list);
667 
668 	vp9_free_all_sf_ref_fb(inst);
669 	inst->vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
670 
671 	if (vpu_dec_reset(&inst->vpu))
672 		mtk_vcodec_err(inst, "vp9_dec_vpu_reset failed");
673 
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;
678 
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;
683 
684 }
685 
init_all_fb_lists(struct vdec_vp9_inst * inst)686 static void init_all_fb_lists(struct vdec_vp9_inst *inst)
687 {
688 	int i;
689 
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);
694 
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);
700 	}
701 }
702 
get_pic_info(struct vdec_vp9_inst * inst,struct vdec_pic_info * pic)703 static void get_pic_info(struct vdec_vp9_inst *inst, struct vdec_pic_info *pic)
704 {
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;
709 
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;
714 
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);
719 }
720 
get_disp_fb(struct vdec_vp9_inst * inst,struct vdec_fb ** out_fb)721 static void get_disp_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb)
722 {
723 
724 	*out_fb = vp9_rm_from_fb_disp_list(inst);
725 	if (*out_fb)
726 		(*out_fb)->status |= FB_ST_DISPLAY;
727 }
728 
get_free_fb(struct vdec_vp9_inst * inst,struct vdec_fb ** out_fb)729 static void get_free_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb)
730 {
731 	struct vdec_fb_node *node;
732 	struct vdec_fb *fb = NULL;
733 
734 	node = list_first_entry_or_null(&inst->fb_free_list,
735 					struct vdec_fb_node, list);
736 	if (node) {
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);
742 	} else {
743 		mtk_vcodec_debug(inst, "[FB] there is no free fb");
744 	}
745 
746 	*out_fb = fb;
747 }
748 
validate_vsi_array_indexes(struct vdec_vp9_inst * inst,struct vdec_vp9_vsi * vsi)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.",
753 				vsi->sf_frm_idx);
754 		return -EIO;
755 	}
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);
759 		return -EIO;
760 	}
761 	if (vsi->new_fb_idx >= VP9_MAX_FRM_BUF_NUM) {
762 		mtk_vcodec_err(inst, "Invalid vsi->new_fb_idx=%u.",
763 				vsi->new_fb_idx);
764 		return -EIO;
765 	}
766 	return 0;
767 }
768 
vdec_vp9_deinit(unsigned long h_vdec)769 static void vdec_vp9_deinit(unsigned long h_vdec)
770 {
771 	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
772 	struct mtk_vcodec_mem *mem;
773 	int ret = 0;
774 
775 	ret = vpu_dec_deinit(&inst->vpu);
776 	if (ret)
777 		mtk_vcodec_err(inst, "vpu_dec_deinit failed");
778 
779 	mem = &inst->mv_buf;
780 	if (mem->va)
781 		mtk_vcodec_mem_free(inst->ctx, mem);
782 
783 	mem = &inst->seg_id_buf;
784 	if (mem->va)
785 		mtk_vcodec_mem_free(inst->ctx, mem);
786 
787 	vp9_free_all_sf_ref_fb(inst);
788 	vp9_free_inst(inst);
789 }
790 
vdec_vp9_init(struct mtk_vcodec_ctx * ctx,unsigned long * h_vdec)791 static int vdec_vp9_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
792 {
793 	struct vdec_vp9_inst *inst;
794 
795 	inst = vp9_alloc_inst(ctx);
796 	if (!inst)
797 		return -ENOMEM;
798 
799 	inst->total_frm_cnt = 0;
800 	inst->ctx = ctx;
801 
802 	inst->vpu.id = IPI_VDEC_VP9;
803 	inst->vpu.dev = ctx->dev->vpu_plat_dev;
804 	inst->vpu.ctx = ctx;
805 	inst->vpu.handler = vpu_dec_ipi_handler;
806 
807 	if (vpu_dec_init(&inst->vpu)) {
808 		mtk_vcodec_err(inst, "vp9_dec_vpu_init failed");
809 		goto err_deinit_inst;
810 	}
811 
812 	inst->vsi = (struct vdec_vp9_vsi *)inst->vpu.vsi;
813 	init_all_fb_lists(inst);
814 
815 	(*h_vdec) = (unsigned long)inst;
816 	return 0;
817 
818 err_deinit_inst:
819 	vp9_free_inst(inst);
820 
821 	return -EINVAL;
822 }
823 
vdec_vp9_decode(unsigned long h_vdec,struct mtk_vcodec_mem * bs,struct vdec_fb * fb,bool * res_chg)824 static int vdec_vp9_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
825 		   struct vdec_fb *fb, bool *res_chg)
826 {
827 	int ret = 0;
828 	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
829 	struct vdec_vp9_vsi *vsi = inst->vsi;
830 	u32 data[3];
831 	int i;
832 
833 	*res_chg = false;
834 
835 	if ((bs == NULL) && (fb == NULL)) {
836 		mtk_vcodec_debug(inst, "[EOS]");
837 		vp9_reset(inst);
838 		return ret;
839 	}
840 
841 	if (bs == NULL) {
842 		mtk_vcodec_err(inst, "bs == NULL");
843 		return -EINVAL;
844 	}
845 
846 	mtk_vcodec_debug(inst, "Input BS Size = %zu", bs->size);
847 
848 	while (1) {
849 		struct vdec_fb *cur_fb = NULL;
850 
851 		data[0] = *((unsigned int *)bs->va);
852 		data[1] = *((unsigned int *)(bs->va + 4));
853 		data[2] = *((unsigned int *)(bs->va + 8));
854 
855 		vsi->bs = *bs;
856 
857 		if (fb)
858 			vsi->fb = *fb;
859 
860 		if (!vsi->sf_init) {
861 			unsigned int sf_bs_sz;
862 			unsigned int sf_bs_off;
863 			unsigned char *sf_bs_src;
864 			unsigned char *sf_bs_dst;
865 
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);
872 		} else {
873 			if ((vsi->sf_frm_cnt > 0) &&
874 				(vsi->sf_frm_idx < vsi->sf_frm_cnt)) {
875 				unsigned int idx = vsi->sf_frm_idx;
876 
877 				memcpy((void *)bs->va,
878 					(void *)(bs->va +
879 					vsi->sf_frm_offset[idx]),
880 					vsi->sf_frm_sz[idx]);
881 			}
882 		}
883 		memset(inst->seg_id_buf.va, 0, inst->seg_id_buf.size);
884 		ret = vpu_dec_start(&inst->vpu, data, 3);
885 		if (ret) {
886 			mtk_vcodec_err(inst, "vpu_dec_start failed");
887 			goto DECODE_ERROR;
888 		}
889 
890 		ret = validate_vsi_array_indexes(inst, vsi);
891 		if (ret) {
892 			mtk_vcodec_err(inst, "Invalid values from VPU.");
893 			goto DECODE_ERROR;
894 		}
895 
896 		if (vsi->resolution_changed) {
897 			if (!vp9_alloc_work_buf(inst)) {
898 				ret = -EINVAL;
899 				goto DECODE_ERROR;
900 			}
901 		}
902 
903 		if (vsi->sf_frm_cnt > 0) {
904 			cur_fb = &vsi->sf_ref_fb[vsi->sf_next_ref_fb_idx].fb;
905 
906 			if (vsi->sf_frm_idx < vsi->sf_frm_cnt)
907 				inst->cur_fb = cur_fb;
908 			else
909 				inst->cur_fb = fb;
910 		} else {
911 			inst->cur_fb = fb;
912 		}
913 
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);
917 
918 		mtk_vcodec_debug(inst, "[#pic %d]", vsi->frm_num);
919 
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);
924 
925 		if (vsi->show_existing_frame && (vsi->frm_to_show_idx <
926 					VP9_MAX_FRM_BUF_NUM)) {
927 			mtk_vcodec_err(inst,
928 				"Skip Decode drv->new_fb_idx=%d, drv->frm_to_show_idx=%d",
929 				vsi->new_fb_idx, vsi->frm_to_show_idx);
930 
931 			vp9_ref_cnt_fb(inst, &vsi->new_fb_idx,
932 					vsi->frm_to_show_idx);
933 			ret = -EINVAL;
934 			goto DECODE_ERROR;
935 		}
936 
937 		/* VPU assign the buffer pointer in its address space,
938 		 * reassign here
939 		 */
940 		for (i = 0; i < ARRAY_SIZE(vsi->frm_refs); i++) {
941 			unsigned int idx = vsi->frm_refs[i].idx;
942 
943 			vsi->frm_refs[i].buf = &vsi->frm_bufs[idx].buf;
944 		}
945 
946 		if (vsi->resolution_changed) {
947 			*res_chg = true;
948 			mtk_vcodec_debug(inst, "VDEC_ST_RESOLUTION_CHANGED");
949 
950 			ret = 0;
951 			goto DECODE_ERROR;
952 		}
953 
954 		if (vp9_decode_end_proc(inst) != true) {
955 			mtk_vcodec_err(inst, "vp9_decode_end_proc");
956 			ret = -EINVAL;
957 			goto DECODE_ERROR;
958 		}
959 
960 		if (vp9_is_last_sub_frm(inst))
961 			break;
962 
963 	}
964 	inst->total_frm_cnt++;
965 
966 DECODE_ERROR:
967 	if (ret < 0)
968 		vp9_add_to_fb_free_list(inst, fb);
969 
970 	return ret;
971 }
972 
get_crop_info(struct vdec_vp9_inst * inst,struct v4l2_rect * cr)973 static void get_crop_info(struct vdec_vp9_inst *inst, struct v4l2_rect *cr)
974 {
975 	cr->left = 0;
976 	cr->top = 0;
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);
981 }
982 
vdec_vp9_get_param(unsigned long h_vdec,enum vdec_get_param_type type,void * out)983 static int vdec_vp9_get_param(unsigned long h_vdec,
984 		enum vdec_get_param_type type, void *out)
985 {
986 	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
987 	int ret = 0;
988 
989 	switch (type) {
990 	case GET_PARAM_DISP_FRAME_BUFFER:
991 		get_disp_fb(inst, out);
992 		break;
993 	case GET_PARAM_FREE_FRAME_BUFFER:
994 		get_free_fb(inst, out);
995 		break;
996 	case GET_PARAM_PIC_INFO:
997 		get_pic_info(inst, out);
998 		break;
999 	case GET_PARAM_DPB_SIZE:
1000 		*((unsigned int *)out) = MAX_VP9_DPB_SIZE;
1001 		break;
1002 	case GET_PARAM_CROP_INFO:
1003 		get_crop_info(inst, out);
1004 		break;
1005 	default:
1006 		mtk_vcodec_err(inst, "not supported param type %d", type);
1007 		ret = -EINVAL;
1008 		break;
1009 	}
1010 
1011 	return ret;
1012 }
1013 
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,
1019 };
1020 
1021 struct vdec_common_if *get_vp9_dec_comm_if(void);
1022 
get_vp9_dec_comm_if(void)1023 struct vdec_common_if *get_vp9_dec_comm_if(void)
1024 {
1025 	return &vdec_vp9_if;
1026 }
1027