Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] vcodec: mediatek: Add Mediatek VP9 Video Decoder Driver

Add vp9 decoder driver for MT8173

[mchehab@s-opensource.org: make checkpatch.pl happy]

Signed-off-by: Tiffany Lin <tiffany.lin@mediatek.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

authored by

Tiffany Lin and committed by
Mauro Carvalho Chehab
f77e8985 988fcf0c

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