This source file includes following definitions.
- vp8_enc_read_reg
 
- vp8_enc_free_work_buf
 
- vp8_enc_alloc_work_buf
 
- vp8_enc_wait_venc_done
 
- vp8_enc_compose_one_frame
 
- vp8_enc_encode_frame
 
- vp8_enc_init
 
- vp8_enc_encode
 
- vp8_enc_set_param
 
- vp8_enc_deinit
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 #include <linux/interrupt.h>
   9 #include <linux/kernel.h>
  10 #include <linux/slab.h>
  11 
  12 #include "../mtk_vcodec_drv.h"
  13 #include "../mtk_vcodec_util.h"
  14 #include "../mtk_vcodec_intr.h"
  15 #include "../mtk_vcodec_enc.h"
  16 #include "../mtk_vcodec_enc_pm.h"
  17 #include "../venc_drv_base.h"
  18 #include "../venc_ipi_msg.h"
  19 #include "../venc_vpu_if.h"
  20 #include "mtk_vpu.h"
  21 
  22 #define VENC_BITSTREAM_FRAME_SIZE 0x0098
  23 #define VENC_BITSTREAM_HEADER_LEN 0x00e8
  24 
  25 
  26 #define MAX_AC_TAG_SIZE 10
  27 
  28 
  29 
  30 
  31 enum venc_vp8_vpu_work_buf {
  32         VENC_VP8_VPU_WORK_BUF_LUMA,
  33         VENC_VP8_VPU_WORK_BUF_LUMA2,
  34         VENC_VP8_VPU_WORK_BUF_LUMA3,
  35         VENC_VP8_VPU_WORK_BUF_CHROMA,
  36         VENC_VP8_VPU_WORK_BUF_CHROMA2,
  37         VENC_VP8_VPU_WORK_BUF_CHROMA3,
  38         VENC_VP8_VPU_WORK_BUF_MV_INFO,
  39         VENC_VP8_VPU_WORK_BUF_BS_HEADER,
  40         VENC_VP8_VPU_WORK_BUF_PROB_BUF,
  41         VENC_VP8_VPU_WORK_BUF_RC_INFO,
  42         VENC_VP8_VPU_WORK_BUF_RC_CODE,
  43         VENC_VP8_VPU_WORK_BUF_RC_CODE2,
  44         VENC_VP8_VPU_WORK_BUF_RC_CODE3,
  45         VENC_VP8_VPU_WORK_BUF_MAX,
  46 };
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54 
  55 
  56 
  57 
  58 
  59 
  60 
  61 
  62 
  63 
  64 
  65 
  66 struct venc_vp8_vpu_config {
  67         u32 input_fourcc;
  68         u32 bitrate;
  69         u32 pic_w;
  70         u32 pic_h;
  71         u32 buf_w;
  72         u32 buf_h;
  73         u32 gop_size;
  74         u32 framerate;
  75         u32 ts_mode;
  76 };
  77 
  78 
  79 
  80 
  81 
  82 
  83 
  84 
  85 
  86 struct venc_vp8_vpu_buf {
  87         u32 iova;
  88         u32 vpua;
  89         u32 size;
  90 };
  91 
  92 
  93 
  94 
  95 
  96 
  97 
  98 
  99 
 100 
 101 
 102 
 103 
 104 
 105 
 106 struct venc_vp8_vsi {
 107         struct venc_vp8_vpu_config config;
 108         struct venc_vp8_vpu_buf work_bufs[VENC_VP8_VPU_WORK_BUF_MAX];
 109 };
 110 
 111 
 112 
 113 
 114 
 115 
 116 
 117 
 118 
 119 
 120 
 121 
 122 
 123 
 124 
 125 struct venc_vp8_inst {
 126         void __iomem *hw_base;
 127         struct mtk_vcodec_mem work_bufs[VENC_VP8_VPU_WORK_BUF_MAX];
 128         bool work_buf_allocated;
 129         unsigned int frm_cnt;
 130         unsigned int ts_mode;
 131         struct venc_vpu_inst vpu_inst;
 132         struct venc_vp8_vsi *vsi;
 133         struct mtk_vcodec_ctx *ctx;
 134 };
 135 
 136 static inline u32 vp8_enc_read_reg(struct venc_vp8_inst *inst, u32 addr)
 137 {
 138         return readl(inst->hw_base + addr);
 139 }
 140 
 141 static void vp8_enc_free_work_buf(struct venc_vp8_inst *inst)
 142 {
 143         int i;
 144 
 145         mtk_vcodec_debug_enter(inst);
 146 
 147         
 148         for (i = 0; i < VENC_VP8_VPU_WORK_BUF_MAX; i++) {
 149                 if (inst->work_bufs[i].size == 0)
 150                         continue;
 151                 mtk_vcodec_mem_free(inst->ctx, &inst->work_bufs[i]);
 152         }
 153 
 154         mtk_vcodec_debug_leave(inst);
 155 }
 156 
 157 static int vp8_enc_alloc_work_buf(struct venc_vp8_inst *inst)
 158 {
 159         int i;
 160         int ret = 0;
 161         struct venc_vp8_vpu_buf *wb = inst->vsi->work_bufs;
 162 
 163         mtk_vcodec_debug_enter(inst);
 164 
 165         for (i = 0; i < VENC_VP8_VPU_WORK_BUF_MAX; i++) {
 166                 if (wb[i].size == 0)
 167                         continue;
 168                 
 169 
 170 
 171 
 172 
 173 
 174 
 175 
 176 
 177 
 178                 inst->work_bufs[i].size = wb[i].size;
 179                 ret = mtk_vcodec_mem_alloc(inst->ctx, &inst->work_bufs[i]);
 180                 if (ret) {
 181                         mtk_vcodec_err(inst,
 182                                        "cannot alloc work_bufs[%d]", i);
 183                         goto err_alloc;
 184                 }
 185                 
 186 
 187 
 188 
 189 
 190                 if (i == VENC_VP8_VPU_WORK_BUF_RC_CODE ||
 191                     i == VENC_VP8_VPU_WORK_BUF_RC_CODE2 ||
 192                     i == VENC_VP8_VPU_WORK_BUF_RC_CODE3) {
 193                         void *tmp_va;
 194 
 195                         tmp_va = vpu_mapping_dm_addr(inst->vpu_inst.dev,
 196                                                      wb[i].vpua);
 197                         memcpy(inst->work_bufs[i].va, tmp_va, wb[i].size);
 198                 }
 199                 wb[i].iova = inst->work_bufs[i].dma_addr;
 200 
 201                 mtk_vcodec_debug(inst,
 202                                  "work_bufs[%d] va=0x%p,iova=%pad,size=%zu",
 203                                  i, inst->work_bufs[i].va,
 204                                  &inst->work_bufs[i].dma_addr,
 205                                  inst->work_bufs[i].size);
 206         }
 207 
 208         mtk_vcodec_debug_leave(inst);
 209 
 210         return ret;
 211 
 212 err_alloc:
 213         vp8_enc_free_work_buf(inst);
 214 
 215         return ret;
 216 }
 217 
 218 static unsigned int vp8_enc_wait_venc_done(struct venc_vp8_inst *inst)
 219 {
 220         unsigned int irq_status = 0;
 221         struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)inst->ctx;
 222 
 223         if (!mtk_vcodec_wait_for_done_ctx(ctx, MTK_INST_IRQ_RECEIVED,
 224                                           WAIT_INTR_TIMEOUT_MS)) {
 225                 irq_status = ctx->irq_status;
 226                 mtk_vcodec_debug(inst, "isr return %x", irq_status);
 227         }
 228         return irq_status;
 229 }
 230 
 231 
 232 
 233 
 234 
 235 static int vp8_enc_compose_one_frame(struct venc_vp8_inst *inst,
 236                                      struct mtk_vcodec_mem *bs_buf,
 237                                      unsigned int *bs_size)
 238 {
 239         unsigned int not_key;
 240         u32 bs_frm_size;
 241         u32 bs_hdr_len;
 242         unsigned int ac_tag_size;
 243         u8 ac_tag[MAX_AC_TAG_SIZE];
 244         u32 tag;
 245 
 246         bs_frm_size = vp8_enc_read_reg(inst, VENC_BITSTREAM_FRAME_SIZE);
 247         bs_hdr_len = vp8_enc_read_reg(inst, VENC_BITSTREAM_HEADER_LEN);
 248 
 249         
 250         not_key = !inst->vpu_inst.is_key_frm;
 251         tag = (bs_hdr_len << 5) | 0x10 | not_key;
 252         ac_tag[0] = tag & 0xff;
 253         ac_tag[1] = (tag >> 8) & 0xff;
 254         ac_tag[2] = (tag >> 16) & 0xff;
 255 
 256         
 257         if (not_key == 0) {
 258                 ac_tag_size = MAX_AC_TAG_SIZE;
 259                 ac_tag[3] = 0x9d;
 260                 ac_tag[4] = 0x01;
 261                 ac_tag[5] = 0x2a;
 262                 ac_tag[6] = inst->vsi->config.pic_w;
 263                 ac_tag[7] = inst->vsi->config.pic_w >> 8;
 264                 ac_tag[8] = inst->vsi->config.pic_h;
 265                 ac_tag[9] = inst->vsi->config.pic_h >> 8;
 266         } else {
 267                 ac_tag_size = 3;
 268         }
 269 
 270         if (bs_buf->size < bs_hdr_len + bs_frm_size + ac_tag_size) {
 271                 mtk_vcodec_err(inst, "bitstream buf size is too small(%zu)",
 272                                bs_buf->size);
 273                 return -EINVAL;
 274         }
 275 
 276         
 277 
 278 
 279 
 280 
 281 
 282 
 283         memmove(bs_buf->va + bs_hdr_len + ac_tag_size,
 284                 bs_buf->va, bs_frm_size);
 285         memcpy(bs_buf->va + ac_tag_size,
 286                inst->work_bufs[VENC_VP8_VPU_WORK_BUF_BS_HEADER].va,
 287                bs_hdr_len);
 288         memcpy(bs_buf->va, ac_tag, ac_tag_size);
 289         *bs_size = bs_frm_size + bs_hdr_len + ac_tag_size;
 290 
 291         return 0;
 292 }
 293 
 294 static int vp8_enc_encode_frame(struct venc_vp8_inst *inst,
 295                                 struct venc_frm_buf *frm_buf,
 296                                 struct mtk_vcodec_mem *bs_buf,
 297                                 unsigned int *bs_size)
 298 {
 299         int ret = 0;
 300         unsigned int irq_status;
 301 
 302         mtk_vcodec_debug(inst, "->frm_cnt=%d", inst->frm_cnt);
 303 
 304         ret = vpu_enc_encode(&inst->vpu_inst, 0, frm_buf, bs_buf, bs_size);
 305         if (ret)
 306                 return ret;
 307 
 308         irq_status = vp8_enc_wait_venc_done(inst);
 309         if (irq_status != MTK_VENC_IRQ_STATUS_FRM) {
 310                 mtk_vcodec_err(inst, "irq_status=%d failed", irq_status);
 311                 return -EIO;
 312         }
 313 
 314         if (vp8_enc_compose_one_frame(inst, bs_buf, bs_size)) {
 315                 mtk_vcodec_err(inst, "vp8_enc_compose_one_frame failed");
 316                 return -EINVAL;
 317         }
 318 
 319         inst->frm_cnt++;
 320         mtk_vcodec_debug(inst, "<-size=%d key_frm=%d", *bs_size,
 321                          inst->vpu_inst.is_key_frm);
 322 
 323         return ret;
 324 }
 325 
 326 static int vp8_enc_init(struct mtk_vcodec_ctx *ctx)
 327 {
 328         int ret = 0;
 329         struct venc_vp8_inst *inst;
 330 
 331         inst = kzalloc(sizeof(*inst), GFP_KERNEL);
 332         if (!inst)
 333                 return -ENOMEM;
 334 
 335         inst->ctx = ctx;
 336         inst->vpu_inst.ctx = ctx;
 337         inst->vpu_inst.dev = ctx->dev->vpu_plat_dev;
 338         inst->vpu_inst.id = IPI_VENC_VP8;
 339         inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx, VENC_LT_SYS);
 340 
 341         mtk_vcodec_debug_enter(inst);
 342 
 343         ret = vpu_enc_init(&inst->vpu_inst);
 344 
 345         inst->vsi = (struct venc_vp8_vsi *)inst->vpu_inst.vsi;
 346 
 347         mtk_vcodec_debug_leave(inst);
 348 
 349         if (ret)
 350                 kfree(inst);
 351         else
 352                 ctx->drv_handle = inst;
 353 
 354         return ret;
 355 }
 356 
 357 static int vp8_enc_encode(void *handle,
 358                           enum venc_start_opt opt,
 359                           struct venc_frm_buf *frm_buf,
 360                           struct mtk_vcodec_mem *bs_buf,
 361                           struct venc_done_result *result)
 362 {
 363         int ret = 0;
 364         struct venc_vp8_inst *inst = (struct venc_vp8_inst *)handle;
 365         struct mtk_vcodec_ctx *ctx = inst->ctx;
 366 
 367         mtk_vcodec_debug_enter(inst);
 368 
 369         enable_irq(ctx->dev->enc_lt_irq);
 370 
 371         switch (opt) {
 372         case VENC_START_OPT_ENCODE_FRAME:
 373                 ret = vp8_enc_encode_frame(inst, frm_buf, bs_buf,
 374                                            &result->bs_size);
 375                 if (ret)
 376                         goto encode_err;
 377                 result->is_key_frm = inst->vpu_inst.is_key_frm;
 378                 break;
 379 
 380         default:
 381                 mtk_vcodec_err(inst, "opt not support:%d", opt);
 382                 ret = -EINVAL;
 383                 break;
 384         }
 385 
 386 encode_err:
 387 
 388         disable_irq(ctx->dev->enc_lt_irq);
 389         mtk_vcodec_debug_leave(inst);
 390 
 391         return ret;
 392 }
 393 
 394 static int vp8_enc_set_param(void *handle,
 395                              enum venc_set_param_type type,
 396                              struct venc_enc_param *enc_prm)
 397 {
 398         int ret = 0;
 399         struct venc_vp8_inst *inst = (struct venc_vp8_inst *)handle;
 400 
 401         mtk_vcodec_debug(inst, "->type=%d", type);
 402 
 403         switch (type) {
 404         case VENC_SET_PARAM_ENC:
 405                 inst->vsi->config.input_fourcc = enc_prm->input_yuv_fmt;
 406                 inst->vsi->config.bitrate = enc_prm->bitrate;
 407                 inst->vsi->config.pic_w = enc_prm->width;
 408                 inst->vsi->config.pic_h = enc_prm->height;
 409                 inst->vsi->config.buf_w = enc_prm->buf_width;
 410                 inst->vsi->config.buf_h = enc_prm->buf_height;
 411                 inst->vsi->config.gop_size = enc_prm->gop_size;
 412                 inst->vsi->config.framerate = enc_prm->frm_rate;
 413                 inst->vsi->config.ts_mode = inst->ts_mode;
 414                 ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
 415                 if (ret)
 416                         break;
 417                 if (inst->work_buf_allocated) {
 418                         vp8_enc_free_work_buf(inst);
 419                         inst->work_buf_allocated = false;
 420                 }
 421                 ret = vp8_enc_alloc_work_buf(inst);
 422                 if (ret)
 423                         break;
 424                 inst->work_buf_allocated = true;
 425                 break;
 426 
 427         
 428 
 429 
 430         case VENC_SET_PARAM_TS_MODE:
 431                 inst->ts_mode = 1;
 432                 mtk_vcodec_debug(inst, "set ts_mode");
 433                 break;
 434 
 435         default:
 436                 ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
 437                 break;
 438         }
 439 
 440         mtk_vcodec_debug_leave(inst);
 441 
 442         return ret;
 443 }
 444 
 445 static int vp8_enc_deinit(void *handle)
 446 {
 447         int ret = 0;
 448         struct venc_vp8_inst *inst = (struct venc_vp8_inst *)handle;
 449 
 450         mtk_vcodec_debug_enter(inst);
 451 
 452         ret = vpu_enc_deinit(&inst->vpu_inst);
 453 
 454         if (inst->work_buf_allocated)
 455                 vp8_enc_free_work_buf(inst);
 456 
 457         mtk_vcodec_debug_leave(inst);
 458         kfree(inst);
 459 
 460         return ret;
 461 }
 462 
 463 const struct venc_common_if venc_vp8_if = {
 464         .init = vp8_enc_init,
 465         .encode = vp8_enc_encode,
 466         .set_param = vp8_enc_set_param,
 467         .deinit = vp8_enc_deinit,
 468 };