From 72fd43ac08fd262884ba913625575ac277e32ce3 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Thu, 10 Sep 2020 14:26:08 +0800 Subject: [PATCH] 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 Change-Id: Ic929d3d4e5c1d23fae542481ca90ab6ba1680e0e --- drivers/video/rockchip/rga2/rga2.h | 1 + drivers/video/rockchip/rga2/rga2_drv.c | 1 + drivers/video/rockchip/rga2/rga2_mmu_info.c | 160 ++++++++++++++++++-- drivers/video/rockchip/rga2/rga2_mmu_info.h | 9 ++ 4 files changed, 157 insertions(+), 14 deletions(-) diff --git a/drivers/video/rockchip/rga2/rga2.h b/drivers/video/rockchip/rga2/rga2.h index 17776f1ce2d4..05b7e8a15480 100644 --- a/drivers/video/rockchip/rga2/rga2.h +++ b/drivers/video/rockchip/rga2/rga2.h @@ -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; diff --git a/drivers/video/rockchip/rga2/rga2_drv.c b/drivers/video/rockchip/rga2/rga2_drv.c index b9b79ab1a0aa..1953d5bf3bdb 100644 --- a/drivers/video/rockchip/rga2/rga2_drv.c +++ b/drivers/video/rockchip/rga2/rga2_drv.c @@ -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__); diff --git a/drivers/video/rockchip/rga2/rga2_mmu_info.c b/drivers/video/rockchip/rga2/rga2_mmu_info.c index 4d88f6169f58..9b16b540ad09 100644 --- a/drivers/video/rockchip/rga2/rga2_mmu_info.c +++ b/drivers/video/rockchip/rga2/rga2_mmu_info.c @@ -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(¤t->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); diff --git a/drivers/video/rockchip/rga2/rga2_mmu_info.h b/drivers/video/rockchip/rga2/rga2_mmu_info.h index 644b10444bb2..36e386c62caf 100644 --- a/drivers/video/rockchip/rga2/rga2_mmu_info.h +++ b/drivers/video/rockchip/rga2/rga2_mmu_info.h @@ -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);