From: Song Zhao Date: Wed, 9 Sep 2020 06:56:44 +0000 (-0700) Subject: v4l2: refine dmabuf recycle on output port [1/1] X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=d04e649b53377aa4116d759e10abda82446c92af;p=GitHub%2FLineageOS%2FG12%2Fandroid_hardware_amlogic_kernel-modules_media.git v4l2: refine dmabuf recycle on output port [1/1] PD#SWPL-32040 Problem: When output port is working at DMABUF mode, at resolution change point, there is a chance recycle_dmabuf can not be triggered at right timing. As a result, all the freed buffers are still in vdec input, but applicaiton can not dqueue any from M2M. Solution: Add callback in vdec intput, so when a chunk is released the callback is triggered to return the buffer to M2M. Verify: U212 + DSTV Change-Id: I64d6f0b2d1d7000323e6e2f674ae328846cb89a7 Signed-off-by: Song Zhao --- diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.c b/drivers/amvdec_ports/aml_vcodec_adapt.c index 94f1f0e..521526c 100644 --- a/drivers/amvdec_ports/aml_vcodec_adapt.c +++ b/drivers/amvdec_ports/aml_vcodec_adapt.c @@ -55,6 +55,7 @@ //#define DATA_DEBUG +extern void aml_recycle_dma_buffers(struct aml_vcodec_ctx *ctx, u32 handle); static int def_4k_vstreambuf_sizeM = (DEFAULT_VIDEO_BUFFER_SIZE_4K >> 20); static int def_vstreambuf_sizeM = @@ -688,8 +689,16 @@ int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, return ret; } +void vdec_vframe_input_free(void *priv, u32 handle) +{ + struct aml_vcodec_ctx *ctx = priv; + + aml_recycle_dma_buffers(ctx, handle); +} + int vdec_vframe_write_with_dma(struct aml_vdec_adapt *ada_ctx, - ulong addr, u32 count, u64 timestamp, u32 handle) + ulong addr, u32 count, u64 timestamp, u32 handle, + chunk_free free, void* priv) { int ret = -1; struct vdec_s *vdec = ada_ctx->vdec; @@ -697,7 +706,8 @@ int vdec_vframe_write_with_dma(struct aml_vdec_adapt *ada_ctx, /* set timestamp */ vdec_set_timestamp(vdec, timestamp); - ret = vdec_write_vframe_with_dma(vdec, addr, count, handle); + ret = vdec_write_vframe_with_dma(vdec, addr, count, + handle, free, priv); if (slow_input) { v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO, @@ -784,9 +794,3 @@ void v4l2_config_vdec_parm(struct aml_vdec_adapt *ada_ctx, u8 *data, u32 len) vdec->config_len = len > PAGE_SIZE ? PAGE_SIZE : len; memcpy(vdec->config, data, vdec->config_len); } - -u32 aml_recycle_buffer(struct aml_vdec_adapt *adaptor) -{ - return vdec_input_get_freed_handle(adaptor->vdec); -} - diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.h b/drivers/amvdec_ports/aml_vcodec_adapt.h index d09f5f0..b86cbff 100644 --- a/drivers/amvdec_ports/aml_vcodec_adapt.h +++ b/drivers/amvdec_ports/aml_vcodec_adapt.h @@ -23,6 +23,7 @@ #include #include #include "../stream_input/amports/streambuf.h" +#include "../frame_provider/decoder/utils/vdec_input.h" #include "aml_vcodec_drv.h" struct aml_vdec_adapt { @@ -54,8 +55,11 @@ int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, const char *buf, unsigned int count, u64 timestamp); +void vdec_vframe_input_free(void *priv, u32 handle); + int vdec_vframe_write_with_dma(struct aml_vdec_adapt *ada_ctx, - ulong addr, u32 count, u64 timestamp, u32 handle); + ulong addr, u32 count, u64 timestamp, u32 handle, + chunk_free free, void *priv); bool vdec_input_full(struct aml_vdec_adapt *ada_ctx); @@ -69,7 +73,5 @@ bool is_input_ready(struct aml_vdec_adapt *ada_ctx); int vdec_frame_number(struct aml_vdec_adapt *ada_ctx); -u32 aml_recycle_buffer(struct aml_vdec_adapt *adaptor); - #endif /* VDEC_ADAPT_H */ diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c index afe3282..5516691 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec.c +++ b/drivers/amvdec_ports/aml_vcodec_dec.c @@ -194,7 +194,6 @@ extern bool dump_capture_frame; extern int dmabuf_fd_install_data(int fd, void* data, u32 size); extern bool is_v4l2_buf_file(struct file *file); -static void aml_recycle_dma_buffers(struct aml_vcodec_ctx *ctx); static ulong aml_vcodec_ctx_lock(struct aml_vcodec_ctx *ctx) { @@ -538,9 +537,6 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f dstbuf = container_of(fb, struct aml_video_dec_buf, frame_buffer); vb2_buf = &dstbuf->vb.vb2_buf; - if (ctx->is_drm_mode && vb2_buf->memory == VB2_MEMORY_DMABUF) - aml_recycle_dma_buffers(ctx); - if (dstbuf->frame_buffer.num_planes == 1) { vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, fb->m.mem[0].bytes_used); } else if (dstbuf->frame_buffer.num_planes == 2) { @@ -740,28 +736,29 @@ static void aml_wait_dpb_ready(struct aml_vcodec_ctx *ctx) } } -static void aml_recycle_dma_buffers(struct aml_vcodec_ctx *ctx) +void aml_recycle_dma_buffers(struct aml_vcodec_ctx *ctx, u32 handle) { struct vb2_v4l2_buffer *vb; struct aml_video_dec_buf *buf; struct vb2_queue *q; - u32 handle; + int index = handle & 0xf; + if (ctx->is_out_stream_off) { + v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT, + "ignore buff idx: %d streamoff\n", index); + return; + } q = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); - while ((handle = aml_recycle_buffer(ctx->ada_ctx))) { - int index = handle & 0xf; + vb = to_vb2_v4l2_buffer(q->bufs[index]); + buf = container_of(vb, struct aml_video_dec_buf, vb); + v4l2_m2m_buf_done(vb, buf->error ? VB2_BUF_STATE_ERROR : + VB2_BUF_STATE_DONE); - vb = to_vb2_v4l2_buffer(q->bufs[index]); - buf = container_of(vb, struct aml_video_dec_buf, vb); - v4l2_m2m_buf_done(vb, buf->error ? VB2_BUF_STATE_ERROR : - VB2_BUF_STATE_DONE); - - v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT, - "recycle buff idx: %d, vbuf: %lx\n", index, - (ulong)vb2_dma_contig_plane_dma_addr(q->bufs[index], 0)); - } + v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT, + "recycle buff idx: %d, vbuf: %lx\n", index, + (ulong)vb2_dma_contig_plane_dma_addr(q->bufs[index], 0)); } static void aml_vdec_worker(struct work_struct *work) @@ -865,18 +862,13 @@ static void aml_vdec_worker(struct work_struct *work) * when decode success without resolution change. */ v4l2_m2m_src_buf_remove(ctx->m2m_ctx); - - if (ctx->is_drm_mode && buf.model == VB2_MEMORY_DMABUF) - aml_recycle_dma_buffers(ctx); - else + if (!(ctx->is_drm_mode && buf.model == VB2_MEMORY_DMABUF)) v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE); } else if (ret && ret != -EAGAIN) { src_buf_info->error = (ret == -EIO ? true : false); v4l2_m2m_src_buf_remove(ctx->m2m_ctx); - if (ctx->is_drm_mode && buf.model == VB2_MEMORY_DMABUF) - aml_recycle_dma_buffers(ctx); - else + if (!(ctx->is_drm_mode && buf.model == VB2_MEMORY_DMABUF)) v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR); v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, @@ -1206,7 +1198,8 @@ static int vidioc_decoder_streamon(struct file *file, void *priv, ctx->is_stream_off = false; } - } + } else + ctx->is_out_stream_off = false; v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s, type: %d\n", __func__, q->type); @@ -1222,9 +1215,10 @@ static int vidioc_decoder_streamoff(struct file *file, void *priv, struct vb2_queue *q; q = v4l2_m2m_get_vq(fh->m2m_ctx, i); - if (!V4L2_TYPE_IS_OUTPUT(q->type)) { + if (!V4L2_TYPE_IS_OUTPUT(q->type)) ctx->is_stream_off = true; - } + else + ctx->is_out_stream_off = true; v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s, type: %d\n", __func__, q->type); @@ -2130,9 +2124,7 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) if (vdec_if_probe(ctx, &src_mem, NULL)) { v4l2_m2m_src_buf_remove(ctx->m2m_ctx); - if (ctx->is_drm_mode && src_mem.model == VB2_MEMORY_DMABUF) - aml_recycle_dma_buffers(ctx); - else + if (!(ctx->is_drm_mode && src_mem.model == VB2_MEMORY_DMABUF)) v4l2_m2m_buf_done(to_vb2_v4l2_buffer(vb), VB2_BUF_STATE_DONE); return; } @@ -2143,7 +2135,6 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) */ if (ctx->is_drm_mode && src_mem.model == VB2_MEMORY_DMABUF) { v4l2_m2m_src_buf_remove(ctx->m2m_ctx); - aml_recycle_dma_buffers(ctx); } else if (ctx->param_sets_from_ucode) { v4l2_m2m_src_buf_remove(ctx->m2m_ctx); v4l2_m2m_buf_done(to_vb2_v4l2_buffer(vb), @@ -2349,9 +2340,6 @@ static void vb2ops_vdec_stop_streaming(struct vb2_queue *q) codec_mm_bufs_cnt_clean(q); if (V4L2_TYPE_IS_OUTPUT(q->type)) { - if (ctx->is_drm_mode && q->memory == VB2_MEMORY_DMABUF) - aml_recycle_dma_buffers(ctx); - while ((vb2_v4l2 = v4l2_m2m_src_buf_remove(ctx->m2m_ctx))) v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR); diff --git a/drivers/amvdec_ports/aml_vcodec_drv.h b/drivers/amvdec_ports/aml_vcodec_drv.h index a828b42..f3ee0c5 100644 --- a/drivers/amvdec_ports/aml_vcodec_drv.h +++ b/drivers/amvdec_ports/aml_vcodec_drv.h @@ -421,6 +421,7 @@ struct aml_vdec_thread { * @is_drm_mode: decoding work on drm mode if that set. * @is_stream_mode: vdec input used to stream mode, default frame mode. * @is_stream_off: the value used to handle reset active. + * @is_out_stream_off: streamoff called for output port. * @receive_cmd_stop: if receive the cmd flush decoder. * @reset_flag: reset mode includes lightly and normal mode. * @decoded_frame_cnt: the capture buffer deque number to be count. @@ -466,6 +467,7 @@ struct aml_vcodec_ctx { bool is_drm_mode; bool output_dma_mode; bool is_stream_off; + bool is_out_stream_off; bool receive_cmd_stop; int reset_flag; int decoded_frame_cnt; diff --git a/drivers/amvdec_ports/decoder/vdec_av1_if.c b/drivers/amvdec_ports/decoder/vdec_av1_if.c index ca5e6ae..0a79789 100644 --- a/drivers/amvdec_ports/decoder/vdec_av1_if.c +++ b/drivers/amvdec_ports/decoder/vdec_av1_if.c @@ -434,7 +434,8 @@ static int parse_stream_ucode_dma(struct vdec_av1_inst *inst, int ret = 0; struct aml_vdec_adapt *vdec = &inst->vdec; - ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle); + ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle, + vdec_vframe_input_free, inst->ctx); if (ret < 0) { v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, "write frame data failed. err: %d\n", ret); @@ -1118,7 +1119,8 @@ static int vdec_av1_decode(unsigned long h_vdec, bs->model == VB2_MEMORY_USERPTR) { ret = vdec_vframe_write_with_dma(vdec, bs->addr, size, bs->timestamp, - BUFF_IDX(bs, bs->index)); + BUFF_IDX(bs, bs->index), + vdec_vframe_input_free, inst->ctx); } } else { /*checked whether the resolution changes.*/ diff --git a/drivers/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amvdec_ports/decoder/vdec_h264_if.c index aaef303..8ac9a1e 100644 --- a/drivers/amvdec_ports/decoder/vdec_h264_if.c +++ b/drivers/amvdec_ports/decoder/vdec_h264_if.c @@ -587,7 +587,8 @@ static int parse_stream_ucode_dma(struct vdec_h264_inst *inst, int ret = 0; struct aml_vdec_adapt *vdec = &inst->vdec; - ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle); + ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle, + vdec_vframe_input_free, inst->ctx); if (ret < 0) { v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, "write frame data failed. err: %d\n", ret); @@ -906,7 +907,8 @@ static int vdec_h264_decode(unsigned long h_vdec, bs->model == VB2_MEMORY_USERPTR) { ret = vdec_vframe_write_with_dma(vdec, bs->addr, size, bs->timestamp, - BUFF_IDX(bs, bs->index)); + BUFF_IDX(bs, bs->index), + vdec_vframe_input_free, inst->ctx); } } else { if (inst->ctx->param_sets_from_ucode) { diff --git a/drivers/amvdec_ports/decoder/vdec_hevc_if.c b/drivers/amvdec_ports/decoder/vdec_hevc_if.c index 12c4ccf..9ad24d3 100644 --- a/drivers/amvdec_ports/decoder/vdec_hevc_if.c +++ b/drivers/amvdec_ports/decoder/vdec_hevc_if.c @@ -435,7 +435,8 @@ static int parse_stream_ucode_dma(struct vdec_hevc_inst *inst, int ret = 0; struct aml_vdec_adapt *vdec = &inst->vdec; - ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle); + ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle, + vdec_vframe_input_free, inst->ctx); if (ret < 0) { v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, "write frame data failed. err: %d\n", ret); @@ -670,7 +671,8 @@ static int vdec_hevc_decode(unsigned long h_vdec, bs->model == VB2_MEMORY_USERPTR) { ret = vdec_vframe_write_with_dma(vdec, bs->addr, size, bs->timestamp, - BUFF_IDX(bs, bs->index)); + BUFF_IDX(bs, bs->index), + vdec_vframe_input_free, inst->ctx); } } else { if (!inst->ctx->param_sets_from_ucode) { diff --git a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c index 949f025..f200a34 100644 --- a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c +++ b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c @@ -335,7 +335,8 @@ static int parse_stream_ucode_dma(struct vdec_mjpeg_inst *inst, int ret = 0; struct aml_vdec_adapt *vdec = &inst->vdec; - ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle); + ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle, + vdec_vframe_input_free, inst->ctx); if (ret < 0) { v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, "write frame data failed. err: %d\n", ret); @@ -520,7 +521,8 @@ static int vdec_mjpeg_decode(unsigned long h_vdec, bs->model == VB2_MEMORY_USERPTR) { ret = vdec_vframe_write_with_dma(vdec, bs->addr, size, bs->timestamp, - BUFF_IDX(bs, bs->index)); + BUFF_IDX(bs, bs->index), + vdec_vframe_input_free, inst->ctx); } } else { ret = vdec_write_nalu(inst, buf, size, bs->timestamp); diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c index 7401be4..613e282 100644 --- a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c +++ b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c @@ -322,7 +322,8 @@ static int parse_stream_ucode_dma(struct vdec_mpeg12_inst *inst, int ret = 0; struct aml_vdec_adapt *vdec = &inst->vdec; - ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle); + ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle, + vdec_vframe_input_free, inst->ctx); if (ret < 0) { v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, "write frame data failed. err: %d\n", ret); @@ -507,7 +508,8 @@ static int vdec_mpeg12_decode(unsigned long h_vdec, bs->model == VB2_MEMORY_USERPTR) { ret = vdec_vframe_write_with_dma(vdec, bs->addr, size, bs->timestamp, - BUFF_IDX(bs, bs->index)); + BUFF_IDX(bs, bs->index), + vdec_vframe_input_free, inst->ctx); } } else { ret = vdec_write_nalu(inst, buf, size, bs->timestamp); diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c index b0f9d6c..ea7fbc9 100644 --- a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c +++ b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c @@ -332,7 +332,8 @@ static int parse_stream_ucode_dma(struct vdec_mpeg4_inst *inst, int ret = 0; struct aml_vdec_adapt *vdec = &inst->vdec; - ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle); + ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle, + vdec_vframe_input_free, inst->ctx); if (ret < 0) { v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, "write frame data failed. err: %d\n", ret); @@ -517,7 +518,8 @@ static int vdec_mpeg4_decode(unsigned long h_vdec, bs->model == VB2_MEMORY_USERPTR) { ret = vdec_vframe_write_with_dma(vdec, bs->addr, size, bs->timestamp, - BUFF_IDX(bs, bs->index)); + BUFF_IDX(bs, bs->index), + vdec_vframe_input_free, inst->ctx); } } else { ret = vdec_write_nalu(inst, buf, size, bs->timestamp); diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_if.c b/drivers/amvdec_ports/decoder/vdec_vp9_if.c index 12d572d..30c5b3b 100644 --- a/drivers/amvdec_ports/decoder/vdec_vp9_if.c +++ b/drivers/amvdec_ports/decoder/vdec_vp9_if.c @@ -465,7 +465,8 @@ static int parse_stream_ucode_dma(struct vdec_vp9_inst *inst, int ret = 0; struct aml_vdec_adapt *vdec = &inst->vdec; - ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle); + ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle, + vdec_vframe_input_free, inst->ctx); if (ret < 0) { v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, "write frame data failed. err: %d\n", ret); @@ -877,7 +878,8 @@ static int vdec_vp9_decode(unsigned long h_vdec, bs->model == VB2_MEMORY_USERPTR) { ret = vdec_vframe_write_with_dma(vdec, bs->addr, size, bs->timestamp, - BUFF_IDX(bs, bs->index)); + BUFF_IDX(bs, bs->index), + vdec_vframe_input_free, inst->ctx); } } else { /*checked whether the resolution changes.*/ diff --git a/drivers/frame_provider/decoder/utils/vdec.c b/drivers/frame_provider/decoder/utils/vdec.c index 092e63d..fed3c02 100644 --- a/drivers/frame_provider/decoder/utils/vdec.c +++ b/drivers/frame_provider/decoder/utils/vdec.c @@ -1244,9 +1244,10 @@ int vdec_write_vframe(struct vdec_s *vdec, const char *buf, size_t count) EXPORT_SYMBOL(vdec_write_vframe); int vdec_write_vframe_with_dma(struct vdec_s *vdec, - ulong addr, size_t count, u32 handle) + ulong addr, size_t count, u32 handle, chunk_free free, void* priv) { - return vdec_input_add_frame_with_dma(&vdec->input, addr, count, handle); + return vdec_input_add_frame_with_dma(&vdec->input, + addr, count, handle, free, priv); } EXPORT_SYMBOL(vdec_write_vframe_with_dma); diff --git a/drivers/frame_provider/decoder/utils/vdec.h b/drivers/frame_provider/decoder/utils/vdec.h index c800051..0a98c74 100644 --- a/drivers/frame_provider/decoder/utils/vdec.h +++ b/drivers/frame_provider/decoder/utils/vdec.h @@ -327,7 +327,7 @@ extern int vdec_write_vframe(struct vdec_s *vdec, const char *buf, size_t count); extern int vdec_write_vframe_with_dma(struct vdec_s *vdec, - ulong addr, size_t count, u32 handle); + ulong addr, size_t count, u32 handle, chunk_free free, void* priv); /* mark the vframe_chunk as consumed */ extern void vdec_vframe_dirty(struct vdec_s *vdec, diff --git a/drivers/frame_provider/decoder/utils/vdec_input.c b/drivers/frame_provider/decoder/utils/vdec_input.c index 284dc02..481edd7 100644 --- a/drivers/frame_provider/decoder/utils/vdec_input.c +++ b/drivers/frame_provider/decoder/utils/vdec_input.c @@ -56,7 +56,9 @@ static struct vframe_block_list_s * vdec_input_alloc_new_block(struct vdec_input_s *input, ulong phy_addr, - int size); + int size, + chunk_free free, + void* priv); static int aml_copy_from_user(void *to, const void *from, ulong n) { @@ -235,7 +237,9 @@ static void vframe_block_free_block(struct vframe_block_list_s *block) static int vframe_block_init_alloc_storage(struct vdec_input_s *input, struct vframe_block_list_s *block, ulong phy_addr, - int size) + int size, + chunk_free free, + void *priv) { int alloc_size = input->default_block_size; block->magic = 0x4b434c42; @@ -250,6 +254,8 @@ static int vframe_block_init_alloc_storage(struct vdec_input_s *input, block->start_virt = NULL; block->start = phy_addr; block->size = size; + block->free = free; + block->priv = priv; } else { alloc_size = PAGE_ALIGN(alloc_size); block->addr = codec_mm_alloc_for_dma_ex( @@ -271,6 +277,7 @@ static int vframe_block_init_alloc_storage(struct vdec_input_s *input, block->start = block->addr; block->size = alloc_size; block->is_out_buf = 0; + block->free = NULL; } return 0; @@ -306,7 +313,7 @@ int vdec_input_prepare_bufs(struct vdec_input_s *input, } /*prepared 3 buffers for smooth start.*/ for (i = 0; i < 3; i++) { - block = vdec_input_alloc_new_block(input, 0, 0); + block = vdec_input_alloc_new_block(input, 0, 0, NULL, NULL); if (!block) break; flags = vdec_input_lock(input); @@ -605,7 +612,9 @@ EXPORT_SYMBOL(vdec_input_level); static struct vframe_block_list_s * vdec_input_alloc_new_block(struct vdec_input_s *input, ulong phy_addr, - int size) + int size, + chunk_free free, + void* priv) { struct vframe_block_list_s *block; block = kzalloc(sizeof(struct vframe_block_list_s), @@ -617,7 +626,7 @@ static struct vframe_block_list_s * } if (vframe_block_init_alloc_storage(input, - block, phy_addr, size) != 0) { + block, phy_addr, size, free, priv) != 0) { kfree(block); pr_err("vframe_block storage allocation failed\n"); return NULL; @@ -748,7 +757,7 @@ static int vdec_input_get_free_block( /*128k aligned,same as codec_mm*/ input->default_block_size = def_size; } - block = vdec_input_alloc_new_block(input, 0, 0); + block = vdec_input_alloc_new_block(input, 0, 0, NULL, NULL); if (!block) { input->no_mem_err_cnt++; return -EAGAIN; @@ -759,7 +768,7 @@ static int vdec_input_get_free_block( } int vdec_input_add_chunk(struct vdec_input_s *input, const char *buf, - size_t count, u32 handle) + size_t count, u32 handle, chunk_free free, void* priv) { unsigned long flags; struct vframe_chunk_s *chunk; @@ -769,7 +778,8 @@ int vdec_input_add_chunk(struct vdec_input_s *input, const char *buf, if (vdec_secure(vdec)) { block = vdec_input_alloc_new_block(input, (ulong)buf, - PAGE_ALIGN(count + HEVC_PADDING_SIZE + 1)); /*Add padding large than HEVC_PADDING_SIZE */ + PAGE_ALIGN(count + HEVC_PADDING_SIZE + 1), + free, priv); /*Add padding large than HEVC_PADDING_SIZE */ if (!block) return -ENOMEM; block->handle = handle; @@ -954,7 +964,7 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, return -EIO; /*must drm info v2 version*/ phy_buf = (unsigned long) drm.drm_phy; vdec_input_add_chunk(input, (char *)phy_buf, - (size_t)drm.drm_pktsize, drm.handle); + (size_t)drm.drm_pktsize, drm.handle, NULL, NULL); count -= sizeof(struct drm_info); ret += sizeof(struct drm_info); @@ -964,7 +974,7 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, vdec->pts_valid = true; } } else { - ret = vdec_input_add_chunk(input, buf, count, 0); + ret = vdec_input_add_chunk(input, buf, count, 0, NULL, NULL); } return ret; @@ -972,12 +982,13 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, EXPORT_SYMBOL(vdec_input_add_frame); int vdec_input_add_frame_with_dma(struct vdec_input_s *input, ulong addr, - size_t count, u32 handle) + size_t count, u32 handle, chunk_free free, void* priv) { struct vdec_s *vdec = input->vdec; return vdec_secure(vdec) ? - vdec_input_add_chunk(input, (char *)addr, count, handle) : -1; + vdec_input_add_chunk(input, + (char *)addr, count, handle, free, priv) : -1; } EXPORT_SYMBOL(vdec_input_add_frame_with_dma); @@ -1057,6 +1068,11 @@ void vdec_input_release_chunk(struct vdec_input_s *input, if (block->is_out_buf) { list_move_tail(&block->list, &input->vframe_block_free_list); + if (block->free) { + vdec_input_del_block_locked(input, block); + block->free(block->priv, block->handle); + } + kfree(block); } else if (block->chunk_count == 0 && input->wr_block != block ) {/*don't free used block*/ if (block->size < input->default_block_size) { @@ -1152,6 +1168,8 @@ u32 vdec_input_get_freed_handle(struct vdec_s *vdec) handle = block->handle; vdec_input_del_block_locked(input, block); + if (block->free) + block->free(block->priv, handle); kfree(block); } while(!handle); diff --git a/drivers/frame_provider/decoder/utils/vdec_input.h b/drivers/frame_provider/decoder/utils/vdec_input.h index 1ca9ebe..3a6180b 100644 --- a/drivers/frame_provider/decoder/utils/vdec_input.h +++ b/drivers/frame_provider/decoder/utils/vdec_input.h @@ -21,6 +21,8 @@ struct vdec_s; struct vdec_input_s; +typedef void (*chunk_free)(void *priv, u32 handle); + struct vframe_block_list_s { u32 magic; int id; @@ -37,6 +39,11 @@ struct vframe_block_list_s { int chunk_count; int is_out_buf; u32 handle; + + /* free callback */ + chunk_free free; + void* priv; + struct vdec_input_s *input; }; @@ -144,7 +151,7 @@ extern int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, size_t count); extern int vdec_input_add_frame_with_dma(struct vdec_input_s *input, ulong addr, - size_t count, u32 handle); + size_t count, u32 handle, chunk_free free, void* priv); /* Peek next frame data from decoder's input */ extern struct vframe_chunk_s *vdec_input_next_chunk(