v4l2: refine dmabuf recycle on output port [1/1]
authorSong Zhao <song.zhao@amlogic.com>
Wed, 9 Sep 2020 06:56:44 +0000 (23:56 -0700)
committerHui Zhang <hui.zhang@amlogic.com>
Sat, 12 Sep 2020 12:56:23 +0000 (05:56 -0700)
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 <song.zhao@amlogic.com>
15 files changed:
drivers/amvdec_ports/aml_vcodec_adapt.c
drivers/amvdec_ports/aml_vcodec_adapt.h
drivers/amvdec_ports/aml_vcodec_dec.c
drivers/amvdec_ports/aml_vcodec_drv.h
drivers/amvdec_ports/decoder/vdec_av1_if.c
drivers/amvdec_ports/decoder/vdec_h264_if.c
drivers/amvdec_ports/decoder/vdec_hevc_if.c
drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
drivers/amvdec_ports/decoder/vdec_vp9_if.c
drivers/frame_provider/decoder/utils/vdec.c
drivers/frame_provider/decoder/utils/vdec.h
drivers/frame_provider/decoder/utils/vdec_input.c
drivers/frame_provider/decoder/utils/vdec_input.h

index 94f1f0e74cb2715f65044a2b021eca63cf79ca09..521526ceae7c177d1e24ba13a615d0addcde2463 100644 (file)
@@ -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);
-}
-
index d09f5f0245d8e3fa37e0841f2ac4a71facd72744..b86cbffa275fbfcb35a1d6ae341ee806b350b517 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/amlogic/media/utils/vformat.h>
 #include <linux/amlogic/media/utils/amstream.h>
 #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 */
 
index afe328250823a156a14ff616d1bb6420b89fb1fa..55166910c18e15897e3a83d189729834ef43e38e 100644 (file)
@@ -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);
 
index a828b421340dd013e208132ccfb5e88e88b8dfb8..f3ee0c5da958ec754d22f00d13e6e801d0fa5786 100644 (file)
@@ -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;
index ca5e6aeb087407f784fccd623e239a86b43c6c44..0a79789169a1622c36430403437cec76130e2ee0 100644 (file)
@@ -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.*/
index aaef30322f1fd944aac54f78225ccd6a92a03bdf..8ac9a1ec07dc6f3c827285663e65d7ae12ab373e 100644 (file)
@@ -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) {
index 12c4ccff57c50bb8333f7ea43b69f3699c8b2126..9ad24d3b520711db6b6cfcda5ab7a35865f2e29a 100644 (file)
@@ -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) {
index 949f0256c589ab8a4be1c0aadba8b51ba36a1497..f200a342ab57217872e1135004b855f2ec6a91f6 100644 (file)
@@ -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);
index 7401be420b2313ccc43811fb89aef4d08c28205b..613e2825278809ad044b1ef6a1b7812b2707d9ed 100644 (file)
@@ -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);
index b0f9d6c1fa64e2eafad66c278be020365cc8b911..ea7fbc90b16d9f23644d2f0983376b9e5ccd41c2 100644 (file)
@@ -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);
index 12d572d361de034cf8441725096f0cd2364cb1fb..30c5b3b82e08a149be90fa36483994a3fcc6251e 100644 (file)
@@ -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.*/
index 092e63d25334357ae176c7efdabcba2f92ef725a..fed3c02cfd47cde468fa01e41c142e997d87678f 100644 (file)
@@ -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);
 
index c80005123fc2cf9afb0e294c5820141d416534ce..0a98c746213093abe1aad3d1c1c8834a71a6a25f 100644 (file)
@@ -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,
index 284dc0237ab976d00b8de9f7284365f25e3c85bd..481edd7eab888ec81dc21548a6fc3e3940733c09 100644 (file)
@@ -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);
index 1ca9ebe05f6f81309f020972b8df6f656015edf2..3a6180b83771ebcefbcd910988d746f8e6437441 100644 (file)
@@ -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(