From 3fb2e28edd06d378e59b84a544e0e7483953a8a5 Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Thu, 16 Feb 2023 10:17:41 +0800 Subject: [PATCH] video: rockchip: mpp: change the way to refresh the dma cache Signed-off-by: Yandong Lin Change-Id: I0a929cb896069d7bc4a782f19e2fde4de5dc58db --- drivers/video/rockchip/mpp/mpp_iommu.c | 46 +++++++++++++++++++++++- drivers/video/rockchip/mpp/mpp_iommu.h | 3 ++ drivers/video/rockchip/mpp/mpp_rkvenc2.c | 46 ++++++++++-------------- drivers/video/rockchip/mpp/mpp_vepu2.c | 33 +++++++---------- 4 files changed, 79 insertions(+), 49 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_iommu.c b/drivers/video/rockchip/mpp/mpp_iommu.c index 5ba44f54f5fe..612813bf615d 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.c +++ b/drivers/video/rockchip/mpp/mpp_iommu.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -27,7 +28,7 @@ #include "mpp_iommu.h" #include "mpp_common.h" -static struct mpp_dma_buffer * +struct mpp_dma_buffer * mpp_dma_find_buffer_fd(struct mpp_dma_session *dma, int fd) { struct dma_buf *dmabuf; @@ -374,6 +375,49 @@ mpp_dma_session_create(struct device *dev, u32 max_buffers) return dma; } +/* + * begin cpu access => for_cpu = true + * end cpu access => for_cpu = false + */ +void mpp_dma_buf_sync(struct mpp_dma_buffer *buffer, u32 offset, u32 length, + enum dma_data_direction dir, bool for_cpu) +{ + struct scatterlist *sg; + unsigned int len = 0; + dma_addr_t sg_dma_addr; + int i; + struct sg_table *sgt = buffer->sgt; + struct device *dev = buffer->dma->dev; + + for_each_sgtable_sg(sgt, sg, i) { + unsigned int sg_offset, sg_left, size = 0; + + sg_dma_addr = sg_dma_address(sg); + + len += sg->length; + if (len <= offset) + continue; + + sg_left = len - offset; + sg_offset = sg->length - sg_left; + + size = (length < sg_left) ? length : sg_left; + + if (for_cpu) + dma_sync_single_range_for_cpu(dev, sg_dma_addr, + sg_offset, size, dir); + else + dma_sync_single_range_for_device(dev, sg_dma_addr, + sg_offset, size, dir); + + offset += size; + length -= size; + + if (length == 0) + break; + } +} + int mpp_iommu_detach(struct mpp_iommu_info *info) { if (!info) diff --git a/drivers/video/rockchip/mpp/mpp_iommu.h b/drivers/video/rockchip/mpp/mpp_iommu.h index 4419741e5fb0..12c2044d6318 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.h +++ b/drivers/video/rockchip/mpp/mpp_iommu.h @@ -103,6 +103,9 @@ int mpp_dma_unmap_kernel(struct mpp_dma_session *dma, struct mpp_dma_buffer *buffer); int mpp_dma_map_kernel(struct mpp_dma_session *dma, struct mpp_dma_buffer *buffer); +struct mpp_dma_buffer *mpp_dma_find_buffer_fd(struct mpp_dma_session *dma, int fd); +void mpp_dma_buf_sync(struct mpp_dma_buffer *buffer, u32 offset, u32 length, + enum dma_data_direction dir, bool for_cpu); struct mpp_iommu_info * mpp_iommu_probe(struct device *dev); diff --git a/drivers/video/rockchip/mpp/mpp_rkvenc2.c b/drivers/video/rockchip/mpp/mpp_rkvenc2.c index 4d911088f215..4a808f32074e 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvenc2.c +++ b/drivers/video/rockchip/mpp/mpp_rkvenc2.c @@ -228,7 +228,7 @@ struct rkvenc_task { DECLARE_KFIFO(slice_info, union rkvenc2_slice_len_info, RKVENC_MAX_SLICE_FIFO_LEN); /* jpege bitstream */ - struct dma_buf *dmabuf_bs; + struct mpp_dma_buffer *bs_buf; u32 offset_bs; }; @@ -915,6 +915,7 @@ static void *rkvenc_alloc_task(struct mpp_session *session, u32 off; const u16 *tbl; struct rkvenc_hw_info *hw = task->hw_info; + int fd_bs = -1; for (i = 0; i < hw->fd_class; i++) { u32 class = hw->fd_reg[i].class; @@ -925,22 +926,13 @@ static void *rkvenc_alloc_task(struct mpp_session *session, if (!reg) continue; - if (fmt == RKVENC_FMT_JPEGE && class == RKVENC_CLASS_PIC && - !task->dmabuf_bs) { - int bs_fd, bs_index; - struct dma_buf *dmabuf_bs; + if (fmt == RKVENC_FMT_JPEGE && class == RKVENC_CLASS_PIC && fd_bs == -1) { + int bs_index; bs_index = mpp->var->trans_info[fmt].table[2]; - bs_fd = reg[bs_index]; + fd_bs = reg[bs_index]; task->offset_bs = mpp_query_reg_offset_info(&task->off_inf, bs_index + ss); - dmabuf_bs = dma_buf_get(bs_fd); - if (!IS_ERR(dmabuf_bs)) { - dma_buf_end_cpu_access_partial(dmabuf_bs, - DMA_TO_DEVICE, - 0, task->offset_bs); - task->dmabuf_bs = dmabuf_bs; - } } ret = mpp_translate_reg_address(session, mpp_task, fmt, reg, NULL); @@ -955,6 +947,17 @@ static void *rkvenc_alloc_task(struct mpp_session *session, reg[tbl[j]] += off; } } + + if (fd_bs >= 0) { + struct mpp_dma_buffer *bs_buf = + mpp_dma_find_buffer_fd(session->dma, fd_bs); + + if (bs_buf && task->offset_bs > 0) { + mpp_dma_buf_sync(bs_buf, 0, task->offset_bs, + DMA_TO_DEVICE, false); + task->bs_buf = bs_buf; + } + } } rkvenc2_setup_task_id(session->index, task); task->clk_mode = CLK_MODE_NORMAL; @@ -965,11 +968,6 @@ static void *rkvenc_alloc_task(struct mpp_session *session, return mpp_task; fail: - if (task->dmabuf_bs) { - dma_buf_put(task->dmabuf_bs); - task->dmabuf_bs = NULL; - task->offset_bs = 0; - } mpp_task_dump_mem_region(mpp, mpp_task); mpp_task_dump_reg(mpp, mpp_task); mpp_task_finalize(session, mpp_task); @@ -1408,11 +1406,11 @@ static int rkvenc_finish(struct mpp_dev *mpp, struct mpp_task *mpp_task) } - if (task->dmabuf_bs) { + if (task->bs_buf) { u32 bs_size = mpp_read(mpp, 0x4064); - dma_buf_begin_cpu_access_partial(task->dmabuf_bs, DMA_FROM_DEVICE, 0, - bs_size / 8 + task->offset_bs); + mpp_dma_buf_sync(task->bs_buf, 0, bs_size / 8 + task->offset_bs, + DMA_FROM_DEVICE, true); } /* revert hack for irq status */ @@ -1456,12 +1454,6 @@ static int rkvenc_free_task(struct mpp_session *session, { struct rkvenc_task *task = to_rkvenc_task(mpp_task); - if (task->dmabuf_bs) { - dma_buf_put(task->dmabuf_bs); - task->dmabuf_bs = NULL; - task->offset_bs = 0; - } - mpp_task_finalize(session, mpp_task); rkvenc_free_class_msg(task); kfree(task); diff --git a/drivers/video/rockchip/mpp/mpp_vepu2.c b/drivers/video/rockchip/mpp/mpp_vepu2.c index d87f7788dbc0..acb1dc0dbfe3 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu2.c +++ b/drivers/video/rockchip/mpp/mpp_vepu2.c @@ -99,7 +99,7 @@ struct vepu_task { u32 width; u32 height; u32 pixels; - struct dma_buf *dmabuf_bs; + struct mpp_dma_buffer *bs_buf; u32 offset_bs; }; @@ -200,17 +200,14 @@ static int vepu_process_reg_fd(struct mpp_session *session, &task->off_inf, task->reg); if (fmt == VEPU2_FMT_JPEGE) { + struct mpp_dma_buffer *bs_buf = mpp_dma_find_buffer_fd(session->dma, fd_bs); + task->offset_bs = mpp_query_reg_offset_info(&task->off_inf, VEPU2_REG_OUT_INDEX); - - task->dmabuf_bs = dma_buf_get(fd_bs); - - if (IS_ERR_OR_NULL(task->dmabuf_bs)) { - task->dmabuf_bs = NULL; - return 0; + if (bs_buf && task->offset_bs > 0) { + mpp_dma_buf_sync(bs_buf, 0, task->offset_bs, DMA_TO_DEVICE, false); + task->bs_buf = bs_buf; } - if (task->offset_bs > 0) - dma_buf_end_cpu_access_partial(task->dmabuf_bs, DMA_TO_DEVICE, 0, - task->offset_bs); + } return 0; @@ -484,6 +481,11 @@ static int vepu_finish(struct mpp_dev *mpp, /* revert hack for irq status */ task->reg[VEPU2_REG_INT_INDEX] = task->irq_status; + if (task->bs_buf) + mpp_dma_buf_sync(task->bs_buf, 0, + task->reg[VEPU2_REG_STRM_INDEX] / 8 + + task->offset_bs, + DMA_FROM_DEVICE, true); mpp_debug_leave(); return 0; @@ -509,11 +511,6 @@ static int vepu_result(struct mpp_dev *mpp, } } - if (task->dmabuf_bs) - dma_buf_begin_cpu_access_partial(task->dmabuf_bs, DMA_FROM_DEVICE, 0, - task->reg[VEPU2_REG_STRM_INDEX] / 8 + - task->offset_bs); - return 0; } @@ -522,12 +519,6 @@ static int vepu_free_task(struct mpp_session *session, { struct vepu_task *task = to_vepu_task(mpp_task); - if (task->dmabuf_bs) { - dma_buf_put(task->dmabuf_bs); - task->dmabuf_bs = NULL; - task->offset_bs = 0; - } - mpp_task_finalize(session, mpp_task); kfree(task);