static int vpu_enc_send_msg(struct venc_vpu_inst *vpu, void *msg, int len) { int status; mtk_vcodec_debug_enter(vpu); if (!vpu->dev) { mtk_vcodec_err(vpu, "inst dev is NULL"); return -EINVAL; } status = vpu_ipi_send(vpu->dev, vpu->id, msg, len); if (status) { mtk_vcodec_err(vpu, "vpu_ipi_send msg_id %x len %d fail %d", *(uint32_t *)msg, len, status); return -EINVAL; } if (vpu->failure) return -EINVAL; mtk_vcodec_debug_leave(vpu); return 0; }
int vpu_enc_init(struct venc_vpu_inst *vpu) { int status; struct venc_ap_ipi_msg_init out; mtk_vcodec_debug_enter(vpu); init_waitqueue_head(&vpu->wq_hd); vpu->signaled = 0; vpu->failure = 0; status = vpu_ipi_register(vpu->dev, vpu->id, vpu_enc_ipi_handler, NULL, NULL); if (status) { mtk_vcodec_err(vpu, "vpu_ipi_register fail %d", status); return -EINVAL; } memset(&out, 0, sizeof(out)); out.msg_id = AP_IPIMSG_ENC_INIT; out.venc_inst = (unsigned long)vpu; if (vpu_enc_send_msg(vpu, &out, sizeof(out))) { mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_INIT fail"); return -EINVAL; } mtk_vcodec_debug_leave(vpu); return 0; }
static int h264_encode_pps(struct venc_h264_inst *inst, struct mtk_vcodec_mem *bs_buf, unsigned int *bs_size) { int ret = 0; unsigned int irq_status; mtk_vcodec_debug_enter(inst); ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_PPS, NULL, bs_buf, bs_size); if (ret) return ret; irq_status = h264_enc_wait_venc_done(inst); if (irq_status != MTK_VENC_IRQ_STATUS_PPS) { mtk_vcodec_err(inst, "expect irq status %d", MTK_VENC_IRQ_STATUS_PPS); return -EINVAL; } *bs_size = h264_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT); mtk_vcodec_debug(inst, "bs size %d <-", *bs_size); return ret; }
static int h264_enc_init(struct mtk_vcodec_ctx *ctx, unsigned long *handle) { int ret = 0; struct venc_h264_inst *inst; inst = kzalloc(sizeof(*inst), GFP_KERNEL); if (!inst) return -ENOMEM; inst->ctx = ctx; inst->vpu_inst.ctx = ctx; inst->vpu_inst.dev = ctx->dev->vpu_plat_dev; inst->vpu_inst.id = IPI_VENC_H264; inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx, VENC_SYS); mtk_vcodec_debug_enter(inst); ret = vpu_enc_init(&inst->vpu_inst); inst->vsi = (struct venc_h264_vsi *)inst->vpu_inst.vsi; mtk_vcodec_debug_leave(inst); if (ret) kfree(inst); else (*handle) = (unsigned long)inst; return ret; }
static void free_predication_buf(struct vdec_h264_inst *inst) { struct mtk_vcodec_mem *mem = NULL; mtk_vcodec_debug_enter(inst); inst->vsi->pred_buf_dma = 0; mem = &inst->pred_buf; if (mem->va) mtk_vcodec_mem_free(inst->ctx, mem); }
static void vdec_h264_deinit(unsigned long h_vdec) { struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; mtk_vcodec_debug_enter(inst); vpu_dec_deinit(&inst->vpu); free_predication_buf(inst); free_mv_buf(inst); kfree(inst); }
static int h264_enc_deinit(unsigned long handle) { int ret = 0; struct venc_h264_inst *inst = (struct venc_h264_inst *)handle; mtk_vcodec_debug_enter(inst); ret = vpu_enc_deinit(&inst->vpu_inst); if (inst->work_buf_allocated) h264_enc_free_work_buf(inst); mtk_vcodec_debug_leave(inst); kfree(inst); return ret; }
int vpu_enc_deinit(struct venc_vpu_inst *vpu) { struct venc_ap_ipi_msg_deinit out; mtk_vcodec_debug_enter(vpu); memset(&out, 0, sizeof(out)); out.msg_id = AP_IPIMSG_ENC_DEINIT; out.vpu_inst_addr = vpu->inst_addr; if (vpu_enc_send_msg(vpu, &out, sizeof(out))) { mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_DEINIT fail"); return -EINVAL; } mtk_vcodec_debug_leave(vpu); return 0; }
static void h264_enc_free_work_buf(struct venc_h264_inst *inst) { int i; mtk_vcodec_debug_enter(inst); /* Except the SKIP_FRAME buffers, * other buffers need to be freed by AP. */ for (i = 0; i < VENC_H264_VPU_WORK_BUF_MAX; i++) { if (i != VENC_H264_VPU_WORK_BUF_SKIP_FRAME) mtk_vcodec_mem_free(inst->ctx, &inst->work_bufs[i]); } mtk_vcodec_mem_free(inst->ctx, &inst->pps_buf); mtk_vcodec_debug_leave(inst); }
static int h264_encode_frame(struct venc_h264_inst *inst, struct venc_frm_buf *frm_buf, struct mtk_vcodec_mem *bs_buf, unsigned int *bs_size) { int ret = 0; unsigned int irq_status; mtk_vcodec_debug_enter(inst); ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_FRAME, frm_buf, bs_buf, bs_size); if (ret) return ret; /* * skip frame case: The skip frame buffer is composed by vpu side only, * it does not trigger the hw, so skip the wait interrupt operation. */ if (inst->vpu_inst.state == VEN_IPI_MSG_ENC_STATE_SKIP) { *bs_size = inst->vpu_inst.bs_size; memcpy(bs_buf->va, inst->work_bufs[VENC_H264_VPU_WORK_BUF_SKIP_FRAME].va, *bs_size); ++inst->frm_cnt; return ret; } irq_status = h264_enc_wait_venc_done(inst); if (irq_status != MTK_VENC_IRQ_STATUS_FRM) { mtk_vcodec_err(inst, "irq_status=%d failed", irq_status); return -EIO; } *bs_size = h264_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT); ++inst->frm_cnt; mtk_vcodec_debug(inst, "frm %d bs_size %d key_frm %d <-", inst->frm_cnt, *bs_size, inst->vpu_inst.is_key_frm); return ret; }
static int h264_enc_alloc_work_buf(struct venc_h264_inst *inst) { int i; int ret = 0; struct venc_h264_vpu_buf *wb = inst->vsi->work_bufs; mtk_vcodec_debug_enter(inst); for (i = 0; i < VENC_H264_VPU_WORK_BUF_MAX; i++) { /* * This 'wb' structure is set by VPU side and shared to AP for * buffer allocation and IO virtual addr mapping. For most of * the buffers, AP will allocate the buffer according to 'size' * field and store the IO virtual addr in 'iova' field. There * are two exceptions: * (1) RC_CODE buffer, it's pre-allocated in the VPU side, and * save the VPU addr in the 'vpua' field. The AP will translate * the VPU addr to the corresponding IO virtual addr and store * in 'iova' field for reg setting in VPU side. * (2) SKIP_FRAME buffer, it's pre-allocated in the VPU side, * and save the VPU addr in the 'vpua' field. The AP will * translate the VPU addr to the corresponding AP side virtual * address and do some memcpy access to move to bitstream buffer * assigned by v4l2 layer. */ inst->work_bufs[i].size = wb[i].size; if (i == VENC_H264_VPU_WORK_BUF_SKIP_FRAME) { inst->work_bufs[i].va = vpu_mapping_dm_addr( inst->vpu_inst.dev, wb[i].vpua); inst->work_bufs[i].dma_addr = 0; } else { ret = mtk_vcodec_mem_alloc(inst->ctx, &inst->work_bufs[i]); if (ret) { mtk_vcodec_err(inst, "cannot allocate buf %d", i); goto err_alloc; } /* * This RC_CODE is pre-allocated by VPU and saved in VPU * addr. So we need use memcpy to copy RC_CODE from VPU * addr into IO virtual addr in 'iova' field for reg * setting in VPU side. */ if (i == VENC_H264_VPU_WORK_BUF_RC_CODE) { void *tmp_va; tmp_va = vpu_mapping_dm_addr(inst->vpu_inst.dev, wb[i].vpua); memcpy(inst->work_bufs[i].va, tmp_va, wb[i].size); } } wb[i].iova = inst->work_bufs[i].dma_addr; mtk_vcodec_debug(inst, "work_buf[%d] va=0x%p iova=%pad size=%zu", i, inst->work_bufs[i].va, &inst->work_bufs[i].dma_addr, inst->work_bufs[i].size); } /* the pps_buf is used by AP side only */ inst->pps_buf.size = 128; ret = mtk_vcodec_mem_alloc(inst->ctx, &inst->pps_buf); if (ret) { mtk_vcodec_err(inst, "cannot allocate pps_buf"); goto err_alloc; } mtk_vcodec_debug_leave(inst); return ret; err_alloc: h264_enc_free_work_buf(inst); return ret; }