From 8daf918a39e4d092f95f2e15cd1f71796949c3df Mon Sep 17 00:00:00 2001 From: Ayoung Sim Date: Tue, 17 Apr 2018 15:29:01 +0900 Subject: [PATCH] media: mfc: DRV4.0: support encoder DRC We support the DRC(Dynamic Resolution Change) using LASE_SEQ command. So we can start from SEQ_START without CLOSE/OPEN. Change-Id: I92a8e0e5beb889837164b3fb8917c74ec5b31ee9 Signed-off-by: Ayoung Sim --- .../media/platform/exynos/mfc/s5p_mfc_buf.c | 1 + .../media/platform/exynos/mfc/s5p_mfc_cmd.c | 5 +- .../media/platform/exynos/mfc/s5p_mfc_enc.c | 10 ++-- .../platform/exynos/mfc/s5p_mfc_enc_vb2_ops.c | 25 +++++++++- .../media/platform/exynos/mfc/s5p_mfc_irq.c | 46 ++++++++----------- .../media/platform/exynos/mfc/s5p_mfc_nal_q.c | 6 --- .../media/platform/exynos/mfc/s5p_mfc_opr.c | 9 +--- .../media/platform/exynos/mfc/s5p_mfc_reg.c | 2 +- 8 files changed, 53 insertions(+), 51 deletions(-) diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_buf.c b/drivers/media/platform/exynos/mfc/s5p_mfc_buf.c index 03c2610a6b94..aee117835eaa 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_buf.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_buf.c @@ -441,6 +441,7 @@ void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx) } s5p_mfc_mem_ion_free(dev, &ctx->codec_buf); + ctx->codec_buffer_allocated = 0; mfc_debug(2, "Release the codec buffer\n"); } diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_cmd.c b/drivers/media/platform/exynos/mfc/s5p_mfc_cmd.c index 3d2614c8c83a..af09a6c9f848 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_cmd.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_cmd.c @@ -264,10 +264,11 @@ int s5p_mfc_cmd_enc_init_buffers(struct s5p_mfc_ctx *ctx) return -EINVAL; } - /* Header was generated now starting processing + /* + * Header was generated now starting processing * First set the reference frame buffers */ - if (!ctx->codec_buf.dma_buf) { + if (!ctx->codec_buffer_allocated) { mfc_info_ctx("there isn't codec buffer, re-alloc!\n"); ret = s5p_mfc_alloc_codec_buffers(ctx); if (ret) { diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c b/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c index 219e59905660..743132ead2fc 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c @@ -463,10 +463,12 @@ static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv, mfc_enc_check_format(ctx); - if ((ctx->state == MFCINST_RUNNING) - && (((ctx->old_img_width != 0) && (ctx->old_img_width != ctx->img_width)) - || ((ctx->old_img_height != 0) && (ctx->old_img_height != ctx->img_height)))) { - ctx->enc_drc_flag = 1; + if (ctx->state == MFCINST_RUNNING) { + s5p_mfc_change_state(ctx, MFCINST_GOT_INST); + mfc_info_ctx("Enc resolution is changed\n"); + if (((ctx->old_img_width != 0) && (ctx->old_img_width != ctx->img_width)) + || ((ctx->old_img_height != 0) && (ctx->old_img_height != ctx->img_height))) + ctx->enc_drc_flag = 1; } mfc_info_ctx("Enc input pixelformat : %s\n", ctx->src_fmt->name); diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc_vb2_ops.c b/drivers/media/platform/exynos/mfc/s5p_mfc_enc_vb2_ops.c index efe7a187e24c..db868b3a155e 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_enc_vb2_ops.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_enc_vb2_ops.c @@ -356,6 +356,29 @@ static void s5p_mfc_enc_stop_streaming(struct vb2_queue *q) index++; } } else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + if (ctx->state == MFCINST_FREE) { + mfc_debug(2, "already closed\n"); + } else { + s5p_mfc_change_state(ctx, MFCINST_FINISHING); + s5p_mfc_set_bit(ctx->num, &dev->work_bits); + + while (s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED)) { + ret = s5p_mfc_just_run(dev, ctx->num); + if (ret) { + mfc_err_ctx("Failed to run MFC.\n"); + break; + } + if (s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_FRAME_DONE_RET)) { + mfc_err_ctx("Waiting for LAST_SEQ timed out\n"); + break; + } + if (ctx->state == MFCINST_RUNNING) { + mfc_debug(2, "all encoded buffers out\n"); + break; + } + } + } + s5p_mfc_move_all_bufs(&ctx->buf_queue_lock, &ctx->src_buf_queue, &ctx->ref_buf_queue, MFC_QUEUE_ADD_BOTTOM); s5p_mfc_cleanup_enc_src_queue(ctx); @@ -377,8 +400,6 @@ static void s5p_mfc_enc_stop_streaming(struct vb2_queue *q) s5p_mfc_clear_bit(ctx->num, &dev->work_bits); s5p_mfc_release_hwlock_ctx(ctx); - if (s5p_mfc_enc_ctx_ready(ctx)) - s5p_mfc_set_bit(ctx->num, &dev->work_bits); if (s5p_mfc_is_work_to_do(dev)) queue_work(dev->butler_wq, &dev->butler_work); } diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c b/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c index c986b6dcb838..c457efb3b72e 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c @@ -808,8 +808,7 @@ static void mfc_handle_stream_input(struct s5p_mfc_ctx *ctx, int slice_type) raw = &ctx->raw_buf; - if (!ctx->enc_res_change_re_input && slice_type >= 0 && - ctx->state != MFCINST_FINISHING) { + if (!ctx->enc_res_change_re_input && slice_type >= 0) { if (ctx->state == MFCINST_RUNNING_NO_OUTPUT || ctx->state == MFCINST_RUNNING_BUF_FULL) s5p_mfc_change_state(ctx, MFCINST_RUNNING); @@ -885,21 +884,6 @@ static void mfc_handle_stream_input(struct s5p_mfc_ctx *ctx, int slice_type) } } } - } else if (ctx->state == MFCINST_FINISHING) { - src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, - &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED); - if (!src_mb) { - mfc_err_ctx("no src buffers.\n"); - return; - } - - vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE); - - /* encoder src buffer CFW UNPROT */ - if (ctx->is_drm) { - index = src_mb->vb.vb2_buf.index; - s5p_mfc_raw_unprotect(ctx, src_mb, index); - } } } @@ -910,8 +894,7 @@ static void mfc_handle_stream_output(struct s5p_mfc_ctx *ctx, int slice_type, struct s5p_mfc_buf *dst_mb; unsigned int index; - if (strm_size > 0 || ctx->state == MFCINST_FINISHING - || ctx->state == MFCINST_RUNNING_BUF_FULL) { + if (strm_size > 0 || ctx->state == MFCINST_RUNNING_BUF_FULL) { /* at least one more dest. buffers exist always */ dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED); @@ -955,12 +938,6 @@ static void mfc_handle_stream_output(struct s5p_mfc_ctx *ctx, int slice_type, if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0) mfc_err_ctx("failed in get_buf_ctrls_val\n"); - if (strm_size == 0 && ctx->state == MFCINST_FINISHING) - call_cop(ctx, get_buf_update_val, ctx, - &ctx->dst_ctrls[index], - V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, - enc->stored_tag); - vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE); /* encoder dst buffer CFW UNPROT */ @@ -1230,7 +1207,6 @@ static int mfc_handle_seq_enc(struct s5p_mfc_ctx *ctx) p->codec.bpg.thumb_size, p->codec.bpg.exif_size); } else { - /* TODO: is there other case? */ if ((p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) || (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_AT_THE_READY)) { dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, @@ -1249,7 +1225,6 @@ static int mfc_handle_seq_enc(struct s5p_mfc_ctx *ctx) s5p_mfc_stream_unprotect(ctx, dst_mb, index); } - } } @@ -1259,6 +1234,14 @@ static int mfc_handle_seq_enc(struct s5p_mfc_ctx *ctx) /* If the ROI is enabled at SEQ_START, clear ROI_ENABLE bit */ s5p_mfc_clear_roi_enable(dev); + if (!ctx->codec_buffer_allocated) { + mfc_debug(2, "previous codec buffer is exist\n"); + + if (dev->has_mmcache && dev->mmcache.is_on_status) + s5p_mfc_invalidate_mmcache(dev); + + s5p_mfc_release_codec_buffers(ctx); + } ret = s5p_mfc_alloc_codec_buffers(ctx); if (ret) { mfc_err_ctx("Failed to allocate encoding buffers.\n"); @@ -1481,9 +1464,16 @@ static int mfc_irq_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned in case S5P_FIMV_R2H_CMD_SLICE_DONE_RET: case S5P_FIMV_R2H_CMD_FIELD_DONE_RET: case S5P_FIMV_R2H_CMD_FRAME_DONE_RET: - case S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET: case S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET: return mfc_handle_done_frame(ctx, reason, err); + case S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET: + if (ctx->type == MFCINST_ENCODER) { + mfc_handle_stream(ctx); + s5p_mfc_change_state(ctx, MFCINST_RUNNING); + } else if (ctx->type == MFCINST_DECODER) { + return mfc_handle_done_frame(ctx, reason, err); + } + break; case S5P_FIMV_R2H_CMD_SEQ_DONE_RET: if (ctx->type == MFCINST_ENCODER) { if (ctx->otf_handle) { diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c b/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c index 29dbf9c96887..f38ab5c1eb60 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c @@ -1087,12 +1087,6 @@ static void mfc_nal_q_handle_stream(struct s5p_mfc_ctx *ctx, EncoderOutputStr *p mfc_err_ctx("NAL Q: failed in get_buf_ctrls_val in nal q\n"); vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE); - } else if (strm_size == 0) { - dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue, MFC_BUF_NO_TOUCH_USED); - if (!dst_mb) - mfc_err_dev("NAL Q: no dst buffers\n"); - else - vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR); } mfc_debug_leave(); diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_opr.c b/drivers/media/platform/exynos/mfc/s5p_mfc_opr.c index e20f7a0c35a8..9006a54b2129 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_opr.c @@ -304,18 +304,11 @@ int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) int s5p_mfc_run_enc_last_frames(struct s5p_mfc_ctx *ctx) { - struct s5p_mfc_buf *src_mb, *dst_mb; + struct s5p_mfc_buf *dst_mb; struct s5p_mfc_raw_info *raw; raw = &ctx->raw_buf; - /* Get the next source buffer */ - src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED); - if (!src_mb) { - mfc_debug(2, "no src buffers.\n"); - return -EAGAIN; - } - dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_SET_USED); if (!dst_mb) { mfc_debug(2, "no dst buffers.\n"); diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c b/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c index aee8f0ebad27..abec9c910e53 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c @@ -268,7 +268,7 @@ int s5p_mfc_set_enc_codec_buffers(struct s5p_mfc_ctx *ctx) buf_addr1 += enc->tmv_buffer_size >> 1; buf_size1 -= enc->tmv_buffer_size; - mfc_debug(2, "Buf1: 0x%p, buf_size1: %d (ref frames %d)\n", + mfc_debug(2, "Buf1 end: 0x%p, buf_size1: %d (ref frames %d)\n", (void *)buf_addr1, buf_size1, ctx->dpb_count); if (buf_size1 < 0) { mfc_debug(2, "Not enough memory has been allocated.\n"); -- 2.20.1