video: rockchip: mpp: change the way to refresh the dma cache

Signed-off-by: Yandong Lin <yandong.lin@rock-chips.com>
Change-Id: I0a929cb896069d7bc4a782f19e2fde4de5dc58db
This commit is contained in:
Yandong Lin
2023-02-16 10:17:41 +08:00
parent 9cd6a5c06d
commit 3fb2e28edd
4 changed files with 79 additions and 49 deletions

View File

@@ -11,6 +11,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dma-buf-cache.h> #include <linux/dma-buf-cache.h>
#include <linux/dma-iommu.h> #include <linux/dma-iommu.h>
#include <linux/dma-mapping.h>
#include <linux/iommu.h> #include <linux/iommu.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
@@ -27,7 +28,7 @@
#include "mpp_iommu.h" #include "mpp_iommu.h"
#include "mpp_common.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) mpp_dma_find_buffer_fd(struct mpp_dma_session *dma, int fd)
{ {
struct dma_buf *dmabuf; struct dma_buf *dmabuf;
@@ -374,6 +375,49 @@ mpp_dma_session_create(struct device *dev, u32 max_buffers)
return dma; 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) int mpp_iommu_detach(struct mpp_iommu_info *info)
{ {
if (!info) if (!info)

View File

@@ -103,6 +103,9 @@ int mpp_dma_unmap_kernel(struct mpp_dma_session *dma,
struct mpp_dma_buffer *buffer); struct mpp_dma_buffer *buffer);
int mpp_dma_map_kernel(struct mpp_dma_session *dma, int mpp_dma_map_kernel(struct mpp_dma_session *dma,
struct mpp_dma_buffer *buffer); 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 * struct mpp_iommu_info *
mpp_iommu_probe(struct device *dev); mpp_iommu_probe(struct device *dev);

View File

@@ -228,7 +228,7 @@ struct rkvenc_task {
DECLARE_KFIFO(slice_info, union rkvenc2_slice_len_info, RKVENC_MAX_SLICE_FIFO_LEN); DECLARE_KFIFO(slice_info, union rkvenc2_slice_len_info, RKVENC_MAX_SLICE_FIFO_LEN);
/* jpege bitstream */ /* jpege bitstream */
struct dma_buf *dmabuf_bs; struct mpp_dma_buffer *bs_buf;
u32 offset_bs; u32 offset_bs;
}; };
@@ -915,6 +915,7 @@ static void *rkvenc_alloc_task(struct mpp_session *session,
u32 off; u32 off;
const u16 *tbl; const u16 *tbl;
struct rkvenc_hw_info *hw = task->hw_info; struct rkvenc_hw_info *hw = task->hw_info;
int fd_bs = -1;
for (i = 0; i < hw->fd_class; i++) { for (i = 0; i < hw->fd_class; i++) {
u32 class = hw->fd_reg[i].class; u32 class = hw->fd_reg[i].class;
@@ -925,22 +926,13 @@ static void *rkvenc_alloc_task(struct mpp_session *session,
if (!reg) if (!reg)
continue; continue;
if (fmt == RKVENC_FMT_JPEGE && class == RKVENC_CLASS_PIC && if (fmt == RKVENC_FMT_JPEGE && class == RKVENC_CLASS_PIC && fd_bs == -1) {
!task->dmabuf_bs) { int bs_index;
int bs_fd, bs_index;
struct dma_buf *dmabuf_bs;
bs_index = mpp->var->trans_info[fmt].table[2]; 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, task->offset_bs = mpp_query_reg_offset_info(&task->off_inf,
bs_index + ss); 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); 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; 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); rkvenc2_setup_task_id(session->index, task);
task->clk_mode = CLK_MODE_NORMAL; task->clk_mode = CLK_MODE_NORMAL;
@@ -965,11 +968,6 @@ static void *rkvenc_alloc_task(struct mpp_session *session,
return mpp_task; return mpp_task;
fail: 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_mem_region(mpp, mpp_task);
mpp_task_dump_reg(mpp, mpp_task); mpp_task_dump_reg(mpp, mpp_task);
mpp_task_finalize(session, 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); u32 bs_size = mpp_read(mpp, 0x4064);
dma_buf_begin_cpu_access_partial(task->dmabuf_bs, DMA_FROM_DEVICE, 0, mpp_dma_buf_sync(task->bs_buf, 0, bs_size / 8 + task->offset_bs,
bs_size / 8 + task->offset_bs); DMA_FROM_DEVICE, true);
} }
/* revert hack for irq status */ /* 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); 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); mpp_task_finalize(session, mpp_task);
rkvenc_free_class_msg(task); rkvenc_free_class_msg(task);
kfree(task); kfree(task);

View File

@@ -99,7 +99,7 @@ struct vepu_task {
u32 width; u32 width;
u32 height; u32 height;
u32 pixels; u32 pixels;
struct dma_buf *dmabuf_bs; struct mpp_dma_buffer *bs_buf;
u32 offset_bs; u32 offset_bs;
}; };
@@ -200,17 +200,14 @@ static int vepu_process_reg_fd(struct mpp_session *session,
&task->off_inf, task->reg); &task->off_inf, task->reg);
if (fmt == VEPU2_FMT_JPEGE) { 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->offset_bs = mpp_query_reg_offset_info(&task->off_inf, VEPU2_REG_OUT_INDEX);
if (bs_buf && task->offset_bs > 0) {
task->dmabuf_bs = dma_buf_get(fd_bs); mpp_dma_buf_sync(bs_buf, 0, task->offset_bs, DMA_TO_DEVICE, false);
task->bs_buf = bs_buf;
if (IS_ERR_OR_NULL(task->dmabuf_bs)) {
task->dmabuf_bs = NULL;
return 0;
} }
if (task->offset_bs > 0)
dma_buf_end_cpu_access_partial(task->dmabuf_bs, DMA_TO_DEVICE, 0,
task->offset_bs);
} }
return 0; return 0;
@@ -484,6 +481,11 @@ static int vepu_finish(struct mpp_dev *mpp,
/* revert hack for irq status */ /* revert hack for irq status */
task->reg[VEPU2_REG_INT_INDEX] = task->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(); mpp_debug_leave();
return 0; 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; return 0;
} }
@@ -522,12 +519,6 @@ static int vepu_free_task(struct mpp_session *session,
{ {
struct vepu_task *task = to_vepu_task(mpp_task); 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); mpp_task_finalize(session, mpp_task);
kfree(task); kfree(task);