This source file includes following definitions.
- get_hw_reg_base
- write_hw_segmentation_data
- read_hw_segmentation_data
- enable_hw_rw_function
- store_dec_table
- load_dec_table
- get_pic_info
- vp8_dec_finish
- move_fb_list_use_to_free
- init_list
- add_fb_to_free_list
- alloc_working_buf
- free_working_buf
- vdec_vp8_init
- vdec_vp8_decode
- get_disp_fb
- get_free_fb
- get_crop_info
- vdec_vp8_get_param
- vdec_vp8_deinit
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 #include <linux/slab.h>
   9 #include "../vdec_drv_if.h"
  10 #include "../mtk_vcodec_util.h"
  11 #include "../mtk_vcodec_dec.h"
  12 #include "../mtk_vcodec_intr.h"
  13 #include "../vdec_vpu_if.h"
  14 #include "../vdec_drv_base.h"
  15 
  16 
  17 #define VP8_DPB_SIZE                    4
  18 
  19 
  20 #define VP8_WORKING_BUF_SZ              (45 * 4096)
  21 
  22 
  23 #define VP8_SEGID_DRAM_ADDR             0x3c
  24 #define VP8_HW_VLD_ADDR                 0x93C
  25 #define VP8_HW_VLD_VALUE                0x940
  26 #define VP8_BSASET                      0x100
  27 #define VP8_BSDSET                      0x104
  28 #define VP8_RW_CKEN_SET                 0x0
  29 #define VP8_RW_DCM_CON                  0x18
  30 #define VP8_WO_VLD_SRST                 0x108
  31 #define VP8_RW_MISC_SYS_SEL             0x84
  32 #define VP8_RW_MISC_SPEC_CON            0xC8
  33 #define VP8_WO_VLD_SRST                 0x108
  34 #define VP8_RW_VP8_CTRL                 0xA4
  35 #define VP8_RW_MISC_DCM_CON             0xEC
  36 #define VP8_RW_MISC_SRST                0xF4
  37 #define VP8_RW_MISC_FUNC_CON            0xCC
  38 
  39 #define VP8_MAX_FRM_BUF_NUM             5
  40 #define VP8_MAX_FRM_BUF_NODE_NUM        (VP8_MAX_FRM_BUF_NUM * 2)
  41 
  42 
  43 #define VP8_HW_SEGMENT_DATA_SZ          272
  44 #define VP8_HW_SEGMENT_UINT             4
  45 
  46 #define VP8_DEC_TABLE_PROC_LOOP         96
  47 #define VP8_DEC_TABLE_UNIT              3
  48 #define VP8_DEC_TABLE_SZ                300
  49 #define VP8_DEC_TABLE_OFFSET            2
  50 #define VP8_DEC_TABLE_RW_UNIT           4
  51 
  52 
  53 
  54 
  55 
  56 
  57 
  58 
  59 
  60 
  61 
  62 
  63 
  64 struct vdec_vp8_dec_info {
  65         uint64_t working_buf_dma;
  66         uint64_t prev_y_dma;
  67         uint64_t cur_y_fb_dma;
  68         uint64_t cur_c_fb_dma;
  69         uint64_t bs_dma;
  70         uint32_t bs_sz;
  71         uint32_t resolution_changed;
  72         uint32_t show_frame;
  73         uint32_t wait_key_frame;
  74 };
  75 
  76 
  77 
  78 
  79 
  80 
  81 
  82 
  83 
  84 struct vdec_vp8_vsi {
  85         struct vdec_vp8_dec_info dec;
  86         struct vdec_pic_info pic;
  87         uint32_t dec_table[VP8_DEC_TABLE_SZ];
  88         uint32_t segment_buf[VP8_HW_SEGMENT_DATA_SZ][VP8_HW_SEGMENT_UINT];
  89         uint32_t load_data;
  90 };
  91 
  92 
  93 
  94 
  95 
  96 
  97 
  98 
  99 
 100 
 101 
 102 struct vdec_vp8_hw_reg_base {
 103         void __iomem *sys;
 104         void __iomem *misc;
 105         void __iomem *ld;
 106         void __iomem *top;
 107         void __iomem *cm;
 108         void __iomem *hwd;
 109         void __iomem *hwb;
 110 };
 111 
 112 
 113 
 114 
 115 
 116 
 117 
 118 
 119 struct vdec_vp8_vpu_inst {
 120         wait_queue_head_t wq_hd;
 121         int signaled;
 122         int failure;
 123         uint32_t inst_addr;
 124 };
 125 
 126 
 127 
 128 
 129 
 130 
 131 
 132 
 133 
 134 
 135 
 136 
 137 
 138 
 139 
 140 
 141 
 142 
 143 
 144 
 145 
 146 
 147 
 148 
 149 
 150 
 151 
 152 
 153 struct vdec_vp8_inst {
 154         struct vdec_fb *cur_fb;
 155         struct vdec_fb_node dec_fb[VP8_MAX_FRM_BUF_NODE_NUM];
 156         struct list_head available_fb_node_list;
 157         struct list_head fb_use_list;
 158         struct list_head fb_free_list;
 159         struct list_head fb_disp_list;
 160         struct mtk_vcodec_mem working_buf;
 161         struct vdec_vp8_hw_reg_base reg_base;
 162         unsigned int frm_cnt;
 163         struct mtk_vcodec_ctx *ctx;
 164         struct vdec_vpu_inst vpu;
 165         struct vdec_vp8_vsi *vsi;
 166 };
 167 
 168 static void get_hw_reg_base(struct vdec_vp8_inst *inst)
 169 {
 170         inst->reg_base.top = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_TOP);
 171         inst->reg_base.cm = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_CM);
 172         inst->reg_base.hwd = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_HWD);
 173         inst->reg_base.sys = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_SYS);
 174         inst->reg_base.misc = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_MISC);
 175         inst->reg_base.ld = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_LD);
 176         inst->reg_base.hwb = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_HWB);
 177 }
 178 
 179 static void write_hw_segmentation_data(struct vdec_vp8_inst *inst)
 180 {
 181         int i, j;
 182         u32 seg_id_addr;
 183         u32 val;
 184         void __iomem *cm = inst->reg_base.cm;
 185         struct vdec_vp8_vsi *vsi = inst->vsi;
 186 
 187         seg_id_addr = readl(inst->reg_base.top + VP8_SEGID_DRAM_ADDR) >> 4;
 188 
 189         for (i = 0; i < ARRAY_SIZE(vsi->segment_buf); i++) {
 190                 for (j = ARRAY_SIZE(vsi->segment_buf[i]) - 1; j >= 0; j--) {
 191                         val = (1 << 16) + ((seg_id_addr + i) << 2) + j;
 192                         writel(val, cm + VP8_HW_VLD_ADDR);
 193 
 194                         val = vsi->segment_buf[i][j];
 195                         writel(val, cm + VP8_HW_VLD_VALUE);
 196                 }
 197         }
 198 }
 199 
 200 static void read_hw_segmentation_data(struct vdec_vp8_inst *inst)
 201 {
 202         int i, j;
 203         u32 seg_id_addr;
 204         u32 val;
 205         void __iomem *cm = inst->reg_base.cm;
 206         struct vdec_vp8_vsi *vsi = inst->vsi;
 207 
 208         seg_id_addr = readl(inst->reg_base.top + VP8_SEGID_DRAM_ADDR) >> 4;
 209 
 210         for (i = 0; i < ARRAY_SIZE(vsi->segment_buf); i++) {
 211                 for (j = ARRAY_SIZE(vsi->segment_buf[i]) - 1; j >= 0; j--) {
 212                         val = ((seg_id_addr + i) << 2) + j;
 213                         writel(val, cm + VP8_HW_VLD_ADDR);
 214 
 215                         val = readl(cm + VP8_HW_VLD_VALUE);
 216                         vsi->segment_buf[i][j] = val;
 217                 }
 218         }
 219 }
 220 
 221 
 222 static void enable_hw_rw_function(struct vdec_vp8_inst *inst)
 223 {
 224         u32 val = 0;
 225         void __iomem *sys = inst->reg_base.sys;
 226         void __iomem *misc = inst->reg_base.misc;
 227         void __iomem *ld = inst->reg_base.ld;
 228         void __iomem *hwb = inst->reg_base.hwb;
 229         void __iomem *hwd = inst->reg_base.hwd;
 230 
 231         writel(0x1, sys + VP8_RW_CKEN_SET);
 232         writel(0x101, ld + VP8_WO_VLD_SRST);
 233         writel(0x101, hwb + VP8_WO_VLD_SRST);
 234 
 235         writel(1, sys);
 236         val = readl(misc + VP8_RW_MISC_SRST);
 237         writel((val & 0xFFFFFFFE), misc + VP8_RW_MISC_SRST);
 238 
 239         writel(0x1, misc + VP8_RW_MISC_SYS_SEL);
 240         writel(0x17F, misc + VP8_RW_MISC_SPEC_CON);
 241         writel(0x71201100, misc + VP8_RW_MISC_FUNC_CON);
 242         writel(0x0, ld + VP8_WO_VLD_SRST);
 243         writel(0x0, hwb + VP8_WO_VLD_SRST);
 244         writel(0x1, sys + VP8_RW_DCM_CON);
 245         writel(0x1, misc + VP8_RW_MISC_DCM_CON);
 246         writel(0x1, hwd + VP8_RW_VP8_CTRL);
 247 }
 248 
 249 static void store_dec_table(struct vdec_vp8_inst *inst)
 250 {
 251         int i, j;
 252         u32 addr = 0, val = 0;
 253         void __iomem *hwd = inst->reg_base.hwd;
 254         u32 *p = &inst->vsi->dec_table[VP8_DEC_TABLE_OFFSET];
 255 
 256         for (i = 0; i < VP8_DEC_TABLE_PROC_LOOP; i++) {
 257                 writel(addr, hwd + VP8_BSASET);
 258                 for (j = 0; j < VP8_DEC_TABLE_UNIT ; j++) {
 259                         val = *p++;
 260                         writel(val, hwd + VP8_BSDSET);
 261                 }
 262                 addr += VP8_DEC_TABLE_RW_UNIT;
 263         }
 264 }
 265 
 266 static void load_dec_table(struct vdec_vp8_inst *inst)
 267 {
 268         int i;
 269         u32 addr = 0;
 270         u32 *p = &inst->vsi->dec_table[VP8_DEC_TABLE_OFFSET];
 271         void __iomem *hwd = inst->reg_base.hwd;
 272 
 273         for (i = 0; i < VP8_DEC_TABLE_PROC_LOOP; i++) {
 274                 writel(addr, hwd + VP8_BSASET);
 275                 
 276                 *p++ = readl(hwd + VP8_BSDSET);
 277                 *p++ = readl(hwd + VP8_BSDSET);
 278                 *p++ = readl(hwd + VP8_BSDSET) & 0xFFFFFF;
 279                 addr += VP8_DEC_TABLE_RW_UNIT;
 280         }
 281 }
 282 
 283 static void get_pic_info(struct vdec_vp8_inst *inst, struct vdec_pic_info *pic)
 284 {
 285         *pic = inst->vsi->pic;
 286 
 287         mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
 288                          pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
 289         mtk_vcodec_debug(inst, "fb size: Y(%d), C(%d)",
 290                          pic->fb_sz[0], pic->fb_sz[1]);
 291 }
 292 
 293 static void vp8_dec_finish(struct vdec_vp8_inst *inst)
 294 {
 295         struct vdec_fb_node *node;
 296         uint64_t prev_y_dma = inst->vsi->dec.prev_y_dma;
 297 
 298         mtk_vcodec_debug(inst, "prev fb base dma=%llx", prev_y_dma);
 299 
 300         
 301         if (prev_y_dma != 0) {
 302                 list_for_each_entry(node, &inst->fb_use_list, list) {
 303                         struct vdec_fb *fb = (struct vdec_fb *)node->fb;
 304 
 305                         if (prev_y_dma == (uint64_t)fb->base_y.dma_addr) {
 306                                 list_move_tail(&node->list,
 307                                                &inst->fb_free_list);
 308                                 break;
 309                         }
 310                 }
 311         }
 312 
 313         
 314         node = list_first_entry(&inst->available_fb_node_list,
 315                                 struct vdec_fb_node, list);
 316         node->fb = inst->cur_fb;
 317         list_move_tail(&node->list, &inst->fb_use_list);
 318 
 319         
 320         if (inst->vsi->dec.show_frame) {
 321                 node = list_first_entry(&inst->available_fb_node_list,
 322                                         struct vdec_fb_node, list);
 323                 node->fb = inst->cur_fb;
 324                 list_move_tail(&node->list, &inst->fb_disp_list);
 325         }
 326 }
 327 
 328 static void move_fb_list_use_to_free(struct vdec_vp8_inst *inst)
 329 {
 330         struct vdec_fb_node *node, *tmp;
 331 
 332         list_for_each_entry_safe(node, tmp, &inst->fb_use_list, list)
 333                 list_move_tail(&node->list, &inst->fb_free_list);
 334 }
 335 
 336 static void init_list(struct vdec_vp8_inst *inst)
 337 {
 338         int i;
 339 
 340         INIT_LIST_HEAD(&inst->available_fb_node_list);
 341         INIT_LIST_HEAD(&inst->fb_use_list);
 342         INIT_LIST_HEAD(&inst->fb_free_list);
 343         INIT_LIST_HEAD(&inst->fb_disp_list);
 344 
 345         for (i = 0; i < ARRAY_SIZE(inst->dec_fb); i++) {
 346                 INIT_LIST_HEAD(&inst->dec_fb[i].list);
 347                 inst->dec_fb[i].fb = NULL;
 348                 list_add_tail(&inst->dec_fb[i].list,
 349                               &inst->available_fb_node_list);
 350         }
 351 }
 352 
 353 static void add_fb_to_free_list(struct vdec_vp8_inst *inst, void *fb)
 354 {
 355         struct vdec_fb_node *node;
 356 
 357         if (fb) {
 358                 node = list_first_entry(&inst->available_fb_node_list,
 359                                         struct vdec_fb_node, list);
 360                 node->fb = fb;
 361                 list_move_tail(&node->list, &inst->fb_free_list);
 362         }
 363 }
 364 
 365 static int alloc_working_buf(struct vdec_vp8_inst *inst)
 366 {
 367         int err;
 368         struct mtk_vcodec_mem *mem = &inst->working_buf;
 369 
 370         mem->size = VP8_WORKING_BUF_SZ;
 371         err = mtk_vcodec_mem_alloc(inst->ctx, mem);
 372         if (err) {
 373                 mtk_vcodec_err(inst, "Cannot allocate working buffer");
 374                 return err;
 375         }
 376 
 377         inst->vsi->dec.working_buf_dma = (uint64_t)mem->dma_addr;
 378         return 0;
 379 }
 380 
 381 static void free_working_buf(struct vdec_vp8_inst *inst)
 382 {
 383         struct mtk_vcodec_mem *mem = &inst->working_buf;
 384 
 385         if (mem->va)
 386                 mtk_vcodec_mem_free(inst->ctx, mem);
 387 
 388         inst->vsi->dec.working_buf_dma = 0;
 389 }
 390 
 391 static int vdec_vp8_init(struct mtk_vcodec_ctx *ctx)
 392 {
 393         struct vdec_vp8_inst *inst;
 394         int err;
 395 
 396         inst = kzalloc(sizeof(*inst), GFP_KERNEL);
 397         if (!inst)
 398                 return  -ENOMEM;
 399 
 400         inst->ctx = ctx;
 401 
 402         inst->vpu.id = IPI_VDEC_VP8;
 403         inst->vpu.dev = ctx->dev->vpu_plat_dev;
 404         inst->vpu.ctx = ctx;
 405         inst->vpu.handler = vpu_dec_ipi_handler;
 406 
 407         err = vpu_dec_init(&inst->vpu);
 408         if (err) {
 409                 mtk_vcodec_err(inst, "vdec_vp8 init err=%d", err);
 410                 goto error_free_inst;
 411         }
 412 
 413         inst->vsi = (struct vdec_vp8_vsi *)inst->vpu.vsi;
 414         init_list(inst);
 415         err = alloc_working_buf(inst);
 416         if (err)
 417                 goto error_deinit;
 418 
 419         get_hw_reg_base(inst);
 420         mtk_vcodec_debug(inst, "VP8 Instance >> %p", inst);
 421 
 422         ctx->drv_handle = inst;
 423         return 0;
 424 
 425 error_deinit:
 426         vpu_dec_deinit(&inst->vpu);
 427 error_free_inst:
 428         kfree(inst);
 429         return err;
 430 }
 431 
 432 static int vdec_vp8_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
 433                            struct vdec_fb *fb, bool *res_chg)
 434 {
 435         struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
 436         struct vdec_vp8_dec_info *dec = &inst->vsi->dec;
 437         struct vdec_vpu_inst *vpu = &inst->vpu;
 438         unsigned char *bs_va;
 439         unsigned int data;
 440         int err = 0;
 441         uint64_t y_fb_dma;
 442         uint64_t c_fb_dma;
 443 
 444         
 445         if (bs == NULL) {
 446                 move_fb_list_use_to_free(inst);
 447                 return vpu_dec_reset(vpu);
 448         }
 449 
 450         y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
 451         c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
 452 
 453         mtk_vcodec_debug(inst, "+ [%d] FB y_dma=%llx c_dma=%llx fb=%p",
 454                          inst->frm_cnt, y_fb_dma, c_fb_dma, fb);
 455 
 456         inst->cur_fb = fb;
 457         dec->bs_dma = (unsigned long)bs->dma_addr;
 458         dec->bs_sz = bs->size;
 459         dec->cur_y_fb_dma = y_fb_dma;
 460         dec->cur_c_fb_dma = c_fb_dma;
 461 
 462         mtk_vcodec_debug(inst, "\n + FRAME[%d] +\n", inst->frm_cnt);
 463 
 464         write_hw_segmentation_data(inst);
 465         enable_hw_rw_function(inst);
 466         store_dec_table(inst);
 467 
 468         bs_va = (unsigned char *)bs->va;
 469 
 470         
 471         data = (*(bs_va + 9) << 24) | (*(bs_va + 8) << 16) |
 472                (*(bs_va + 7) << 8) | *(bs_va + 6);
 473         err = vpu_dec_start(vpu, &data, 1);
 474         if (err) {
 475                 add_fb_to_free_list(inst, fb);
 476                 if (dec->wait_key_frame) {
 477                         mtk_vcodec_debug(inst, "wait key frame !");
 478                         return 0;
 479                 }
 480 
 481                 goto error;
 482         }
 483 
 484         if (dec->resolution_changed) {
 485                 mtk_vcodec_debug(inst, "- resolution_changed -");
 486                 *res_chg = true;
 487                 add_fb_to_free_list(inst, fb);
 488                 return 0;
 489         }
 490 
 491         
 492         mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
 493                                      WAIT_INTR_TIMEOUT_MS);
 494 
 495         if (inst->vsi->load_data)
 496                 load_dec_table(inst);
 497 
 498         vp8_dec_finish(inst);
 499         read_hw_segmentation_data(inst);
 500 
 501         err = vpu_dec_end(vpu);
 502         if (err)
 503                 goto error;
 504 
 505         mtk_vcodec_debug(inst, "\n - FRAME[%d] - show=%d\n", inst->frm_cnt,
 506                          dec->show_frame);
 507         inst->frm_cnt++;
 508         *res_chg = false;
 509         return 0;
 510 
 511 error:
 512         mtk_vcodec_err(inst, "\n - FRAME[%d] - err=%d\n", inst->frm_cnt, err);
 513         return err;
 514 }
 515 
 516 static void get_disp_fb(struct vdec_vp8_inst *inst, struct vdec_fb **out_fb)
 517 {
 518         struct vdec_fb_node *node;
 519         struct vdec_fb *fb;
 520 
 521         node = list_first_entry_or_null(&inst->fb_disp_list,
 522                                         struct vdec_fb_node, list);
 523         if (node) {
 524                 list_move_tail(&node->list, &inst->available_fb_node_list);
 525                 fb = (struct vdec_fb *)node->fb;
 526                 fb->status |= FB_ST_DISPLAY;
 527                 mtk_vcodec_debug(inst, "[FB] get disp fb %p st=%d",
 528                                  node->fb, fb->status);
 529         } else {
 530                 fb = NULL;
 531                 mtk_vcodec_debug(inst, "[FB] there is no disp fb");
 532         }
 533 
 534         *out_fb = fb;
 535 }
 536 
 537 static void get_free_fb(struct vdec_vp8_inst *inst, struct vdec_fb **out_fb)
 538 {
 539         struct vdec_fb_node *node;
 540         struct vdec_fb *fb;
 541 
 542         node = list_first_entry_or_null(&inst->fb_free_list,
 543                                         struct vdec_fb_node, list);
 544         if (node) {
 545                 list_move_tail(&node->list, &inst->available_fb_node_list);
 546                 fb = (struct vdec_fb *)node->fb;
 547                 fb->status |= FB_ST_FREE;
 548                 mtk_vcodec_debug(inst, "[FB] get free fb %p st=%d",
 549                                  node->fb, fb->status);
 550         } else {
 551                 fb = NULL;
 552                 mtk_vcodec_debug(inst, "[FB] there is no free fb");
 553         }
 554 
 555         *out_fb = fb;
 556 }
 557 
 558 static void get_crop_info(struct vdec_vp8_inst *inst, struct v4l2_rect *cr)
 559 {
 560         cr->left = 0;
 561         cr->top = 0;
 562         cr->width = inst->vsi->pic.pic_w;
 563         cr->height = inst->vsi->pic.pic_h;
 564         mtk_vcodec_debug(inst, "get crop info l=%d, t=%d, w=%d, h=%d",
 565                          cr->left, cr->top, cr->width, cr->height);
 566 }
 567 
 568 static int vdec_vp8_get_param(void *h_vdec, enum vdec_get_param_type type,
 569                               void *out)
 570 {
 571         struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
 572 
 573         switch (type) {
 574         case GET_PARAM_DISP_FRAME_BUFFER:
 575                 get_disp_fb(inst, out);
 576                 break;
 577 
 578         case GET_PARAM_FREE_FRAME_BUFFER:
 579                 get_free_fb(inst, out);
 580                 break;
 581 
 582         case GET_PARAM_PIC_INFO:
 583                 get_pic_info(inst, out);
 584                 break;
 585 
 586         case GET_PARAM_CROP_INFO:
 587                 get_crop_info(inst, out);
 588                 break;
 589 
 590         case GET_PARAM_DPB_SIZE:
 591                 *((unsigned int *)out) = VP8_DPB_SIZE;
 592                 break;
 593 
 594         default:
 595                 mtk_vcodec_err(inst, "invalid get parameter type=%d", type);
 596                 return -EINVAL;
 597         }
 598 
 599         return 0;
 600 }
 601 
 602 static void vdec_vp8_deinit(void *h_vdec)
 603 {
 604         struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
 605 
 606         mtk_vcodec_debug_enter(inst);
 607 
 608         vpu_dec_deinit(&inst->vpu);
 609         free_working_buf(inst);
 610         kfree(inst);
 611 }
 612 
 613 const struct vdec_common_if vdec_vp8_if = {
 614         .init           = vdec_vp8_init,
 615         .decode         = vdec_vp8_decode,
 616         .get_param      = vdec_vp8_get_param,
 617         .deinit         = vdec_vp8_deinit,
 618 };