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/dma-buf-cache.h>
#include <linux/dma-iommu.h>
#include <linux/dma-mapping.h>
#include <linux/iommu.h>
#include <linux/of.h>
#include <linux/of_platform.h>
@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);