mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
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:
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user