From 367bc37682b29aa33f3457f22db7865199f1f734 Mon Sep 17 00:00:00 2001 From: Ayoung Sim Date: Tue, 25 Jul 2017 17:11:29 +0900 Subject: [PATCH] media: mfc: Support buffer batch mode Eight images in buffer container is handled Change-Id: I12999f1a5800da019810de3618ce46d14fa41492 Signed-off-by: Jiho Chang Signed-off-by: Ayoung Sim --- .../platform/exynos/mfc/s5p_mfc_common.h | 3 + .../platform/exynos/mfc/s5p_mfc_data_struct.h | 11 +- .../platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c | 26 +- .../platform/exynos/mfc/s5p_mfc_enc_vb2_ops.c | 71 +++-- .../media/platform/exynos/mfc/s5p_mfc_irq.c | 91 +++++-- .../media/platform/exynos/mfc/s5p_mfc_mem.c | 62 +++++ .../media/platform/exynos/mfc/s5p_mfc_mem.h | 23 ++ .../media/platform/exynos/mfc/s5p_mfc_nal_q.c | 246 ++++++++++++------ .../media/platform/exynos/mfc/s5p_mfc_opr.c | 12 +- .../media/platform/exynos/mfc/s5p_mfc_queue.c | 113 ++++++-- .../media/platform/exynos/mfc/s5p_mfc_queue.h | 6 +- .../media/platform/exynos/mfc/s5p_mfc_reg.c | 31 ++- 12 files changed, 509 insertions(+), 186 deletions(-) diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_common.h b/drivers/media/platform/exynos/mfc/s5p_mfc_common.h index e97e36ad4228..baea4468e290 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_common.h +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_common.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -136,6 +137,8 @@ #define ON_RES_CHANGE(ctx) (((ctx)->state >= MFCINST_RES_CHANGE_INIT) && \ ((ctx)->state <= MFCINST_RES_CHANGE_END)) +#define IS_BUFFER_BATCH_MODE(ctx) ((ctx)->num_bufs_in_vb > 0) + /* UHD resoluition */ #define MFC_UHD_RES (3840 * 2160) #define IS_UHD_RES(ctx) (((ctx)->img_width * (ctx)->img_height) == MFC_UHD_RES) diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h b/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h index 52115947c6d8..1b1767038cff 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h @@ -47,6 +47,9 @@ /* Maximum number of temporal layers */ #define VIDEO_MAX_TEMPORAL_LAYERS 7 +#define MAX_NUM_IMAGES_IN_VB 8 +#define MAX_NUM_BUFCON_BUFS 32 + /* * MFC version */ @@ -222,7 +225,11 @@ struct s5p_mfc_debug { struct s5p_mfc_buf { struct vb2_v4l2_buffer vb; struct list_head list; - dma_addr_t addr[MFC_MAX_PLANES]; + dma_addr_t addr[MAX_NUM_IMAGES_IN_VB][MFC_MAX_PLANES]; + struct dma_buf *dmabufs[MAX_NUM_IMAGES_IN_VB][MFC_MAX_PLANES]; + struct dma_buf_attachment *attachments[MAX_NUM_IMAGES_IN_VB][MFC_MAX_PLANES]; + int next_index; + int done_index; int used; unsigned char *vir_addr; }; @@ -1321,6 +1328,8 @@ struct s5p_mfc_ctx { unsigned long raw_protect_flag; unsigned long stream_protect_flag; struct _otf_handle *otf_handle; + + int num_bufs_in_vb; }; #endif /* __S5P_MFC_DATA_STRUCT_H */ diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c b/drivers/media/platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c index a965d2e0ab8f..cadcd56f31fa 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c @@ -181,26 +181,26 @@ static int s5p_mfc_dec_buf_init(struct vb2_buffer *vb) start_raw = s5p_mfc_mem_get_daddr_vb(vb, 0); if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12N) { - buf->addr[0] = start_raw; - buf->addr[1] = NV12N_CBCR_BASE(start_raw, + buf->addr[0][0] = start_raw; + buf->addr[0][1] = NV12N_CBCR_BASE(start_raw, ctx->img_width, ctx->img_height); } else if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12N_10B) { - buf->addr[0] = start_raw; - buf->addr[1] = NV12N_10B_CBCR_BASE(start_raw, + buf->addr[0][0] = start_raw; + buf->addr[0][1] = NV12N_10B_CBCR_BASE(start_raw, ctx->img_width, ctx->img_height); } else if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420N) { - buf->addr[0] = start_raw; - buf->addr[1] = YUV420N_CB_BASE(start_raw, + buf->addr[0][0] = start_raw; + buf->addr[0][1] = YUV420N_CB_BASE(start_raw, ctx->img_width, ctx->img_height); - buf->addr[2] = YUV420N_CR_BASE(start_raw, + buf->addr[0][2] = YUV420N_CR_BASE(start_raw, ctx->img_width, ctx->img_height); } else { for (i = 0; i < ctx->dst_fmt->mem_planes; i++) - buf->addr[i] = s5p_mfc_mem_get_daddr_vb(vb, i); + buf->addr[0][i] = s5p_mfc_mem_get_daddr_vb(vb, i); } if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_DST, @@ -211,7 +211,7 @@ static int s5p_mfc_dec_buf_init(struct vb2_buffer *vb) if (ret < 0) return ret; - buf->addr[0] = s5p_mfc_mem_get_daddr_vb(vb, 0); + buf->addr[0][0] = s5p_mfc_mem_get_daddr_vb(vb, 0); if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_SRC, vb->index) < 0) @@ -580,7 +580,7 @@ static void s5p_mfc_dec_buf_queue(struct vb2_buffer *vb) mfc_debug(2, "Src queue: 0x%p\n", &ctx->src_buf_queue); mfc_debug(2, "Adding to src: 0x%p (0x%08llx, 0x%08llx)\n", vb, s5p_mfc_mem_get_daddr_vb(vb, 0), - buf->addr[0]); + buf->addr[0][0]); if (dec->dst_memtype == V4L2_MEMORY_DMABUF && ctx->state < MFCINST_HEAD_PARSED && !ctx->is_drm) stream_vir = vb2_plane_vaddr(vb, 0); @@ -590,7 +590,7 @@ static void s5p_mfc_dec_buf_queue(struct vb2_buffer *vb) s5p_mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, buf); MFC_TRACE_CTX("Q src[%d] fd: %d, %#llx\n", - vb->index, vb->planes[0].m.fd, buf->addr[0]); + vb->index, vb->planes[0].m.fd, buf->addr[0][0]); } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { index = vb->index; mfc_debug(2, "Dst queue: 0x%p\n", &ctx->dst_buf_queue); @@ -598,7 +598,7 @@ static void s5p_mfc_dec_buf_queue(struct vb2_buffer *vb) s5p_mfc_mem_get_daddr_vb(vb, 0)); for (i = 0; i < ctx->dst_fmt->num_planes; i++) mfc_debug(2, "dec dst plane[%d]: %08llx\n", - i, buf->addr[i]); + i, buf->addr[0][i]); s5p_mfc_store_dpb(ctx, vb); if ((dec->dst_memtype == V4L2_MEMORY_USERPTR || dec->dst_memtype == V4L2_MEMORY_DMABUF) && @@ -607,7 +607,7 @@ static void s5p_mfc_dec_buf_queue(struct vb2_buffer *vb) ctx->capture_state = QUEUE_BUFS_MMAPED; MFC_TRACE_CTX("Q dst[%d] fd: %d, %#llx / avail %#lx used %#x\n", - index, vb->planes[0].m.fd, buf->addr[0], + index, vb->planes[0].m.fd, buf->addr[0][0], dec->available_dpb, dec->dynamic_used); } else { mfc_err_ctx("Unsupported buffer type (%d)\n", vq->type); 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 cc2b04c1d079..44a178b83823 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 @@ -124,7 +124,7 @@ static int s5p_mfc_enc_buf_init(struct vb2_buffer *vb) struct vb2_queue *vq = vb->vb2_queue; struct s5p_mfc_ctx *ctx = vq->drv_priv; struct s5p_mfc_buf *buf = vb_to_mfc_buf(vb); - dma_addr_t start_raw; + struct dma_buf *dmabuf; int i, ret; mfc_debug_enter(); @@ -134,7 +134,7 @@ static int s5p_mfc_enc_buf_init(struct vb2_buffer *vb) if (ret < 0) return ret; - buf->addr[0] = s5p_mfc_mem_get_daddr_vb(vb, 0); + buf->addr[0][0] = s5p_mfc_mem_get_daddr_vb(vb, 0); if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_DST, vb->index) < 0) @@ -145,33 +145,55 @@ static int s5p_mfc_enc_buf_init(struct vb2_buffer *vb) if (ret < 0) return ret; - start_raw = s5p_mfc_mem_get_daddr_vb(vb, 0); - if (start_raw == 0) { - mfc_err_ctx("Plane mem not allocated.\n"); - return -ENOMEM; - } - if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12N) { - buf->addr[0] = start_raw; - buf->addr[1] = NV12N_CBCR_BASE(start_raw, + for (i = 0; i < ctx->src_fmt->num_planes; i++) { + dmabuf = s5p_mfc_mem_get_dmabuf(vb->planes[i].m.fd); + if (!dmabuf) + return -ENOMEM; + + ctx->num_bufs_in_vb = s5p_mfc_bufcon_get_buf_count(dmabuf); + mfc_debug(3, "bufcon count:%d\n", ctx->num_bufs_in_vb); + + if (IS_BUFFER_BATCH_MODE(ctx)) { + int count = 0; + + count = s5p_mfc_bufcon_get_daddr(ctx, buf, dmabuf, i); + if (count != ctx->num_bufs_in_vb) { + mfc_err_ctx("invalid buffer count %d != num_bufs_in_vb %d\n", + count, ctx->num_bufs_in_vb); + return -EFAULT; + } + + s5p_mfc_mem_put_dmabuf(dmabuf); + } else { + dma_addr_t start_raw; + + start_raw = s5p_mfc_mem_get_daddr_vb(vb, 0); + if (start_raw == 0) { + mfc_err_ctx("Plane mem not allocated.\n"); + return -ENOMEM; + } + if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12N) { + buf->addr[0][0] = start_raw; + buf->addr[0][1] = NV12N_CBCR_BASE(start_raw, ctx->img_width, ctx->img_height); - } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_YUV420N) { - buf->addr[0] = start_raw; - buf->addr[1] = YUV420N_CB_BASE(start_raw, + } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_YUV420N) { + buf->addr[0][0] = start_raw; + buf->addr[0][1] = YUV420N_CB_BASE(start_raw, ctx->img_width, ctx->img_height); - buf->addr[2] = YUV420N_CR_BASE(start_raw, + buf->addr[0][2] = YUV420N_CR_BASE(start_raw, ctx->img_width, ctx->img_height); - } else { - for (i = 0; i < ctx->src_fmt->num_planes; i++) - buf->addr[i] = s5p_mfc_mem_get_daddr_vb(vb, i); - } - - if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_SRC, - vb->index) < 0) - mfc_err_ctx("failed in init_buf_ctrls\n"); + } else { + buf->addr[0][i] = s5p_mfc_mem_get_daddr_vb(vb, i); + } + if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_SRC, + vb->index) < 0) + mfc_err_ctx("failed in init_buf_ctrls\n"); + } + } } else { mfc_err_ctx("inavlid queue type: %d\n", vq->type); return -EINVAL; @@ -371,9 +393,12 @@ static void s5p_mfc_enc_buf_queue(struct vb2_buffer *vb) mfc_debug_enter(); + buf->next_index = 0; + buf->done_index = 0; + if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { mfc_debug(2, "dst queue: 0x%p\n", &ctx->dst_buf_queue); - mfc_debug(2, "Adding to dst vb: 0x%p, addr: %08llx\n", vb, buf->addr[0]); + mfc_debug(2, "Adding to dst vb: 0x%p, addr: %08llx\n", vb, buf->addr[0][0]); /* Mark destination as available for use by MFC */ s5p_mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, buf); diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c b/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c index 9cb1433b908d..21eaf54f00ba 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c @@ -173,7 +173,7 @@ static void mfc_handle_frame_copy_timestamp(struct s5p_mfc_ctx *ctx) return; } - ref_mb = s5p_mfc_find_buf(&ctx->buf_queue_lock, &ctx->ref_buf_queue, dec_y_addr); + ref_mb = s5p_mfc_find_buf(&ctx->buf_queue_lock, &ctx->ref_buf_queue, dec_y_addr, 0); if (ref_mb) ref_mb->vb.vb2_buf.timestamp = src_mb->vb.vb2_buf.timestamp; } @@ -192,7 +192,7 @@ static void mfc_handle_frame_output_move(struct s5p_mfc_ctx *ctx, mfc_debug(2, "Listing: %d\n", ref_mb->vb.vb2_buf.index); /* Check if this is the buffer we're looking for */ mfc_debug(2, "Found 0x%08llx, looking for 0x%08llx\n", - ref_mb->addr[0], dspl_y_addr); + ref_mb->addr[0][0], dspl_y_addr); index = ref_mb->vb.vb2_buf.index; @@ -248,12 +248,12 @@ static void mfc_handle_frame_output_del(struct s5p_mfc_ctx *ctx, } ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, - &ctx->ref_buf_queue, dspl_y_addr); + &ctx->ref_buf_queue, dspl_y_addr, 0); if (ref_mb) { mfc_debug(2, "Listing: %d\n", ref_mb->vb.vb2_buf.index); /* Check if this is the buffer we're looking for */ mfc_debug(2, "Found 0x%08llx, looking for 0x%08llx\n", - ref_mb->addr[0], dspl_y_addr); + ref_mb->addr[0][0], dspl_y_addr); index = ref_mb->vb.vb2_buf.index; @@ -484,7 +484,7 @@ static void mfc_handle_ref_frame(struct s5p_mfc_ctx *ctx) &ctx->ref_buf_queue, &ctx->dst_buf_queue, dec_addr); if (dst_mb) { mfc_debug(2, "Found in dst queue = 0x%08llx, buf = 0x%08llx\n", - dec_addr, dst_mb->addr[0]); + dec_addr, dst_mb->addr[0][0]); if (!(dec->dynamic_set & s5p_mfc_get_dec_used_flag())) dec->dynamic_used |= dec->dynamic_set; @@ -779,30 +779,62 @@ static void mfc_handle_stream_input(struct s5p_mfc_ctx *ctx, int slice_type) mfc_debug(2, "encoded[%d] addr: 0x%08llx\n", i, enc_addr[i]); - src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, - &ctx->src_buf_queue, enc_addr[0]); - if (src_mb) { - index = src_mb->vb.vb2_buf.index; - if (call_cop(ctx, recover_buf_ctrls_val, ctx, - &ctx->src_ctrls[index]) < 0) - mfc_err_ctx("failed in recover_buf_ctrls_val\n"); + if (IS_BUFFER_BATCH_MODE(ctx)) { + src_mb = s5p_mfc_find_first_buf(&ctx->buf_queue_lock, + &ctx->src_buf_queue, enc_addr[0], ctx->num_bufs_in_vb); + if (src_mb) { + src_mb->done_index++; + mfc_debug(4, "batch buf done_index: %d\n", src_mb->done_index); - vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE); + index = src_mb->vb.vb2_buf.index; - /* encoder src buffer CFW UNPROT */ - if (ctx->is_drm) - s5p_mfc_raw_unprotect(ctx, src_mb, index); - } + if (call_cop(ctx, recover_buf_ctrls_val, ctx, + &ctx->src_ctrls[index]) < 0) + mfc_err_ctx("failed in recover_buf_ctrls_val\n"); + + /* last image in a buffer container */ + if (src_mb->done_index == ctx->num_bufs_in_vb) { + src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, + &ctx->src_buf_queue, enc_addr[0], + ctx->num_bufs_in_vb); + if (src_mb) { + for (i = 0; i < raw->num_planes; i++) + s5p_mfc_bufcon_put_daddr(ctx, src_mb, i); + vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE); + } + } + + /* encoder src buffer CFW UNPROT */ + if (ctx->is_drm) + s5p_mfc_raw_unprotect(ctx, src_mb, index); + } + } else { + /* normal single buffer */ + src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, + &ctx->src_buf_queue, enc_addr[0], 0); + if (src_mb) { + index = src_mb->vb.vb2_buf.index; + if (call_cop(ctx, recover_buf_ctrls_val, ctx, + &ctx->src_ctrls[index]) < 0) + mfc_err_ctx("failed in recover_buf_ctrls_val\n"); - ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, - &ctx->ref_buf_queue, enc_addr[0]); - if (ref_mb) { - vb2_buffer_done(&ref_mb->vb.vb2_buf, VB2_BUF_STATE_DONE); + vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE); - /* encoder src buffer CFW UNPROT */ - if (ctx->is_drm) { - index = ref_mb->vb.vb2_buf.index; - s5p_mfc_raw_unprotect(ctx, ref_mb, index); + /* encoder src buffer CFW UNPROT */ + if (ctx->is_drm) + s5p_mfc_raw_unprotect(ctx, src_mb, index); + } + + ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, + &ctx->ref_buf_queue, enc_addr[0], 0); + if (ref_mb) { + vb2_buffer_done(&ref_mb->vb.vb2_buf, VB2_BUF_STATE_DONE); + + /* encoder src buffer CFW UNPROT */ + if (ctx->is_drm) { + index = ref_mb->vb.vb2_buf.index; + s5p_mfc_raw_unprotect(ctx, ref_mb, index); + } } } } else if (ctx->state == MFCINST_FINISHING) { @@ -936,6 +968,9 @@ static int mfc_handle_stream(struct s5p_mfc_ctx *ctx) /* handle source buffer */ mfc_handle_stream_input(ctx, slice_type); + if (IS_BUFFER_BATCH_MODE(ctx)) + return 0; + if (ctx->enc_res_change_re_input) ctx->enc_res_change_re_input = 0; @@ -947,8 +982,10 @@ static int mfc_handle_stream(struct s5p_mfc_ctx *ctx) s5p_mfc_move_first_buf_used(&ctx->buf_queue_lock, &ctx->ref_buf_queue, &ctx->src_buf_queue, MFC_QUEUE_ADD_BOTTOM); - /* slice_type = 4 && strm_size = 0, skipped enable - should be considered */ + /* + * slice_type = 4 && strm_size = 0, skipped enable + * should be considered + */ if ((slice_type == -1) && (strm_size == 0)) s5p_mfc_change_state(ctx, MFCINST_RUNNING_NO_OUTPUT); diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_mem.c b/drivers/media/platform/exynos/mfc/s5p_mfc_mem.c index f23ef7fe1f0c..b5957363124f 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_mem.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_mem.c @@ -188,3 +188,65 @@ void s5p_mfc_mem_ion_free(struct s5p_mfc_dev *dev, special_buf->daddr = 0; special_buf->vaddr = NULL; } + +void s5p_mfc_bufcon_put_daddr(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf, int plane) +{ + int i; + + for (i = 0; i < ctx->num_bufs_in_vb; i++) { + if (mfc_buf->addr[i][plane]) { + mfc_debug(4, "put batch buf addr[%d][%d]: 0x%08llx\n", + i, plane, mfc_buf->addr[i][plane]); + ion_iovmm_unmap(mfc_buf->attachments[i][plane], mfc_buf->addr[i][plane]); + } + if (mfc_buf->attachments[i][plane]) + dma_buf_detach(mfc_buf->dmabufs[i][plane], mfc_buf->attachments[i][plane]); + if (mfc_buf->dmabufs[i][plane]) + dma_buf_put(mfc_buf->dmabufs[i][plane]); + + mfc_buf->addr[i][plane] = 0; + mfc_buf->attachments[i][plane] = NULL; + mfc_buf->dmabufs[i][plane] = NULL; + } +} + +int s5p_mfc_bufcon_get_daddr(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf, + struct dma_buf *bufcon_dmabuf, int plane) +{ + struct s5p_mfc_dev *dev = ctx->dev; + struct s5p_mfc_raw_info *raw = &ctx->raw_buf; + int i; + + for (i = 0; i < ctx->num_bufs_in_vb; i++) { + mfc_buf->dmabufs[i][plane] = dmabuf_container_get_buffer(bufcon_dmabuf, i); + if (IS_ERR(mfc_buf->dmabufs[i][plane])) { + mfc_err_ctx("Failed to get dma_buf (err %ld)", + PTR_ERR(mfc_buf->dmabufs[i][plane])); + goto err_get_daddr; + } + + mfc_buf->attachments[i][plane] = dma_buf_attach(mfc_buf->dmabufs[i][plane], dev->device); + if (IS_ERR(mfc_buf->attachments[i][plane])) { + mfc_err_ctx("Failed to get dma_buf_attach (err %ld)", + PTR_ERR(mfc_buf->attachments[i][plane])); + goto err_get_daddr; + } + + mfc_buf->addr[i][plane] = ion_iovmm_map(mfc_buf->attachments[i][plane], 0, + raw->plane_size[plane], DMA_BIDIRECTIONAL, 0); + if (IS_ERR_VALUE(mfc_buf->addr[i][plane])) { + mfc_err_ctx("Failed to allocate iova (err %pa)", + &mfc_buf->addr[i][plane]); + goto err_get_daddr; + } + + mfc_debug(4, "get batch buf addr[%d][%d]: 0x%08llx, size: %d\n", + i, plane, mfc_buf->addr[i][plane], raw->plane_size[plane]); + } + + return i; + +err_get_daddr: + s5p_mfc_bufcon_put_daddr(ctx, mfc_buf, plane); + return -1; +} diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_mem.h b/drivers/media/platform/exynos/mfc/s5p_mfc_mem.h index 51d274662043..eb14659edca2 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_mem.h +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_mem.h @@ -30,6 +30,26 @@ static inline dma_addr_t s5p_mfc_mem_get_daddr_vb( return addr; } +static inline struct dma_buf *s5p_mfc_mem_get_dmabuf(int fd) +{ + struct dma_buf *dmabuf = NULL; + + dmabuf = dma_buf_get(fd); + WARN_ON(dmabuf == NULL); + + return dmabuf; +} + +static inline void s5p_mfc_mem_put_dmabuf(struct dma_buf *dmabuf) +{ + dma_buf_put(dmabuf); +} + +static inline int s5p_mfc_bufcon_get_buf_count(struct dma_buf *dmabuf) +{ + return dmabuf_container_get_count(dmabuf); +} + struct vb2_mem_ops *s5p_mfc_mem_ops(void); void s5p_mfc_mem_set_cacheable(bool cacheable); @@ -50,4 +70,7 @@ int s5p_mfc_mem_ion_alloc(struct s5p_mfc_dev *dev, void s5p_mfc_mem_ion_free(struct s5p_mfc_dev *dev, struct s5p_mfc_special_buf *special_buf); +void s5p_mfc_bufcon_put_daddr(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf, int plane); +int s5p_mfc_bufcon_get_daddr(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf, + struct dma_buf *bufcon_dmabuf, int plane); #endif /* __S5P_MFC_MEM_H */ 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 2feab06f4018..62d358e29782 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c @@ -550,7 +550,7 @@ static int mfc_nal_q_run_in_buf_enc(struct s5p_mfc_ctx *ctx, EncoderInputStr *pI struct s5p_mfc_buf *src_mb, *dst_mb; struct s5p_mfc_raw_info *raw = NULL; dma_addr_t src_addr[3] = {0, 0, 0}; - dma_addr_t addr_2bit[2]; + dma_addr_t addr_2bit[2] = {0, 0}; unsigned int index, i; mfc_debug_enter(); @@ -571,18 +571,46 @@ static int mfc_nal_q_run_in_buf_enc(struct s5p_mfc_ctx *ctx, EncoderInputStr *pI raw = &ctx->raw_buf; - /* move src_queue -> src_queue_nal_q */ - src_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock, - &ctx->src_buf_nal_queue, &ctx->src_buf_queue, MFC_BUF_SET_USED, MFC_QUEUE_ADD_BOTTOM); - if (!src_mb) { - mfc_err_dev("NAL Q: no src buffers\n"); - return -EAGAIN; - } + if (IS_BUFFER_BATCH_MODE(ctx)) { + src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED); + if (!src_mb) { + mfc_err_dev("NAL Q: no src buffers\n"); + return -EAGAIN; + } - for (i = 0; i < raw->num_planes; i++) { - src_addr[i] = src_mb->addr[i]; - mfc_debug(2, "NAL Q: enc src[%d] addr: 0x%08llx\n", - i, src_addr[i]); + /* last image in a buffer container */ + /* move src_queue -> src_queue_nal_q */ + if (src_mb->next_index == (ctx->num_bufs_in_vb - 1)) { + src_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock, + &ctx->src_buf_nal_queue, &ctx->src_buf_queue, + MFC_BUF_SET_USED, MFC_QUEUE_ADD_BOTTOM); + if (!src_mb) { + mfc_err_dev("NAL Q: no src buffers\n"); + return -EAGAIN; + } + } + + for (i = 0; i < raw->num_planes; i++) { + src_addr[i] = src_mb->addr[src_mb->next_index][i]; + mfc_debug(2, "NAL Q: enc batch buf[%d] src[%d] addr: 0x%08llx\n", + src_mb->next_index, i, src_addr[i]); + } + src_mb->next_index++; + } else { + /* move src_queue -> src_queue_nal_q */ + src_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock, + &ctx->src_buf_nal_queue, &ctx->src_buf_queue, + MFC_BUF_SET_USED, MFC_QUEUE_ADD_BOTTOM); + if (!src_mb) { + mfc_err_dev("NAL Q: no src buffers\n"); + return -EAGAIN; + } + + for (i = 0; i < raw->num_planes; i++) { + src_addr[i] = src_mb->addr[0][i]; + mfc_debug(2, "NAL Q: enc src[%d] addr: 0x%08llx\n", + i, src_addr[i]); + } } for (i = 0; i < raw->num_planes; i++) @@ -612,7 +640,7 @@ static int mfc_nal_q_run_in_buf_enc(struct s5p_mfc_ctx *ctx, EncoderInputStr *pI return -EAGAIN; } - pInStr->StreamBufferAddr = dst_mb->addr[0]; + pInStr->StreamBufferAddr = dst_mb->addr[0][0]; pInStr->StreamBufferSize = (unsigned int)vb2_plane_size(&dst_mb->vb.vb2_buf, 0); pInStr->StreamBufferSize = ALIGN(pInStr->StreamBufferSize, 512); @@ -695,7 +723,7 @@ static int mfc_nal_q_run_in_buf_dec(struct s5p_mfc_ctx *ctx, DecoderInputStr *pI } /* src buffer setting */ - buf_addr = src_mb->addr[0]; + buf_addr = src_mb->addr[0][0]; strm_size = src_mb->vb.vb2_buf.planes[0].bytesused; cpb_buf_size = ALIGN(dec->src_buf_size, STREAM_BUF_ALIGN); mfc_debug(2, "NAL Q: Src addr: 0x%08llx, size: %d\n", buf_addr, strm_size); @@ -727,10 +755,10 @@ static int mfc_nal_q_run_in_buf_dec(struct s5p_mfc_ctx *ctx, DecoderInputStr *pI for (i = 0; i < raw->num_planes; i++) { pInStr->FrameSize[i] = raw->plane_size[i]; - pInStr->FrameAddr[i] = dst_mb->addr[i]; + pInStr->FrameAddr[i] = dst_mb->addr[0][i]; } mfc_debug(2, "NAL Q: dst addr[0]: 0x%08llx\n", - dst_mb->addr[0]); + dst_mb->addr[0][0]); pInStr->ScratchBufAddr = ctx->codec_buf.daddr; pInStr->ScratchBufSize = ctx->scratch_buf_size; @@ -747,7 +775,7 @@ static int mfc_nal_q_run_in_buf_dec(struct s5p_mfc_ctx *ctx, DecoderInputStr *pI pInStr->AvailableDpbFlagLower = dec->dynamic_set; MFC_TRACE_CTX("Set dst[%d] fd: %d, %#llx / avail %#lx used %#x\n", - dst_index, dst_mb->vb.vb2_buf.planes[0].m.fd, dst_mb->addr[0], + dst_index, dst_mb->vb.vb2_buf.planes[0].m.fd, dst_mb->addr[0][0], dec->available_dpb, dec->dynamic_used); mfc_debug_leave(); @@ -771,13 +799,115 @@ static void mfc_nal_q_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx, mfc_debug(2, "NAL Q: recon c addr: 0x%08lx\n", enc_recon_c_addr); } +static void mfc_nal_q_handle_stream_input(struct s5p_mfc_ctx *ctx, int slice_type, + unsigned int strm_size, EncoderOutputStr *pOutStr) +{ + struct s5p_mfc_buf *src_mb, *ref_mb, *dst_mb; + dma_addr_t enc_addr[3] = { 0, 0, 0 }; + struct s5p_mfc_raw_info *raw; + unsigned int i; + + raw = &ctx->raw_buf; + + if (slice_type >= 0) { + if (ctx->state == MFCINST_RUNNING_NO_OUTPUT || + ctx->state == MFCINST_RUNNING_BUF_FULL) + ctx->state = MFCINST_RUNNING; + + mfc_nal_q_get_enc_frame_buffer(ctx, &enc_addr[0], + raw->num_planes, pOutStr); + + for (i = 0; i < raw->num_planes; i++) + mfc_debug(2, "NAL Q: encoded[%d] addr: 0x%08llx\n", i, + enc_addr[i]); + + if (IS_BUFFER_BATCH_MODE(ctx)) { + src_mb = s5p_mfc_find_first_buf(&ctx->buf_queue_lock, + &ctx->src_buf_queue, enc_addr[0], ctx->num_bufs_in_vb); + if (src_mb) { + src_mb->done_index++; + mfc_debug(4, "batch buf done_index: %d\n", src_mb->done_index); + } else { + src_mb = s5p_mfc_find_first_buf(&ctx->buf_queue_lock, + &ctx->src_buf_nal_queue, enc_addr[0], ctx->num_bufs_in_vb); + if (src_mb) { + src_mb->done_index++; + mfc_debug(4, "batch buf done_index: %d\n", src_mb->done_index); + + /* last image in a buffer container */ + if (src_mb->done_index == ctx->num_bufs_in_vb) { + src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, + &ctx->src_buf_nal_queue, enc_addr[0], + ctx->num_bufs_in_vb); + if (src_mb) { + for (i = 0; i < raw->num_planes; i++) + s5p_mfc_bufcon_put_daddr(ctx, src_mb, i); + vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE); + } + } + } + } + } else { + src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, + &ctx->src_buf_nal_queue, enc_addr[0], 0); + if (!src_mb) { + mfc_err_dev("NAL Q: no src buffers\n"); + return; + } + + vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE); + + ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, + &ctx->ref_buf_queue, enc_addr[0], 0); + if (ref_mb) + vb2_buffer_done(&ref_mb->vb.vb2_buf, VB2_BUF_STATE_DONE); + } + } else if (s5p_mfc_is_queue_count_greater(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue, 0)) { + if (IS_BUFFER_BATCH_MODE(ctx)) + return; + + src_mb = s5p_mfc_get_move_buf_used(&ctx->buf_queue_lock, + &ctx->ref_buf_queue, &ctx->src_buf_nal_queue); + if (!src_mb) { + mfc_err_dev("NAL Q: no src buffers\n"); + return; + } + + if (src_mb->used) { + mfc_debug(2, "NAL Q: no output, src_queue_nal_q -> ref_queue, index:%d\n", + src_mb->vb.vb2_buf.index); + } + + /* + * slice_type = 4 && strm_size = 0, skipped enable + * should be considered + */ + if ((slice_type == -1) && (strm_size == 0)) { + ctx->state = MFCINST_RUNNING_NO_OUTPUT; + + dst_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock, + &ctx->dst_buf_queue, &ctx->dst_buf_nal_queue, MFC_BUF_RESET_USED, MFC_QUEUE_ADD_TOP); + if (!dst_mb) { + mfc_err_dev("NAL Q: no dst buffers\n"); + return; + } + + mfc_debug(2, "NAL Q: no output, dst_buf_nal_queue -> dst_buf_queue, index:%d\n", + dst_mb->vb.vb2_buf.index); + } + + mfc_debug(2, "NAL Q: slice_type: %d, ctx->state: %d\n", slice_type, ctx->state); + mfc_debug(2, "NAL Q: enc src count: %d, enc ref count: %d\n", + s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue), + s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue)); + } +} + static void mfc_nal_q_handle_stream(struct s5p_mfc_ctx *ctx, EncoderOutputStr *pOutStr) { struct s5p_mfc_enc *enc = ctx->enc_priv; - struct s5p_mfc_buf *src_mb, *dst_mb, *ref_mb; - struct s5p_mfc_raw_info *raw; - dma_addr_t enc_addr[3] = { 0, 0, 0 }; - int slice_type, i; + struct s5p_mfc_buf *dst_mb; + int slice_type; unsigned int strm_size; unsigned int pic_count; unsigned int index; @@ -799,9 +929,10 @@ static void mfc_nal_q_handle_stream(struct s5p_mfc_ctx *ctx, EncoderOutputStr *p */ /* set encoded frame type */ enc->frame_type = slice_type; - raw = &ctx->raw_buf; ctx->sequence++; + + /* handle output buffer */ if (strm_size > 0) { /* at least one more dest. buffers exist always */ dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue, MFC_BUF_NO_TOUCH_USED); @@ -851,65 +982,8 @@ static void mfc_nal_q_handle_stream(struct s5p_mfc_ctx *ctx, EncoderOutputStr *p vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR); } - if (slice_type >= 0) { - if (ctx->state == MFCINST_RUNNING_NO_OUTPUT || - ctx->state == MFCINST_RUNNING_BUF_FULL) - ctx->state = MFCINST_RUNNING; - - mfc_nal_q_get_enc_frame_buffer(ctx, &enc_addr[0], - raw->num_planes, pOutStr); - - for (i = 0; i < raw->num_planes; i++) - mfc_debug(2, "NAL Q: encoded[%d] addr: 0x%08llx\n", i, - enc_addr[i]); - - src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, - &ctx->src_buf_nal_queue, enc_addr[0]); - if (!src_mb) { - mfc_err_dev("NAL Q: no src buffers\n"); - return; - } - - vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE); - - ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, - &ctx->ref_buf_queue, enc_addr[0]); - if (ref_mb) - vb2_buffer_done(&ref_mb->vb.vb2_buf, VB2_BUF_STATE_DONE); - } else if (s5p_mfc_is_queue_count_greater(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue, 0)) { - src_mb = s5p_mfc_get_move_buf_used(&ctx->buf_queue_lock, - &ctx->ref_buf_queue, &ctx->src_buf_nal_queue); - if (!src_mb) { - mfc_err_dev("NAL Q: no src buffers\n"); - return; - } - - if (src_mb->used) { - mfc_debug(2, "NAL Q: no output, src_queue_nal_q -> ref_queue, index:%d\n", - src_mb->vb.vb2_buf.index); - } - - /* slice_type = 4 && strm_size = 0, skipped enable - should be considered */ - if ((slice_type == -1) && (strm_size == 0)) { - ctx->state = MFCINST_RUNNING_NO_OUTPUT; - - dst_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock, - &ctx->dst_buf_queue, &ctx->dst_buf_nal_queue, MFC_BUF_RESET_USED, MFC_QUEUE_ADD_TOP); - if (!dst_mb) { - mfc_err_dev("NAL Q: no dst buffers\n"); - return; - } - - mfc_debug(2, "NAL Q: no output, dst_buf_nal_queue -> dst_buf_queue, index:%d\n", - dst_mb->vb.vb2_buf.index); - } - - mfc_debug(2, "NAL Q: slice_type: %d, ctx->state: %d\n", slice_type, ctx->state); - mfc_debug(2, "NAL Q: enc src count: %d, enc ref count: %d\n", - s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue), - s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue)); - } + /* handle input buffer */ + mfc_nal_q_handle_stream_input(ctx, slice_type, strm_size, pOutStr); mfc_debug_leave(); @@ -970,7 +1044,7 @@ static void mfc_nal_q_handle_ref_frame(struct s5p_mfc_ctx *ctx, DecoderOutputStr dst_mb = s5p_mfc_find_move_buf_used(&ctx->buf_queue_lock, &ctx->ref_buf_queue, &ctx->dst_buf_nal_queue, dec_addr); if (dst_mb) { - buf_addr = dst_mb->addr[0]; + buf_addr = dst_mb->addr[0][0]; mfc_debug(2, "NAL Q: Found in dst queue, " "dec addr: 0x%08llx, buf addr: 0x%08llx, used: %d\n", dec_addr, buf_addr, dst_mb->used); @@ -1011,7 +1085,7 @@ static void mfc_nal_q_handle_frame_copy_timestamp(struct s5p_mfc_ctx *ctx, Decod return; } - ref_mb = s5p_mfc_find_buf(&ctx->buf_queue_lock, &ctx->ref_buf_queue, dec_y_addr); + ref_mb = s5p_mfc_find_buf(&ctx->buf_queue_lock, &ctx->ref_buf_queue, dec_y_addr, 0); if (ref_mb) ref_mb->vb.vb2_buf.timestamp = src_mb->vb.vb2_buf.timestamp; @@ -1032,7 +1106,7 @@ static void mfc_nal_q_handle_frame_output_move(struct s5p_mfc_ctx *ctx, mfc_debug(2, "NAL Q: find display buf, index: %d\n", dst_mb->vb.vb2_buf.index); /* Check if this is the buffer we're looking for */ mfc_debug(2, "NAL Q: buf addr: 0x%08llx, disp addr: 0x%08llx\n", - dst_mb->addr[0], dspl_y_addr); + dst_mb->addr[0][0], dspl_y_addr); index = dst_mb->vb.vb2_buf.index; @@ -1090,12 +1164,12 @@ static void mfc_nal_q_handle_frame_output_del(struct s5p_mfc_ctx *ctx, } ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, - &ctx->ref_buf_queue, dspl_y_addr); + &ctx->ref_buf_queue, dspl_y_addr, 0); if (ref_mb) { mfc_debug(2, "NAL Q: find display buf, index: %d\n", ref_mb->vb.vb2_buf.index); /* Check if this is the buffer we're looking for */ mfc_debug(2, "NAL Q: buf addr: 0x%08llx, disp addr: 0x%08llx\n", - ref_mb->addr[0], dspl_y_addr); + ref_mb->addr[0][0], dspl_y_addr); index = ref_mb->vb.vb2_buf.index; diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_opr.c b/drivers/media/platform/exynos/mfc/s5p_mfc_opr.c index 07d1223275fe..cea014465a05 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_opr.c @@ -62,7 +62,7 @@ int s5p_mfc_run_dec_init(struct s5p_mfc_ctx *ctx) 0, src_mb->vb.vb2_buf.planes[0].bytesused); } - mfc_debug(2, "Header addr: 0x%08llx\n", src_mb->addr[0]); + mfc_debug(2, "Header addr: 0x%08llx\n", src_mb->addr[0][0]); s5p_mfc_clean_ctx_int_flags(ctx); s5p_mfc_init_decode(ctx); @@ -235,7 +235,7 @@ int s5p_mfc_run_enc_init(struct s5p_mfc_ctx *ctx) s5p_mfc_set_enc_stride(ctx); - mfc_debug(2, "Header addr: 0x%08llx\n", dst_mb->addr[0]); + mfc_debug(2, "Header addr: 0x%08llx\n", dst_mb->addr[0][0]); s5p_mfc_clean_ctx_int_flags(ctx); ret = s5p_mfc_init_encode(ctx); @@ -259,7 +259,13 @@ int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) return -EAGAIN; } - last_frame = mfc_check_last_frame(ctx, src_mb); + if (IS_BUFFER_BATCH_MODE(ctx)) { + /* last image in a buffer container */ + if (src_mb->next_index == (ctx->num_bufs_in_vb - 1)) + last_frame = mfc_check_last_frame(ctx, src_mb); + } else { + last_frame = mfc_check_last_frame(ctx, src_mb); + } index = src_mb->vb.vb2_buf.index; diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_queue.c b/drivers/media/platform/exynos/mfc/s5p_mfc_queue.c index 235dd2637187..2d326a83dea9 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_queue.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_queue.c @@ -56,7 +56,7 @@ int s5p_mfc_peek_buf_csd(spinlock_t *plock, struct s5p_mfc_buf_queue *queue) csd = mfc_buf->vb.reserved2 & FLAG_CSD ? 1 : 0; mfc_debug(2, "mfc_buf: 0x%p\n", mfc_buf); - mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0]); + mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0][0]); spin_unlock_irqrestore(plock, flags); return csd; @@ -82,7 +82,7 @@ struct s5p_mfc_buf *s5p_mfc_get_buf(spinlock_t *plock, struct s5p_mfc_buf_queue mfc_buf->used = used; mfc_debug(2, "mfc_buf: 0x%p\n", mfc_buf); - mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0]); + mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0][0]); spin_unlock_irqrestore(plock, flags); return mfc_buf; @@ -108,7 +108,7 @@ struct s5p_mfc_buf *s5p_mfc_get_del_buf(spinlock_t *plock, struct s5p_mfc_buf_qu mfc_buf->used = used; mfc_debug(2, "mfc_buf: 0x%p\n", mfc_buf); - mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0]); + mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0][0]); list_del(&mfc_buf->list); queue->count--; @@ -135,7 +135,7 @@ struct s5p_mfc_buf *s5p_mfc_get_del_if_consumed(spinlock_t *plock, struct s5p_mf mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list); mfc_debug(2, "mfc_buf: 0x%p\n", mfc_buf); - mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0]); + mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0][0]); remained = (unsigned int)(mfc_buf->vb.vb2_buf.planes[0].bytesused - consumed); @@ -178,7 +178,7 @@ struct s5p_mfc_buf *s5p_mfc_get_move_buf(spinlock_t *plock, mfc_buf->used = used; mfc_debug(2, "mfc_buf: 0x%p\n", mfc_buf); - mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0]); + mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0][0]); list_del(&mfc_buf->list); from_queue->count--; @@ -212,7 +212,7 @@ struct s5p_mfc_buf *s5p_mfc_get_move_buf_used(spinlock_t *plock, if (mfc_buf->used) { mfc_debug(2, "mfc_buf: 0x%p\n", mfc_buf); - mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0]); + mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0][0]); list_del(&mfc_buf->list); from_queue->count--; @@ -245,8 +245,9 @@ struct s5p_mfc_buf *s5p_mfc_get_move_buf_addr(spinlock_t *plock, mfc_buf = list_entry(from_queue->head.next, struct s5p_mfc_buf, list); - if (mfc_buf->addr[0] == addr) { - mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0]); + if (mfc_buf->addr[0][0] == addr) { + mfc_debug(2, "mfc_buf: 0x%p\n", mfc_buf); + mfc_debug(2, "First plane address: 0x%08llx\n", mfc_buf->addr[0][0]); list_del(&mfc_buf->list); from_queue->count--; @@ -262,18 +263,35 @@ struct s5p_mfc_buf *s5p_mfc_get_move_buf_addr(spinlock_t *plock, } } -struct s5p_mfc_buf *s5p_mfc_find_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue, - dma_addr_t addr) +struct s5p_mfc_buf *s5p_mfc_find_first_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue, + dma_addr_t addr, int search_queue) { unsigned long flags; struct s5p_mfc_buf *mfc_buf = NULL; dma_addr_t mb_addr; + int i; spin_lock_irqsave(plock, flags); + if (list_empty(&queue->head)) { + mfc_debug(2, "queue is empty\n"); + spin_unlock_irqrestore(plock, flags); + return mfc_buf; + } + mfc_debug(2, "Looking for this address: 0x%08llx\n", addr); - list_for_each_entry(mfc_buf, &queue->head, list) { - mb_addr = mfc_buf->addr[0]; + mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list); + if (search_queue > 0) { + for (i = 0; i < search_queue; i++) { + mb_addr = mfc_buf->addr[i][0]; + mfc_debug(2, "batch buf[%d] plane[0] addr: 0x%08llx\n", i, mb_addr); + if (addr == mb_addr) { + spin_unlock_irqrestore(plock, flags); + return mfc_buf; + } + } + } else { + mb_addr = mfc_buf->addr[0][0]; mfc_debug(2, "plane[0] addr: 0x%08llx\n", mb_addr); if (addr == mb_addr) { @@ -286,24 +304,75 @@ struct s5p_mfc_buf *s5p_mfc_find_buf(spinlock_t *plock, struct s5p_mfc_buf_queue return NULL; } +struct s5p_mfc_buf *s5p_mfc_find_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue, + dma_addr_t addr, int search_queue) +{ + unsigned long flags; + struct s5p_mfc_buf *mfc_buf = NULL; + dma_addr_t mb_addr; + int i; + + spin_lock_irqsave(plock, flags); + + mfc_debug(2, "Looking for this address: 0x%08llx\n", addr); + list_for_each_entry(mfc_buf, &queue->head, list) { + if (search_queue > 0) { + for (i = 0; i < search_queue; i++) { + mb_addr = mfc_buf->addr[i][0]; + mfc_debug(2, "batch buf[%d] plane[0] addr: 0x%08llx\n", i, mb_addr); + if (addr == mb_addr) { + spin_unlock_irqrestore(plock, flags); + return mfc_buf; + } + } + } else { + mb_addr = mfc_buf->addr[0][0]; + mfc_debug(2, "plane[0] addr: 0x%08llx\n", mb_addr); + + if (addr == mb_addr) { + spin_unlock_irqrestore(plock, flags); + return mfc_buf; + } + } + } + + spin_unlock_irqrestore(plock, flags); + return NULL; +} + struct s5p_mfc_buf *s5p_mfc_find_del_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue, - dma_addr_t addr) + dma_addr_t addr, int search_queue) { unsigned long flags; struct s5p_mfc_buf *mfc_buf = NULL; dma_addr_t mb_addr; - int found = 0; + int found = 0, i; spin_lock_irqsave(plock, flags); mfc_debug(2, "Looking for this address: 0x%08llx\n", addr); list_for_each_entry(mfc_buf, &queue->head, list) { - mb_addr = mfc_buf->addr[0]; - mfc_debug(2, "plane[0] addr: 0x%08llx\n", mb_addr); + if (search_queue > 0) { + for (i = 0; i < search_queue; i++) { + mb_addr = mfc_buf->addr[i][0]; + mfc_debug(2, "batch buf[%d] plane[0] addr: 0x%08llx\n", i, mb_addr); + + if (addr == mb_addr) { + found = 1; + break; + } + } - if (addr == mb_addr) { - found = 1; - break; + if (found) + break; + } else { + mb_addr = mfc_buf->addr[0][0]; + mfc_debug(2, "plane[0] addr: 0x%08llx\n", mb_addr); + + if (addr == mb_addr) { + found = 1; + break; + } } } @@ -332,7 +401,7 @@ struct s5p_mfc_buf *s5p_mfc_find_move_buf(spinlock_t *plock, mfc_debug(2, "Looking for this address: 0x%08llx\n", addr); list_for_each_entry(mfc_buf, &from_queue->head, list) { - mb_addr = mfc_buf->addr[0]; + mb_addr = mfc_buf->addr[0][0]; mfc_debug(2, "plane[0] addr: 0x%08llx\n", mb_addr); if (addr == mb_addr) { @@ -371,7 +440,7 @@ struct s5p_mfc_buf *s5p_mfc_find_move_buf_used(spinlock_t *plock, mfc_debug(2, "Looking for this address: 0x%08llx\n", addr); list_for_each_entry(mfc_buf, &from_queue->head, list) { - mb_addr = mfc_buf->addr[0]; + mb_addr = mfc_buf->addr[0][0]; mfc_debug(2, "plane[0] addr: 0x%08llx, used: %d\n", mb_addr, mfc_buf->used); @@ -900,7 +969,7 @@ int s5p_mfc_is_last_frame(struct s5p_mfc_ctx *ctx) src_mb = list_entry(ctx->src_buf_queue.head.next, struct s5p_mfc_buf, list); mfc_debug(2, "mfc_buf: 0x%p\n", src_mb); - mfc_debug(2, "First plane address: 0x%08llx\n", src_mb->addr[0]); + mfc_debug(2, "First plane address: 0x%08llx\n", src_mb->addr[0][0]); if (src_mb->vb.reserved2 & FLAG_LAST_FRAME) { mfc_debug(2, "last frame!\n"); diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_queue.h b/drivers/media/platform/exynos/mfc/s5p_mfc_queue.h index d6dadedc22dc..02a25b2947ad 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_queue.h +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_queue.h @@ -122,10 +122,12 @@ struct s5p_mfc_buf *s5p_mfc_get_move_buf_addr(spinlock_t *plock, struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue, dma_addr_t addr); +struct s5p_mfc_buf *s5p_mfc_find_first_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue, + dma_addr_t addr, int search_queue); struct s5p_mfc_buf *s5p_mfc_find_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue, - dma_addr_t addr); + dma_addr_t addr, int search_queue); struct s5p_mfc_buf *s5p_mfc_find_del_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue, - dma_addr_t addr); + dma_addr_t addr, int search_queue); struct s5p_mfc_buf *s5p_mfc_find_move_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue, dma_addr_t addr, unsigned int released_flag); diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c b/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c index 29b9e60b073b..84dac78172dd 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c @@ -310,7 +310,7 @@ int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *m cpb_buf_size = ALIGN(dec->src_buf_size, STREAM_BUF_ALIGN); if (mfc_buf) { - addr = mfc_buf->addr[0]; + addr = mfc_buf->addr[0][0]; if (strm_size > set_strm_size_max(cpb_buf_size)) { mfc_info_ctx("Decrease strm_size because of %d align: %u -> %u\n", STREAM_BUF_ALIGN, strm_size, set_strm_size_max(cpb_buf_size)); @@ -348,16 +348,29 @@ void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx, { struct s5p_mfc_dev *dev = ctx->dev; dma_addr_t addr[3] = { 0, 0, 0 }; - dma_addr_t addr_2bit[2]; + dma_addr_t addr_2bit[2] = { 0, 0 }; int i; - if (mfc_buf) { + if (!mfc_buf) { + mfc_debug(3, "enc zero buffer set\n"); + goto buffer_set; + } + + if (IS_BUFFER_BATCH_MODE(ctx)) { + for (i = 0; i < num_planes; i++) { + addr[i] = mfc_buf->addr[mfc_buf->next_index][i]; + mfc_debug(2, "enc batch buf[%d] src[%d] addr: 0x%08llx\n", + mfc_buf->next_index, i, addr[i]); + } + mfc_buf->next_index++; + } else { for (i = 0; i < num_planes; i++) { - addr[i] = mfc_buf->addr[i]; + addr[i] = mfc_buf->addr[0][i]; mfc_debug(2, "enc src[%d] addr: 0x%08llx\n", i, addr[i]); } } +buffer_set: for (i = 0; i < num_planes; i++) MFC_WRITEL(addr[i], S5P_FIMV_E_SOURCE_FIRST_ADDR + (i * 4)); @@ -386,7 +399,7 @@ int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx, dma_addr_t addr; unsigned int size, offset; - addr = mfc_buf->addr[0]; + addr = mfc_buf->addr[0][0]; offset = mfc_buf->vb.vb2_buf.planes[0].data_offset; size = (unsigned int)vb2_plane_size(&mfc_buf->vb.vb2_buf, 0); size = ALIGN(size, 512); @@ -445,13 +458,13 @@ int s5p_mfc_set_dynamic_dpb(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *dst_mb) set_bit(dst_index, &dec->available_dpb); dec->dynamic_set = 1 << dst_index; mfc_debug(2, "ADDING Flag after: 0x%lx\n", dec->available_dpb); - mfc_debug(2, "Dst addr [%d] = 0x%08llx\n", dst_index, dst_mb->addr[0]); + mfc_debug(2, "Dst addr [%d] = 0x%08llx\n", dst_index, dst_mb->addr[0][0]); /* for debugging about black bar detection */ if (FW_HAS_BLACK_BAR_DETECT(dev) && dec->detect_black_bar) { for (i = 0; i < raw->num_planes; i++) { dec->frame_vaddr[i][dec->frame_cnt] = vb2_plane_vaddr(&dst_mb->vb.vb2_buf, i); - dec->frame_daddr[i][dec->frame_cnt] = dst_mb->addr[i]; + dec->frame_daddr[i][dec->frame_cnt] = dst_mb->addr[0][i]; dec->frame_size[i][dec->frame_cnt] = raw->plane_size[i]; dec->index[i][dec->frame_cnt] = dst_index; dec->fd[i][dec->frame_cnt] = dst_mb->vb.vb2_buf.planes[0].m.fd; @@ -467,12 +480,12 @@ int s5p_mfc_set_dynamic_dpb(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *dst_mb) for (i = 0; i < raw->num_planes; i++) { MFC_WRITEL(raw->plane_size[i], S5P_FIMV_D_FIRST_PLANE_DPB_SIZE + i*4); - MFC_WRITEL(dst_mb->addr[i], + MFC_WRITEL(dst_mb->addr[0][i], S5P_FIMV_D_FIRST_PLANE_DPB0 + (i*0x100 + dst_index*4)); } MFC_TRACE_CTX("Set dst[%d] fd: %d, %#llx / avail %#lx used %#x\n", - dst_index, dst_mb->vb.vb2_buf.planes[0].m.fd, dst_mb->addr[0], + dst_index, dst_mb->vb.vb2_buf.planes[0].m.fd, dst_mb->addr[0][0], dec->available_dpb, dec->dynamic_used); return 0; -- 2.20.1