video/rockchip: rga2: Add invalidate cache.

Use dma_map_page/dma_unmap_page to flush cache.Users
need to call rga2_blit_flush_cache() to flush cache
according to their needs.

Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
Change-Id: Ic929d3d4e5c1d23fae542481ca90ab6ba1680e0e
This commit is contained in:
Yu Qiaowei
2020-09-10 14:26:08 +08:00
committed by Tao Huang
parent 4637222e90
commit 72fd43ac08
4 changed files with 157 additions and 14 deletions

View File

@@ -682,6 +682,7 @@ struct rga2_reg {
uint32_t *MMU_base;
uint32_t MMU_len;
bool MMU_map;
struct sg_table *sg_src0;
struct sg_table *sg_src1;

View File

@@ -1417,6 +1417,7 @@ static int rga2_blit_flush_cache(rga2_session *session, struct rga2_req *req)
#endif
if ((req->mmu_info.src0_mmu_flag & 1) || (req->mmu_info.src1_mmu_flag & 1) ||
(req->mmu_info.dst_mmu_flag & 1) || (req->mmu_info.els_mmu_flag & 1)) {
reg->MMU_map = true;
ret = rga2_set_mmu_info(reg, req);
if (ret < 0) {
pr_err("%s, [%d] set mmu info error\n", __func__, __LINE__);

View File

@@ -43,13 +43,47 @@ void rga2_dma_flush_range(void *pstart, void *pend)
dma_sync_single_for_device(rga2_drvdata->dev, virt_to_phys(pstart), pend - pstart, DMA_TO_DEVICE);
}
static void rga2_dma_flush_page(struct page *page)
static void rga2_dma_flush_page(struct page *page, int map)
{
phys_addr_t paddr;
dma_addr_t paddr;
paddr = page_to_phys(page);
dma_sync_single_for_device(rga2_drvdata->dev, paddr, PAGE_SIZE, DMA_TO_DEVICE);
if (map & MMU_MAP_MASK) {
switch (map) {
case MMU_MAP_CLEAN:
dma_map_page(rga2_drvdata->dev, page, 0,
PAGE_SIZE, DMA_TO_DEVICE);
break;
case MMU_MAP_INVALID:
dma_map_page(rga2_drvdata->dev, page, 0,
PAGE_SIZE, DMA_FROM_DEVICE);
break;
case MMU_MAP_CLEAN | MMU_MAP_INVALID:
dma_map_page(rga2_drvdata->dev, page, 0,
PAGE_SIZE, DMA_TO_DEVICE);
dma_map_page(rga2_drvdata->dev, page, 0,
PAGE_SIZE, DMA_FROM_DEVICE);
break;
}
} else if (map & MMU_UNMAP_MASK) {
switch (map) {
case MMU_UNMAP_CLEAN:
dma_unmap_page(rga2_drvdata->dev, paddr,
PAGE_SIZE, DMA_TO_DEVICE);
break;
case MMU_UNMAP_INVALID:
dma_unmap_page(rga2_drvdata->dev, paddr,
PAGE_SIZE, DMA_FROM_DEVICE);
break;
case MMU_UNMAP_CLEAN | MMU_UNMAP_INVALID:
dma_unmap_page(rga2_drvdata->dev, paddr,
PAGE_SIZE, DMA_TO_DEVICE);
dma_unmap_page(rga2_drvdata->dev, paddr,
PAGE_SIZE, DMA_FROM_DEVICE);
break;
}
}
}
#if 0
@@ -382,7 +416,7 @@ static int rga2_UserMemory_cheeck(struct page **pages, u32 w, u32 h, u32 format,
static int rga2_MapUserMemory(struct page **pages, uint32_t *pageTable,
unsigned long Memory, uint32_t pageCount,
int writeFlag)
int writeFlag, int map)
{
struct vm_area_struct *vma;
int32_t result;
@@ -417,7 +451,7 @@ static int rga2_MapUserMemory(struct page **pages, uint32_t *pageTable,
for (i = 0; i < pageCount; i++) {
/* Get the physical address from page struct. */
pageTable[i] = page_to_phys(pages[i]);
rga2_dma_flush_page(pages[i]);
rga2_dma_flush_page(pages[i], map);
}
for (i = 0; i < result; i++)
put_page(pages[i]);
@@ -465,7 +499,7 @@ static int rga2_MapUserMemory(struct page **pages, uint32_t *pageTable,
Address = ((pfn << PAGE_SHIFT) | (((unsigned long)((Memory + i)
<< PAGE_SHIFT)) & ~PAGE_MASK));
pageTable[i] = (uint32_t)Address;
rga2_dma_flush_page(pfn_to_page(pfn));
rga2_dma_flush_page(pfn_to_page(pfn), map);
pte_unmap_unlock(pte, ptl);
}
up_read(&current->mm->mmap_sem);
@@ -508,6 +542,80 @@ static int rga2_MapION(struct sg_table *sg,
return 0;
}
static int rga2_mmu_flush_cache(struct rga2_reg *reg, struct rga2_req *req)
{
int DstMemSize;
unsigned long DstStart, DstPageCount;
uint32_t *MMU_Base, *MMU_Base_phys;
int ret;
int status;
struct page **pages = NULL;
MMU_Base = NULL;
DstMemSize = 0;
DstPageCount = 0;
DstStart = 0;
if (reg->MMU_map != true)
goto out;
/* cal dst buf mmu info */
if (req->mmu_info.dst_mmu_flag & 1) {
DstPageCount = rga2_buf_size_cal(req->dst.yrgb_addr,
req->dst.uv_addr,
req->dst.v_addr,
req->dst.format,
req->dst.vir_w,
req->dst.vir_h,
&DstStart);
if (DstPageCount == 0)
return -EINVAL;
}
/* Cal out the needed mem size */
DstMemSize = (DstPageCount + 15) & (~15);
if (rga2_mmu_buf_get_try(&rga2_mmu_buf, DstMemSize)) {
pr_err("RGA2 Get MMU mem failed\n");
status = RGA2_MALLOC_ERROR;
goto out;
}
pages = rga2_mmu_buf.pages;
mutex_lock(&rga2_service.lock);
MMU_Base = rga2_mmu_buf.buf_virtual +
(rga2_mmu_buf.front & (rga2_mmu_buf.size - 1));
MMU_Base_phys = rga2_mmu_buf.buf +
(rga2_mmu_buf.front & (rga2_mmu_buf.size - 1));
mutex_unlock(&rga2_service.lock);
if (DstMemSize) {
if (req->sg_dst) {
goto out;
} else {
ret = rga2_MapUserMemory(&pages[0],
MMU_Base,
DstStart, DstPageCount, 1,
MMU_MAP_CLEAN | MMU_MAP_INVALID);
#if RGA2_DEBUGFS
if (RGA2_CHECK_MODE)
rga2_UserMemory_cheeck(&pages[0],
req->dst.vir_w,
req->dst.vir_h,
req->dst.format,
2);
#endif
}
if (ret < 0) {
pr_err("rga2 unmap dst memory failed\n");
status = ret;
goto out;
}
}
rga2_mmu_buf_get(&rga2_mmu_buf, DstMemSize);
reg->MMU_len = DstMemSize;
status = 0;
out:
return status;
}
static int rga2_mmu_info_BitBlt_mode(struct rga2_reg *reg, struct rga2_req *req)
{
@@ -593,7 +701,8 @@ static int rga2_mmu_info_BitBlt_mode(struct rga2_reg *reg, struct rga2_req *req)
&MMU_Base[0], Src0MemSize);
} else {
ret = rga2_MapUserMemory(&pages[0], &MMU_Base[0],
Src0Start, Src0PageCount, 0);
Src0Start, Src0PageCount,
0, MMU_MAP_CLEAN);
#if RGA2_DEBUGFS
if (RGA2_CHECK_MODE)
rga2_UserMemory_cheeck(&pages[0], req->src.vir_w,
@@ -627,7 +736,8 @@ static int rga2_mmu_info_BitBlt_mode(struct rga2_reg *reg, struct rga2_req *req)
else
ret = rga2_MapUserMemory(&pages[0],
MMU_Base + Src0MemSize,
Src1Start, Src1PageCount, 0);
Src1Start, Src1PageCount,
0, MMU_MAP_CLEAN);
if (ret < 0) {
pr_err("rga2 map src1 memory failed\n");
status = ret;
@@ -642,10 +752,25 @@ static int rga2_mmu_info_BitBlt_mode(struct rga2_reg *reg, struct rga2_req *req)
if (req->sg_dst) {
ret = rga2_MapION(req->sg_dst, MMU_Base + Src0MemSize
+ Src1MemSize, DstMemSize);
} else if (req->alpha_mode_0 != 0 && req->bitblt_mode == 0) {
/* The blend mode of src + dst => dst requires clean and invalidate */
ret = rga2_MapUserMemory(&pages[0], MMU_Base
+ Src0MemSize + Src1MemSize,
DstStart, DstPageCount, 1,
MMU_MAP_CLEAN | MMU_MAP_INVALID);
#if RGA2_DEBUGFS
if (RGA2_CHECK_MODE)
rga2_UserMemory_cheeck(&pages[0],
req->src.vir_w,
req->src.vir_h,
req->src.format,
2);
#endif
} else {
ret = rga2_MapUserMemory(&pages[0], MMU_Base
+ Src0MemSize + Src1MemSize,
DstStart, DstPageCount, 1);
DstStart, DstPageCount,
1, MMU_MAP_INVALID);
#if RGA2_DEBUGFS
if (RGA2_CHECK_MODE)
rga2_UserMemory_cheeck(&pages[0], req->src.vir_w,
@@ -761,7 +886,7 @@ static int rga2_mmu_info_color_palette_mode(struct rga2_reg *reg, struct rga2_re
&MMU_Base[0], SrcMemSize);
} else {
ret = rga2_MapUserMemory(&pages[0], &MMU_Base[0],
SrcStart, SrcMemSize, 0);
SrcStart, SrcMemSize, 0, MMU_MAP_CLEAN);
#if RGA2_DEBUGFS
if (RGA2_CHECK_MODE)
rga2_UserMemory_cheeck(&pages[0], req->src.vir_w,
@@ -786,7 +911,7 @@ static int rga2_mmu_info_color_palette_mode(struct rga2_reg *reg, struct rga2_re
MMU_Base + SrcMemSize, DstMemSize);
} else {
ret = rga2_MapUserMemory(&pages[0], MMU_Base + SrcMemSize,
DstStart, DstMemSize, 1);
DstStart, DstMemSize, 1, MMU_MAP_INVALID);
#if RGA2_DEBUGFS
if (RGA2_CHECK_MODE)
rga2_UserMemory_cheeck(&pages[0], req->dst.vir_w,
@@ -860,7 +985,8 @@ static int rga2_mmu_info_color_fill_mode(struct rga2_reg *reg, struct rga2_req *
}
else {
ret = rga2_MapUserMemory(&pages[0], &MMU_Base[0],
DstStart, DstMemSize, 1);
DstStart, DstMemSize,
1, MMU_MAP_INVALID);
}
if (ret < 0) {
pr_err("rga2 map dst memory failed\n");
@@ -940,7 +1066,7 @@ static int rga2_mmu_info_update_palette_table_mode(struct rga2_reg *reg, struct
&MMU_Base[0], LutMemSize);
} else {
ret = rga2_MapUserMemory(&pages[0], &MMU_Base[0],
LutStart, LutMemSize, 0);
LutStart, LutMemSize, 0, MMU_MAP_CLEAN);
}
if (ret < 0) {
pr_err("rga2 map palette memory failed\n");
@@ -1005,7 +1131,8 @@ static int rga2_mmu_info_update_patten_buff_mode(struct rga2_reg *reg, struct rg
{
ret = rga2_MapUserMemory(&pages[CMDMemSize],
&MMU_Base[CMDMemSize],
SrcStart, SrcMemSize, 1);
SrcStart, SrcMemSize,
1, MMU_MAP_CLEAN);
if (ret < 0) {
pr_err("rga map src memory failed\n");
status = ret;
@@ -1047,6 +1174,11 @@ int rga2_set_mmu_info(struct rga2_reg *reg, struct rga2_req *req)
{
int ret;
if (reg->MMU_map == true) {
ret = rga2_mmu_flush_cache(reg, req);
return ret;
}
switch (req->render_mode) {
case bitblt_mode :
ret = rga2_mmu_info_BitBlt_mode(reg, req);

View File

@@ -15,6 +15,15 @@
extern struct rga2_drvdata_t *rga2_drvdata;
enum {
MMU_MAP_CLEAN = 1 << 0,
MMU_MAP_INVALID = 1 << 1,
MMU_MAP_MASK = 0x03,
MMU_UNMAP_CLEAN = 1 << 2,
MMU_UNMAP_INVALID = 1 << 3,
MMU_UNMAP_MASK = 0x0c,
};
int rga2_set_mmu_info(struct rga2_reg *reg, struct rga2_req *req);
void rga2_dma_flush_range(void *pstart, void *pend);