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_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 vpu_enc_ipi_handler(void *data, unsigned int len, void *priv) { struct venc_vpu_ipi_msg_common *msg = data; struct venc_vpu_inst *vpu = (struct venc_vpu_inst *)(unsigned long)msg->venc_inst; mtk_vcodec_debug(vpu, "msg_id %x inst %p status %d", msg->msg_id, vpu, msg->status); switch (msg->msg_id) { case VPU_IPIMSG_ENC_INIT_DONE: handle_enc_init_msg(vpu, data); break; case VPU_IPIMSG_ENC_SET_PARAM_DONE: break; case VPU_IPIMSG_ENC_ENCODE_DONE: handle_enc_encode_msg(vpu, data); break; case VPU_IPIMSG_ENC_DEINIT_DONE: break; default: mtk_vcodec_err(vpu, "unknown msg id %x", msg->msg_id); break; } vpu->signaled = 1; vpu->failure = (msg->status != VENC_IPI_MSG_STATUS_OK); mtk_vcodec_debug_leave(vpu); }
static int h264_enc_set_param(unsigned long handle, enum venc_set_param_type type, struct venc_enc_param *enc_prm) { int ret = 0; struct venc_h264_inst *inst = (struct venc_h264_inst *)handle; mtk_vcodec_debug(inst, "->type=%d", type); switch (type) { case VENC_SET_PARAM_ENC: inst->vsi->config.input_fourcc = enc_prm->input_yuv_fmt; inst->vsi->config.bitrate = enc_prm->bitrate; inst->vsi->config.pic_w = enc_prm->width; inst->vsi->config.pic_h = enc_prm->height; inst->vsi->config.buf_w = enc_prm->buf_width; inst->vsi->config.buf_h = enc_prm->buf_height; inst->vsi->config.gop_size = enc_prm->gop_size; inst->vsi->config.framerate = enc_prm->frm_rate; inst->vsi->config.intra_period = enc_prm->intra_period; inst->vsi->config.profile = h264_get_profile(inst, enc_prm->h264_profile); inst->vsi->config.level = h264_get_level(inst, enc_prm->h264_level); inst->vsi->config.wfd = 0; ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm); if (ret) break; if (inst->work_buf_allocated) { h264_enc_free_work_buf(inst); inst->work_buf_allocated = false; } ret = h264_enc_alloc_work_buf(inst); if (ret) break; inst->work_buf_allocated = true; break; case VENC_SET_PARAM_PREPEND_HEADER: inst->prepend_hdr = 1; mtk_vcodec_debug(inst, "set prepend header mode"); break; default: ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm); break; } mtk_vcodec_debug_leave(inst); return ret; }
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_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; }