MLK-21087-5:[i.MX8QXP/VPU]: Integrate timestamp manager into driver
authorming_qian <ming.qian@nxp.com>
Fri, 19 Apr 2019 05:31:52 +0000 (13:31 +0800)
committerming_qian <ming.qian@nxp.com>
Mon, 22 Apr 2019 07:50:14 +0000 (15:50 +0800)
For some format, scode is need to insert before or after frame data.
It may cause that the input frame length is not match with
the consumed frame length.

The scode can be calculated as part of input frame.

Signed-off-by: ming_qian <ming.qian@nxp.com>
drivers/mxc/vpu_malone/vpu_b0.c

index 12a5e07..09ff672 100644 (file)
@@ -1156,25 +1156,31 @@ static int v4l2_ioctl_querybuf(struct file *file,
 }
 
 static void vpu_dec_receive_ts(struct vpu_ctx *ctx,
-                               struct v4l2_buffer *buf,
+                               struct vb2_buffer *vb,
                                int size)
 {
+       struct vb2_v4l2_buffer *vbuf;
        TSM_TIMESTAMP input_ts;
 
-       if (buf->flags & V4L2_NXP_BUF_FLAG_TIMESTAMP_INVALID) {
+       if (!ctx || !vb)
+               return;
+
+       vbuf = to_vb2_v4l2_buffer(vb);
+       if (vbuf->flags & V4L2_NXP_BUF_FLAG_TIMESTAMP_INVALID) {
                vpu_dbg(LVL_BIT_TS, "[INPUT  TS]Invalid timestamp, drop it\n");
                return;
        }
 
-       input_ts = timeval_to_ns(&buf->timestamp);
+       input_ts = vb->timestamp;
        if (input_ts < 0)
                input_ts = TSM_TIMESTAMP_NONE;
-       vpu_dbg(LVL_BIT_TS, "[INPUT  TS]%32lld\n", input_ts);
 
        if (ctx->tsm_sync_flag) {
+               vpu_dbg(LVL_BIT_TS, "resyncTSManager\n");
                resyncTSManager(ctx->tsm, input_ts, tsm_mode);
                ctx->tsm_sync_flag = false;
        }
+       vpu_dbg(LVL_BIT_TS, "[INPUT  TS]%32lld\n", input_ts);
        TSManagerReceive2(ctx->tsm, input_ts, size);
        ctx->total_ts_bytes += size;
        vpu_dbg(LVL_BIT_FRAME_BYTES, "[%d]receive bytes : %8d / %16ld\n",
@@ -1201,7 +1207,6 @@ static int v4l2_ioctl_qbuf(struct file *file,
                                ctx->total_qbuf_bytes);
                q_data = &ctx->q_data[V4L2_SRC];
 
-               vpu_dec_receive_ts(ctx, buf, buf->m.planes[0].bytesused);
                v4l2_update_stream_addr(ctx, 0);
        } else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
                q_data = &ctx->q_data[V4L2_DST];
@@ -1781,7 +1786,7 @@ static int add_scode_vpu(struct vpu_ctx *ctx, u_int32 uStrBufIdx, VPU_PADDING_SC
        buffer = kzalloc(SCODE_SIZE, GFP_KERNEL); //for eos data
        if (!buffer) {
                vpu_dbg(LVL_ERR, "error:  eos buffer alloc fail\n");
-               return -1;
+               return 0;
        }
        atomic64_add(SCODE_SIZE, &ctx->statistic.total_alloc_size);
        plbuffer = (uint32_t *)buffer;
@@ -1789,7 +1794,7 @@ static int add_scode_vpu(struct vpu_ctx *ctx, u_int32 uStrBufIdx, VPU_PADDING_SC
                pbbuffer = (uint8_t *)(ctx->stream_buffer.dma_virt + wptr - start);
        else {
                vpu_dbg(LVL_ERR, "error: return wptr(0x%x), start(0x%x) is not valid\n", wptr, start);
-               return -1;
+               goto error;
        }
 
        // Word align
@@ -1797,7 +1802,7 @@ static int add_scode_vpu(struct vpu_ctx *ctx, u_int32 uStrBufIdx, VPU_PADDING_SC
                int i;
                if (end%4 != 0) {
                        vpu_dbg(LVL_ERR, "end address of stream not aligned by 4 bytes !\n");
-                       return -1;
+                       goto error;
                }
                pad_bytes = 4 - (((u_int64)pbbuffer)%4);
                for (i = 0; i < pad_bytes; i++)
@@ -1877,7 +1882,7 @@ static int add_scode_vpu(struct vpu_ctx *ctx, u_int32 uStrBufIdx, VPU_PADDING_SC
                } else {
                        /* all other standards do not support the frame flush mechanism so just return */
                        vpu_dbg(LVL_WARN, "warning: format(%d) not support frame flush mechanism !\n", q_data->vdec_std);
-                       return 0;
+                       goto error;
                }
        }
        plbuffer[0] = last;
@@ -1919,6 +1924,10 @@ static int add_scode_vpu(struct vpu_ctx *ctx, u_int32 uStrBufIdx, VPU_PADDING_SC
        vpu_dbg(LVL_INFO, "%s() done type (%d) MCX address virt=%p, phy=0x%x, index=%d\n",
                        __func__, eScodeType, pStrBufDesc, dev->shared_mem.pSharedInterface->pStreamBuffDesc[ctx->str_index][uStrBufIdx], ctx->str_index);
        return pad_bytes;
+error:
+       kfree(buffer);
+       atomic64_sub(SCODE_SIZE, &ctx->statistic.total_alloc_size);
+       return 0;
 }
 
 static int add_scode(struct vpu_ctx *ctx, u_int32 uStrBufIdx, VPU_PADDING_SCODE_TYPE eScodeType, bool bUpdateWr)
@@ -1932,6 +1941,8 @@ static int add_scode(struct vpu_ctx *ctx, u_int32 uStrBufIdx, VPU_PADDING_SCODE_
        size = add_scode_vpu(ctx, uStrBufIdx, eScodeType, bUpdateWr);
        if (size > 0)
                set_pic_end_flag(ctx);
+       else
+               size = 0;
        mutex_unlock(&ctx->instance_mutex);
        return size;
 }
@@ -2011,7 +2022,10 @@ static void v4l2_vpu_send_cmd(struct vpu_ctx *ctx, uint32_t idx, uint32_t cmdid,
        MU_SendMessage(ctx->dev->mu_base_virtaddr, 0, COMMAND);
 }
 
-static void transfer_buffer_to_firmware(struct vpu_ctx *ctx, void *input_buffer, uint32_t buffer_size, uint32_t vdec_std)
+static u32 transfer_buffer_to_firmware(struct vpu_ctx *ctx,
+                                       void *input_buffer,
+                                       uint32_t buffer_size,
+                                       uint32_t vdec_std)
 {
        pSTREAM_BUFFER_DESCRIPTOR_TYPE pStrBufDesc;
        u_int32 uStrBufIdx = 0; //set to be default 0, FIX_ME later
@@ -2033,7 +2047,7 @@ static void transfer_buffer_to_firmware(struct vpu_ctx *ctx, void *input_buffer,
 
        if (ctx->stream_buffer.dma_size < buffer_size + MIN_SPACE) {
                vpu_dbg(LVL_ERR, "circular buffer size is set too small\n");
-               return;
+               return 0;
        }
        if (!ctx->start_code_bypass)
                length = insert_scode_4_seq(ctx, input_buffer, ctx->stream_buffer.dma_virt, vdec_std, buffer_size);
@@ -2074,7 +2088,7 @@ static void transfer_buffer_to_firmware(struct vpu_ctx *ctx, void *input_buffer,
        pCodecPara = (MediaIPFW_Video_CodecParams *)ctx->dev->shared_mem.codec_mem_vir;
        if (ctx->b_dis_reorder) {
                /* set the shared memory space control with this */
-               add_scode(ctx, 0, BUFFLUSH_PADDING_TYPE, true);
+               length += add_scode(ctx, 0, BUFFLUSH_PADDING_TYPE, true);
                record_log_info(ctx, LOG_PADDING, 0, 0);
                pCodecPara[ctx->str_index].uDispImm = 1;
        } else {
@@ -2089,6 +2103,8 @@ static void transfer_buffer_to_firmware(struct vpu_ctx *ctx, void *input_buffer,
        ctx->frm_dec_delay = 1;
        ctx->frm_total_num = 1;
        fill_stream_buffer_info(ctx);
+
+       return length;
 }
 
 static void v4l2_transfer_buffer_to_firmware(struct queue_data *This, struct vb2_buffer *vb)
@@ -2097,6 +2113,7 @@ static void v4l2_transfer_buffer_to_firmware(struct queue_data *This, struct vb2
        struct vb2_data_req *p_data_req;
        void *data_mapped;
        uint32_t buffer_size = vb->planes[0].bytesused;
+       u32 frame_bytes;
        int ret;
 
        data_mapped = (void *)vb2_plane_vaddr(vb, 0);
@@ -2107,7 +2124,10 @@ static void v4l2_transfer_buffer_to_firmware(struct queue_data *This, struct vb2
                        vpu_dbg(LVL_ERR, "alloc vpu buffer fail\n");
                        return;
                }
-               transfer_buffer_to_firmware(ctx, data_mapped, buffer_size, This->vdec_std);
+               frame_bytes = transfer_buffer_to_firmware(ctx,
+                                                         data_mapped,
+                                                         buffer_size,
+                                                         This->vdec_std);
 #ifdef HANDLE_EOS
                if (vb->planes[0].bytesused < vb->planes[0].length)
                        vpu_dbg(LVL_INFO, "v4l2_transfer_buffer_to_firmware - set stream_feed_complete - DEBUG 1\n");
@@ -2115,6 +2135,7 @@ static void v4l2_transfer_buffer_to_firmware(struct queue_data *This, struct vb2
                v4l2_vpu_send_cmd(ctx, ctx->str_index, VID_API_CMD_START, 0, NULL);
                p_data_req = list_first_entry(&This->drv_q,
                                typeof(*p_data_req), list);
+               vpu_dec_receive_ts(ctx, p_data_req->vb2_buf, frame_bytes);
                list_del(&p_data_req->list);
                p_data_req->queued = false;
                if (p_data_req->vb2_buf)
@@ -2150,7 +2171,6 @@ static int update_stream_addr(struct vpu_ctx *ctx, void *input_buffer, uint32_t
        uint32_t start;
        uint32_t end;
        void *wptr_virt;
-       uint32_t ret = 1;
        u_int32 length = 0;
 
        vpu_dbg(LVL_BIT_FUNC, "enter %s\n", __func__);
@@ -2245,8 +2265,9 @@ static int update_stream_addr(struct vpu_ctx *ctx, void *input_buffer, uint32_t
 
        vpu_dbg(LVL_BIT_FUNC, "update address virt=%p, phy=0x%x, index=%d\n",
                        pStrBufDesc, dev->shared_mem.pSharedInterface->pStreamBuffDesc[ctx->str_index][uStrBufIdx], ctx->str_index);
-       return ret;
+       return length + buffer_size;
 }
+
 static int update_stream_addr_vpu(struct vpu_ctx *ctx, void *input_buffer, uint32_t buffer_size, uint32_t uStrBufIdx)
 {
        int size = 0;
@@ -2311,6 +2332,7 @@ static void v4l2_update_stream_addr(struct vpu_ctx *ctx, uint32_t uStrBufIdx)
        struct queue_data *This = &ctx->q_data[V4L2_SRC];
        void *input_buffer;
        uint32_t buffer_size;
+       u32 frame_bytes;
 
        down(&This->drv_q_lock);
        while (!list_empty(&This->drv_q)) {
@@ -2325,7 +2347,11 @@ static void v4l2_update_stream_addr(struct vpu_ctx *ctx, uint32_t uStrBufIdx)
 
                buffer_size = p_data_req->vb2_buf->planes[0].bytesused;
                input_buffer = (void *)vb2_plane_vaddr(p_data_req->vb2_buf, 0);
-               if (!update_stream_addr_vpu(ctx, input_buffer, buffer_size, uStrBufIdx)) {
+               frame_bytes = update_stream_addr_vpu(ctx,
+                                                    input_buffer,
+                                                    buffer_size,
+                                                    uStrBufIdx);
+               if (!frame_bytes) {
                        up(&This->drv_q_lock);
                        vpu_dbg(LVL_INFO, " %s no space to write\n", __func__);
                        return;
@@ -2333,7 +2359,10 @@ static void v4l2_update_stream_addr(struct vpu_ctx *ctx, uint32_t uStrBufIdx)
                        if (ctx->b_dis_reorder) {
                                /* frame successfully written into the stream buffer if in special low latency mode
                                        mark that this frame should be flushed for decode immediately */
-                               add_scode(ctx, 0, BUFFLUSH_PADDING_TYPE, true);
+                               frame_bytes += add_scode(ctx,
+                                                        0,
+                                                        BUFFLUSH_PADDING_TYPE,
+                                                        true);
                                record_log_info(ctx, LOG_PADDING, 0, 0);
                        }
                        ctx->frm_dec_delay++;
@@ -2346,6 +2375,7 @@ static void v4l2_update_stream_addr(struct vpu_ctx *ctx, uint32_t uStrBufIdx)
                if (buffer_size < p_data_req->vb2_buf->planes[0].length)
                        vpu_dbg(LVL_INFO, "v4l2_transfer_buffer_to_firmware - set stream_feed_complete - DEBUG 2\n");
 #endif
+               vpu_dec_receive_ts(ctx, p_data_req->vb2_buf, frame_bytes);
                list_del(&p_data_req->list);
                p_data_req->queued = false;
                if (p_data_req->vb2_buf)