diff --git a/drivers/media/common/codec_mm/codec_mm.c b/drivers/media/common/codec_mm/codec_mm.c index 141faf979..ee8aabb73 100644 --- a/drivers/media/common/codec_mm/codec_mm.c +++ b/drivers/media/common/codec_mm/codec_mm.c @@ -718,17 +718,22 @@ static void *codec_mm_search_vaddr(unsigned long phy_addr) return vaddr; } -u8 *codec_mm_vmap(ulong addr, u32 size) +static u8 *__codec_mm_vmap(ulong addr, u32 size, bool is_cache) { u8 *vaddr = NULL; struct page **pages = NULL; u32 i, npages, offset = 0; ulong phys, page_start; pgprot_t pgprot = PAGE_KERNEL; + ulong vm_flags = VM_MAP; - if (!PageHighMem(phys_to_page(addr))) + if (!PageHighMem(phys_to_page(addr)) && is_cache) return phys_to_virt(addr); + if (!is_cache) { /* remap for noncached. */ + pgprot = pgprot_dmacoherent(PAGE_KERNEL); + vm_flags = VM_DMA_COHERENT; + } offset = offset_in_page(addr); page_start = addr - offset; npages = DIV_ROUND_UP(size + offset, PAGE_SIZE); @@ -742,7 +747,7 @@ u8 *codec_mm_vmap(ulong addr, u32 size) pages[i] = pfn_to_page(phys >> PAGE_SHIFT); } - vaddr = vmap(pages, npages, VM_MAP, pgprot); + vaddr = vmap(pages, npages, vm_flags, pgprot); if (!vaddr) { pr_err("the phy(%lx) vmaped fail, size: %d\n", page_start, npages << PAGE_SHIFT); @@ -753,15 +758,26 @@ u8 *codec_mm_vmap(ulong addr, u32 size) kfree(pages); if (debug_mode & 0x20) { - pr_info("[HIGH-MEM-MAP] %s, pa(%lx) to va(%lx), size: %d\n", + pr_info("[VMAP] %s, pa(%lx) to va(%lx), size: %d, cache:%d\n", __func__, page_start, (ulong)vaddr, - npages << PAGE_SHIFT); + npages << PAGE_SHIFT, is_cache); } return vaddr + offset; } + +u8 *codec_mm_vmap(ulong addr, u32 size) +{ + return __codec_mm_vmap(addr, size, true); +} EXPORT_SYMBOL(codec_mm_vmap); +u8 *codec_mm_vmap_noncache(ulong addr, u32 size) +{ + return __codec_mm_vmap(addr, size, false); +} +EXPORT_SYMBOL(codec_mm_vmap_noncache); + void codec_mm_memset(ulong phys, u32 val, u32 size) { void *ptr = NULL; @@ -900,6 +916,10 @@ static int codec_mm_alloc_in(struct codec_mm_mgt_s *mgt, struct codec_mm_s *mem) if (mem->mem_handle) { mem->vbuffer = mem->mem_handle; mem->phy_addr = virt_to_phys(mem->mem_handle); + dma_sync_single_for_device(mgt->dev, + mem->phy_addr, + PAGE_ALIGN(mem->buffer_size), + DMA_FROM_DEVICE); break; } try_alloced_from_sys = 1; @@ -917,9 +937,14 @@ static int codec_mm_alloc_in(struct codec_mm_mgt_s *mgt, struct codec_mm_s *mem) PAGE_SHIFT, false); mem->from_flags = AMPORTS_MEM_FLAGS_FROM_GET_FROM_CMA; if (mem->mem_handle) { - mem->vbuffer = mem->mem_handle; mem->phy_addr = - page_to_phys((struct page *)mem->mem_handle); + page_to_phys((struct page *)mem->mem_handle); + if (!mgt->tvp_enable) { + dma_sync_single_for_device(mgt->dev, + mem->phy_addr, + mem->page_count << PAGE_SHIFT, + DMA_FROM_DEVICE); + } #ifdef CONFIG_ARM64 if (mem->flags & CODEC_MM_FLAGS_CMA_CLEAR) { /*dma_clear_buffer((struct page *)*/ @@ -997,9 +1022,12 @@ static int codec_mm_alloc_in(struct codec_mm_mgt_s *mgt, struct codec_mm_s *mem) page_to_phys((struct page *) mem->mem_handle); - if (mem->flags & CODEC_MM_FLAGS_CPU) - mem->vbuffer = - codec_mm_map_phyaddr(mem); + if (!mgt->tvp_enable) { + dma_sync_single_for_device(mgt->dev, + mem->phy_addr, + mem->page_count << PAGE_SHIFT, + DMA_FROM_DEVICE); + } #ifdef CONFIG_ARM64 if (mem->flags & CODEC_MM_FLAGS_CMA_CLEAR) { /*dma_clear_buffer((struct page *)*/ @@ -1065,6 +1093,10 @@ static int codec_mm_alloc_in(struct codec_mm_mgt_s *mgt, struct codec_mm_s *mem) mem->vbuffer = mem->mem_handle; mem->phy_addr = virt_to_phys((void *)mem->mem_handle); + dma_sync_single_for_device(mgt->dev, + mem->phy_addr, + PAGE_ALIGN(mem->buffer_size), + DMA_FROM_DEVICE); break; } } diff --git a/drivers/media/common/codec_mm/codec_mm_scatter.c b/drivers/media/common/codec_mm/codec_mm_scatter.c index 09f4177ed..b921e80ac 100644 --- a/drivers/media/common/codec_mm/codec_mm_scatter.c +++ b/drivers/media/common/codec_mm/codec_mm_scatter.c @@ -834,6 +834,11 @@ codec_mm_slot_alloc(struct codec_mm_scatter_mgt *smgt, int size, int flags) slot->page_num = 1 << page_order; slot->phy_addr = virt_to_phys((unsigned long *)slot->page_header); + /* Invalidate range of cache lines. */ + dma_sync_single_for_device(smgt->dev, + slot->phy_addr, + (slot->page_num * PAGE_SIZE), + DMA_FROM_DEVICE); codec_mm_slot_init_bitmap(slot); if (!slot->pagemap) { free_pages(slot->page_header, page_order); diff --git a/include/linux/amlogic/media/codec_mm/codec_mm.h b/include/linux/amlogic/media/codec_mm/codec_mm.h index 7758d007a..05feb20f7 100644 --- a/include/linux/amlogic/media/codec_mm/codec_mm.h +++ b/include/linux/amlogic/media/codec_mm/codec_mm.h @@ -144,6 +144,7 @@ int codec_mm_free_for_dma(const char *owner, unsigned long phy_addr); void *codec_mm_phys_to_virt(unsigned long phy_addr); unsigned long codec_mm_virt_to_phys(void *vaddr); u8 *codec_mm_vmap(ulong addr, u32 size); +u8 *codec_mm_vmap_noncache(ulong addr, u32 size); void codec_mm_unmap_phyaddr(u8 *vaddr); void codec_mm_dma_flush(void *vaddr, int size, enum dma_data_direction dir);