diff options
Diffstat (limited to 'drv-media-cedrus-hevc-Improve-buffer-management.patch')
-rw-r--r-- | drv-media-cedrus-hevc-Improve-buffer-management.patch | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/drv-media-cedrus-hevc-Improve-buffer-management.patch b/drv-media-cedrus-hevc-Improve-buffer-management.patch new file mode 100644 index 000000000000..42ccc693d012 --- /dev/null +++ b/drv-media-cedrus-hevc-Improve-buffer-management.patch @@ -0,0 +1,245 @@ +From e5464070b7b15a21dc9bc133734f95a45d0c58e4 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec <jernej.skrabec@siol.net> +Date: Sat, 9 Nov 2019 13:22:05 +0100 +Subject: [PATCH 049/101] drv:media:cedrus: hevc: Improve buffer management + +Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net> +--- + drivers/staging/media/sunxi/cedrus/cedrus.h | 9 +- + .../staging/media/sunxi/cedrus/cedrus_h265.c | 119 ++++++++++-------- + 2 files changed, 70 insertions(+), 58 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h +index 35faf42f2..6ddcff8f5 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -106,6 +106,11 @@ struct cedrus_buffer { + unsigned int position; + enum cedrus_h264_pic_type pic_type; + } h264; ++ struct { ++ void *mv_col_buf; ++ dma_addr_t mv_col_buf_dma; ++ ssize_t mv_col_buf_size; ++ } h265; + } codec; + }; + +@@ -139,10 +144,6 @@ struct cedrus_ctx { + ssize_t intra_pred_buf_size; + } h264; + struct { +- void *mv_col_buf; +- dma_addr_t mv_col_buf_addr; +- ssize_t mv_col_buf_size; +- ssize_t mv_col_buf_unit_size; + void *neighbor_info_buf; + dma_addr_t neighbor_info_buf_addr; + void *entry_points_buf; +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index 4fa5016a2..3d7f87a80 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -91,26 +91,66 @@ static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data, + + static inline dma_addr_t + cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx, +- unsigned int index, unsigned int field) ++ unsigned int index, ++ const struct v4l2_ctrl_hevc_sps *sps) + { +- return ctx->codec.h265.mv_col_buf_addr + index * +- ctx->codec.h265.mv_col_buf_unit_size + +- field * ctx->codec.h265.mv_col_buf_unit_size / 2; ++ struct cedrus_buffer *cedrus_buf = NULL; ++ struct vb2_buffer *buf = NULL; ++ struct vb2_queue *vq; ++ ++ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ if (vq) ++ buf = vb2_get_buffer(vq, index); ++ ++ if (buf) ++ cedrus_buf = vb2_to_cedrus_buffer(buf); ++ ++ if (!cedrus_buf) ++ return 0; ++ ++ if (!cedrus_buf->codec.h265.mv_col_buf_size) { ++ unsigned int ctb_size_luma, width_in_ctb_luma; ++ unsigned int log2_max_luma_coding_block_size; ++ ++ log2_max_luma_coding_block_size = ++ sps->log2_min_luma_coding_block_size_minus3 + 3 + ++ sps->log2_diff_max_min_luma_coding_block_size; ++ ctb_size_luma = 1 << log2_max_luma_coding_block_size; ++ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, ++ ctb_size_luma); ++ ++ cedrus_buf->codec.h265.mv_col_buf_size = ALIGN(width_in_ctb_luma * ++ DIV_ROUND_UP(sps->pic_height_in_luma_samples, ctb_size_luma) * ++ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE, 1024); ++ ++ cedrus_buf->codec.h265.mv_col_buf = ++ dma_alloc_attrs(ctx->dev->dev, ++ cedrus_buf->codec.h265.mv_col_buf_size, ++ &cedrus_buf->codec.h265.mv_col_buf_dma, ++ GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING); ++ ++ if (!cedrus_buf->codec.h265.mv_col_buf) { ++ cedrus_buf->codec.h265.mv_col_buf_size = 0; ++ cedrus_buf->codec.h265.mv_col_buf_dma = 0; ++ } ++ } ++ ++ return cedrus_buf->codec.h265.mv_col_buf_dma; + } + + static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, + unsigned int index, + bool field_pic, + u32 pic_order_cnt[], +- int buffer_index) ++ int buffer_index, ++ const struct v4l2_ctrl_hevc_sps *sps) + { + struct cedrus_dev *dev = ctx->dev; + dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 0); + dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 1); + dma_addr_t mv_col_buf_addr[2] = { +- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, 0), +- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, +- field_pic ? 1 : 0) ++ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, sps), ++ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, sps) + }; + u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO + + VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index; +@@ -134,7 +174,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, + + static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx, + const struct v4l2_hevc_dpb_entry *dpb, +- u8 num_active_dpb_entries) ++ u8 num_active_dpb_entries, ++ const struct v4l2_ctrl_hevc_sps *sps) + { + struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, + V4L2_BUF_TYPE_VIDEO_CAPTURE); +@@ -149,7 +190,7 @@ static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx, + + cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic, + pic_order_cnt, +- buffer_index); ++ buffer_index, sps); + } + } + +@@ -388,37 +388,6 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + width_in_ctb_luma = + DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma); + +- /* MV column buffer size and allocation. */ +- if (!ctx->codec.h265.mv_col_buf_size) { +- unsigned int num_buffers = +- run->dst->vb2_buf.vb2_queue->num_buffers; +- +- /* +- * Each CTB requires a MV col buffer with a specific unit size. +- * Since the address is given with missing lsb bits, 1 KiB is +- * added to each buffer to ensure proper alignment. +- */ +- ctx->codec.h265.mv_col_buf_unit_size = +- DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) * +- DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) * +- CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K; +- +- ctx->codec.h265.mv_col_buf_size = num_buffers * +- ctx->codec.h265.mv_col_buf_unit_size; +- +- /* Buffer is never accessed by CPU, so we can skip kernel mapping. */ +- ctx->codec.h265.mv_col_buf = +- dma_alloc_attrs(dev->dev, +- ctx->codec.h265.mv_col_buf_size, +- &ctx->codec.h265.mv_col_buf_addr, +- GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING); +- if (!ctx->codec.h265.mv_col_buf) { +- ctx->codec.h265.mv_col_buf_size = 0; +- // TODO: Abort the process here. +- return; +- } +- } +- + /* Activate H265 engine. */ + cedrus_engine_enable(ctx, CEDRUS_CODEC_H265); + +@@ -671,7 +682,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + + /* Write decoded picture buffer in pic list. */ + cedrus_h265_frame_info_write_dpb(ctx, decode_params->dpb, +- decode_params->num_active_dpb_entries); ++ decode_params->num_active_dpb_entries, sps); + + /* Output frame. */ + +@@ -682,7 +693,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + cedrus_h265_frame_info_write_single(ctx, output_pic_list_index, + slice_params->pic_struct != 0, + pic_order_cnt, +- run->dst->vb2_buf.index); ++ run->dst->vb2_buf.index, sps); + + cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index); + +@@ -732,9 +701,6 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx) + { + struct cedrus_dev *dev = ctx->dev; + +- /* The buffer size is calculated at setup time. */ +- ctx->codec.h265.mv_col_buf_size = 0; +- + /* Buffer is never accessed by CPU, so we can skip kernel mapping. */ + ctx->codec.h265.neighbor_info_buf = + dma_alloc_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, +@@ -759,15 +767,6 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx) + { + struct cedrus_dev *dev = ctx->dev; + +- if (ctx->codec.h265.mv_col_buf_size > 0) { +- dma_free_attrs(dev->dev, ctx->codec.h265.mv_col_buf_size, +- ctx->codec.h265.mv_col_buf, +- ctx->codec.h265.mv_col_buf_addr, +- DMA_ATTR_NO_KERNEL_MAPPING); +- +- ctx->codec.h265.mv_col_buf_size = 0; +- } +- + dma_free_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h265.neighbor_info_buf, + ctx->codec.h265.neighbor_info_buf_addr, +@@ -784,6 +783,17 @@ static void cedrus_h265_trigger(struct cedrus_ctx *ctx) + cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE); + } + ++static void cedrus_h265_buf_cleanup(struct cedrus_ctx *ctx, ++ struct cedrus_buffer *buf) ++{ ++ if (buf->codec.h265.mv_col_buf_size) ++ dma_free_attrs(ctx->dev->dev, ++ buf->codec.h265.mv_col_buf_size, ++ buf->codec.h265.mv_col_buf, ++ buf->codec.h265.mv_col_buf_dma, ++ DMA_ATTR_NO_KERNEL_MAPPING); ++} ++ + struct cedrus_dec_ops cedrus_dec_ops_h265 = { + .irq_clear = cedrus_h265_irq_clear, + .irq_disable = cedrus_h265_irq_disable, +@@ -792,4 +802,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h265 = { + .start = cedrus_h265_start, + .stop = cedrus_h265_stop, + .trigger = cedrus_h265_trigger, ++ .buf_cleanup = cedrus_h265_buf_cleanup, + }; +-- +2.31.1 + |