diff --git a/drivers/mxc/vpu_malone/vpu_b0.c b/drivers/mxc/vpu_malone/vpu_b0.c index 2a4606d0f934c764884534d5b00a00db387eab7f..a811011cc20c878f1fbe3c779e85c689c658f78a 100644 --- a/drivers/mxc/vpu_malone/vpu_b0.c +++ b/drivers/mxc/vpu_malone/vpu_b0.c @@ -908,26 +908,28 @@ static int free_dma_buffer(struct vpu_ctx *ctx, struct dma_buffer *buffer) init_dma_buffer(buffer); return 0; } -static int alloc_mbi_buffer(struct vpu_ctx *ctx, - struct queue_data *This, - u_int32 count) + +static u_int32 get_mbi_size(struct queue_data *queue) { - u_int32 uAlign = 0x800-1; - u_int32 mbi_num; + u_int32 uAlign = 0x800; u_int32 mbi_size; + + mbi_size = (queue->sizeimage[0] + queue->sizeimage[1])/4; + return ALIGN(mbi_size, uAlign); +} + +static int alloc_mbi_buffer(struct vpu_ctx *ctx) +{ u_int32 ret = 0; u_int32 i; - if (count >= MAX_MBI_NUM) - mbi_num = MAX_MBI_NUM; - else - mbi_num = count; - ctx->mbi_num = mbi_num; + for (i = 0; i < ctx->mbi_num; i++) { + if (ctx->mbi_buffer[i].dma_size >= ctx->mbi_size) + continue; - mbi_size = (This->sizeimage[0]+This->sizeimage[1])/4; - mbi_size = ((mbi_size + uAlign) & ~uAlign); - for (i = 0; i < mbi_num; i++) { - ctx->mbi_buffer[i].dma_size = mbi_size; + free_dma_buffer(ctx, &ctx->mbi_buffer[i]); + init_dma_buffer(&ctx->mbi_buffer[i]); + ctx->mbi_buffer[i].dma_size = ctx->mbi_size; ret = alloc_dma_buffer(ctx, &ctx->mbi_buffer[i]); if (ret) { vpu_dbg(LVL_ERR, "error: alloc mbi buffer fail\n"); @@ -938,6 +940,57 @@ static int alloc_mbi_buffer(struct vpu_ctx *ctx, return ret; } +static int alloc_dcp_buffer(struct vpu_ctx *ctx) +{ + u_int32 i; + int ret = 0; + + for (i = 0; i < ARRAY_SIZE(ctx->dcp_buffer); i++) { + if (ctx->dcp_buffer[i].dma_size >= DCP_SIZE) + continue; + + free_dma_buffer(ctx, &ctx->dcp_buffer[i]); + init_dma_buffer(&ctx->dcp_buffer[i]); + ctx->dcp_buffer[i].dma_size = DCP_SIZE; + ret = alloc_dma_buffer(ctx, &ctx->dcp_buffer[i]); + if (ret) { + vpu_dbg(LVL_ERR, "error: alloc dcp buffer fail\n"); + return ret; + } + } + + return ret; +} + +static int alloc_decoder_buffer(struct vpu_ctx *ctx) +{ + int ret; + + ret = alloc_mbi_buffer(ctx); + if (ret) + return ret; + + ret = alloc_dcp_buffer(ctx); + if (ret) + return ret; + + return 0; +} + +static int free_decoeder_buffer(struct vpu_ctx *ctx) +{ + u_int32 i; + + for (i = 0; i < ARRAY_SIZE(ctx->mbi_buffer); i++) + free_dma_buffer(ctx, &ctx->mbi_buffer[i]); + for (i = 0; i < ARRAY_SIZE(ctx->dcp_buffer); i++) + free_dma_buffer(ctx, &ctx->dcp_buffer[i]); + free_dma_buffer(ctx, &ctx->stream_buffer); + free_dma_buffer(ctx, &ctx->udata_buffer); + + return 0; +} + void clear_vb2_buf(struct queue_data *q_data) { struct vb2_data_req *p_data_req; @@ -961,7 +1014,6 @@ static int v4l2_ioctl_reqbufs(struct file *file, { struct vpu_ctx *ctx = v4l2_fh_to_ctx(fh); struct queue_data *q_data; - u_int32 i; int ret; vpu_dbg(LVL_INFO, "%s()\n", __func__); @@ -980,23 +1032,15 @@ static int v4l2_ioctl_reqbufs(struct file *file, ctx->buffer_null = false; ret = vpu_dec_queue_reqbufs(q_data, reqbuf); - if (!ret) { - if (reqbuf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - - if (reqbuf->count == 0) { - for (i = 0; i < MAX_MBI_NUM; i++) { - free_dma_buffer(ctx, &ctx->mbi_buffer[i]); - init_dma_buffer(&ctx->mbi_buffer[i]); - } - } else { - for (i = 0; i < reqbuf->count; i++) - q_data->vb2_reqs[i].status = FRAME_ALLOC; - ret = alloc_mbi_buffer(ctx, q_data, reqbuf->count); - } - } - } else if (reqbuf->count != 0) - vpu_dbg(LVL_ERR, "error: %s() can't request (%d) buffer ret=%d\n", + if (ret) { + vpu_dbg(LVL_ERR, "error: %s() can't request (%d) buffer : %d\n", __func__, reqbuf->count, ret); + return ret; + } + if (!V4L2_TYPE_IS_OUTPUT(reqbuf->type) && reqbuf->count > 0) { + ctx->mbi_size = get_mbi_size(q_data); + ctx->mbi_num = min_t(u32, reqbuf->count, MAX_MBI_NUM); + } return ret; } @@ -2299,15 +2343,17 @@ static void vpu_api_event_handler(struct vpu_ctx *ctx, u_int32 uStrIdx, u_int32 struct vb2_data_req; bool buffer_flag = false; + if (alloc_decoder_buffer(ctx)) { + vpu_dbg(LVL_ERR, "alloc decoder buffer fail\n"); + break; + } + vpu_dbg(LVL_INFO, "VID_API_EVENT_REQ_FRAME_BUFF, type=%d, size=%ld\n", pFSREQ->eType, sizeof(MEDIA_PLAYER_FSREQ)); if (pFSREQ->eType == MEDIAIP_DCP_REQ) { if (ctx->dcp_count >= MAX_DCP_NUM) { vpu_dbg(LVL_ERR, "error: request dcp buffers number is over MAX_DCP_NUM\n"); break; } - ctx->dcp_buffer[ctx->dcp_count].dma_size = DCP_SIZE; - alloc_dma_buffer(ctx, &ctx->dcp_buffer[ctx->dcp_count]); - local_cmddata[0] = ctx->dcp_count; local_cmddata[1] = ctx->dcp_buffer[ctx->dcp_count].dma_phy; local_cmddata[2] = DCP_SIZE; @@ -3388,6 +3434,7 @@ static int init_vpu_buffer(struct vpu_ctx *ctx) init_dma_buffer(&ctx->mbi_buffer[i]); ctx->mbi_count = 0; ctx->mbi_num = 0; + ctx->mbi_size = 0; init_dma_buffer(&ctx->stream_buffer); init_dma_buffer(&ctx->udata_buffer); @@ -3596,7 +3643,6 @@ static int v4l2_release(struct file *filp) struct video_device *vdev = video_devdata(filp); struct vpu_dev *dev = video_get_drvdata(vdev); struct vpu_ctx *ctx = v4l2_fh_to_ctx(filp->private_data); - u_int32 i; vpu_dbg(LVL_EVENT, "ctx[%d]: v4l2_release() - stopped(%d), finished(%d), eos_added(%d), total frame: %d\n", ctx->str_index, ctx->firmware_stopped, ctx->firmware_finished, ctx->eos_stop_added, ctx->frm_total_num); @@ -3612,20 +3658,20 @@ static int v4l2_release(struct file *filp) } } else vpu_dbg(LVL_INFO, "v4l2_release() - stopped(%d): skip VID_API_CMD_STOP\n", ctx->firmware_stopped); + + mutex_lock(&ctx->instance_mutex); + ctx->ctx_released = true; + kfifo_free(&ctx->msg_fifo); + destroy_workqueue(ctx->instance_wq); + mutex_unlock(&ctx->instance_mutex); + if (vpu_frmcrcdump_ena) close_crc_file(ctx); release_queue_data(ctx); ctrls_delete_decoder(ctx); v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); - for (i = 0; i < MAX_DCP_NUM; i++) - free_dma_buffer(ctx, &ctx->dcp_buffer[i]); - - for (i = 0; i < MAX_MBI_NUM; i++) - free_dma_buffer(ctx, &ctx->mbi_buffer[i]); - - free_dma_buffer(ctx, &ctx->stream_buffer); - free_dma_buffer(ctx, &ctx->udata_buffer); + free_decoeder_buffer(ctx); if (atomic64_read(&ctx->statistic.total_dma_size) != 0) vpu_dbg(LVL_ERR, "error: memory leak for vpu dma alloc buffer\n"); if (ctx->pSeqinfo) { @@ -3633,11 +3679,6 @@ static int v4l2_release(struct file *filp) ctx->pSeqinfo = NULL; atomic64_sub(sizeof(MediaIPFW_Video_SeqInfo), &ctx->statistic.total_alloc_size); } - mutex_lock(&ctx->instance_mutex); - ctx->ctx_released = true; - kfifo_free(&ctx->msg_fifo); - destroy_workqueue(ctx->instance_wq); - mutex_unlock(&ctx->instance_mutex); pm_runtime_put_sync(ctx->dev->generic_dev); diff --git a/drivers/mxc/vpu_malone/vpu_b0.h b/drivers/mxc/vpu_malone/vpu_b0.h index 8a805e347164a349daf2c6f17bc02803023ee012..222a5584c3173b9dea1cab15af02efa9175ca08b 100644 --- a/drivers/mxc/vpu_malone/vpu_b0.h +++ b/drivers/mxc/vpu_malone/vpu_b0.h @@ -293,6 +293,7 @@ struct vpu_ctx { wait_queue_head_t buffer_wq; u_int32 mbi_count; u_int32 mbi_num; + u_int32 mbi_size; u_int32 dcp_count; struct dma_buffer dpb_buffer; struct dma_buffer dcp_buffer[MAX_DCP_NUM];