vdin: fixed the issue of mem mapping from vmap. [1/1]
authorNanxin Qin <nanxin.qin@amlogic.com>
Thu, 28 Mar 2019 15:43:08 +0000 (23:43 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Thu, 4 Apr 2019 02:24:36 +0000 (19:24 -0700)
PD#SWPL-6196

Problem:
the memory issue cause to kernel crash.

Solution:
1. add flush cache when the mem oper end.
2. unmap addr which from vmap in vdin driver.

Verify:
X301

Change-Id: Id6efe2b009fe64ad753d51eb06784bd4e66f5e87
Signed-off-by: Nanxin Qin <nanxin.qin@amlogic.com>
drivers/amlogic/media/video_processor/pic_dev/picdec.c
drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c
drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c
drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h
drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c
drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c

index 7d28ea3..451718b 100644 (file)
@@ -778,6 +778,7 @@ static int picdec_memset_phyaddr(ulong phys, u32 size, u32 val)
                if (!p)
                        return -1;
                memset(p, val, span);
+               codec_mm_dma_flush(p, span, DMA_TO_DEVICE);
                codec_mm_unmap_phyaddr(p);
        }
        return 0;
@@ -887,6 +888,7 @@ static int copy_phybuf_to_file(ulong phys, u32 size,
                p = codec_mm_vmap(addr, span);
                if (!p)
                        return -1;
+               codec_mm_dma_flush(p, span, DMA_FROM_DEVICE);
                vfs_write(fp, (char *)p,
                        span, &pos);
                pos += span;
index aa29b32..eecaea5 100644 (file)
@@ -580,6 +580,7 @@ void vdin_afbce_maptable_init(struct vdin_dev_s *devp)
        unsigned int *vtable = NULL;
        unsigned int body;
        unsigned int size;
+       void *p = NULL;
 
        size = roundup(devp->afbce_info->frame_body_size, 4096);
 
@@ -599,19 +600,40 @@ void vdin_afbce_maptable_init(struct vdin_dev_s *devp)
                        else
                                vtable = phys_to_virt(ptable);
                } else {
-                       vtable = (unsigned int *)codec_mm_vmap(
-                               ptable,
+                       vtable = (unsigned int *)vdin_vmap(ptable,
                                devp->afbce_info->frame_table_size);
+                       if (vdin_dbg_en) {
+                               pr_err("----vdin vmap v: %p, p: %lx, size: %d\n",
+                                       vtable, ptable,
+                                       devp->afbce_info->frame_table_size);
+                       }
+                       if (!vtable) {
+                               pr_err("vmap fail, size: %d.\n",
+                                       devp->afbce_info->frame_table_size);
+                               return;
+                       }
+
                }
 
+               p = vtable;
                body = devp->afbce_info->fm_body_paddr[i]&0xffffffff;
                for (j = 0; j < size; j += 4096) {
                        *vtable = ((j + body) >> 12) & 0x000fffff;
                        vtable++;
                }
 
+               /* clean tail data. */
+               memset(vtable, 0, devp->afbce_info->frame_table_size -
+                               ((char *)vtable - (char *)p));
+
+               vdin_dma_flush(devp, p,
+                       devp->afbce_info->frame_table_size,
+                       DMA_TO_DEVICE);
+
                if (highmem_flag)
-                       codec_mm_unmap_phyaddr((void *)vtable);
+                       vdin_unmap_phyaddr(p);
+
+               vtable = NULL;
        }
 }
 
index 47435be..f551ce0 100644 (file)
@@ -23,6 +23,9 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/highmem.h>
+#include <linux/page-flags.h>
+#include <linux/vmalloc.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-contiguous.h>
 #include <linux/amlogic/media/video_sink/video.h>
@@ -160,6 +163,79 @@ static unsigned int vpu_reg_27af = 0x3;
 #define pr_info(fmt, ...)
 #endif
 
+u8 *vdin_vmap(ulong addr, u32 size)
+{
+       u8 *vaddr = NULL;
+       struct page **pages = NULL;
+       u32 i, npages, offset = 0;
+       ulong phys, page_start;
+       /*pgprot_t pgprot = pgprot_noncached(PAGE_KERNEL);*/
+       pgprot_t pgprot = PAGE_KERNEL;
+
+       if (!PageHighMem(phys_to_page(addr)))
+               return phys_to_virt(addr);
+
+       offset = offset_in_page(addr);
+       page_start = addr - offset;
+       npages = DIV_ROUND_UP(size + offset, PAGE_SIZE);
+
+       pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
+       if (!pages)
+               return NULL;
+
+       for (i = 0; i < npages; i++) {
+               phys = page_start + i * PAGE_SIZE;
+               pages[i] = pfn_to_page(phys >> PAGE_SHIFT);
+       }
+
+       vaddr = vmap(pages, npages, VM_MAP, pgprot);
+       if (!vaddr) {
+               pr_err("the phy(%lx) vmaped fail, size: %d\n",
+                       page_start, npages << PAGE_SHIFT);
+               kfree(pages);
+               return NULL;
+       }
+
+       kfree(pages);
+
+       if (vdin_dbg_en) {
+               pr_info("[vdin HIGH-MEM-MAP] %s, pa(%lx) to va(%p), size: %d\n",
+                       __func__, page_start, vaddr, npages << PAGE_SHIFT);
+       }
+
+       return vaddr + offset;
+}
+
+void vdin_unmap_phyaddr(u8 *vaddr)
+{
+       void *addr = (void *)(PAGE_MASK & (ulong)vaddr);
+
+       if (is_vmalloc_or_module_addr(vaddr)) {
+               if (vdin_dbg_en)
+                       pr_info("----vdin unmap v: %p\n", addr);
+               vunmap(addr);
+       }
+}
+
+void vdin_dma_flush(struct vdin_dev_s *devp, void *vaddr,
+               int size, enum dma_data_direction dir)
+{
+       ulong phy_addr;
+
+       if (is_vmalloc_or_module_addr(vaddr)) {
+               phy_addr = page_to_phys(vmalloc_to_page(vaddr))
+                       + offset_in_page(vaddr);
+               if (phy_addr && PageHighMem(phys_to_page(phy_addr))) {
+                       if (vdin_dbg_en)
+                               pr_info("----vdin flush v: %p, p: %lx\n",
+                                       vaddr, phy_addr);
+                       dma_sync_single_for_device(&devp->this_pdev->dev,
+                               phy_addr, size, dir);
+               }
+               return;
+       }
+}
+
 /*reset reg mif value of vdin0:
  *     VDIN_WR_CTRL \VDIN_COM_CTRL0\ VDIN_MISC_CTRL
  */
@@ -3550,12 +3626,12 @@ void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size)
                        if ((devp->cma_config_flag & 0x100)
                                && devp->cma_config_en)
                                devp->vfp->dv_buf_ori[index] =
-                                       codec_mm_vmap(devp->vfmem_start[index] +
+                                       vdin_vmap(devp->vfmem_start[index] +
                                        devp->vfmem_size-dolby_size_byte,
                                        dolby_size_byte);
                        else
                                devp->vfp->dv_buf_ori[index] =
-                                       codec_mm_vmap(devp->mem_start +
+                                       vdin_vmap(devp->mem_start +
                                        devp->mem_size -
                                        dolby_size_byte *
                                        (devp->canvas_max_num - index),
@@ -3572,15 +3648,32 @@ void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size)
 void vdin_dolby_addr_release(struct vdin_dev_s *devp, unsigned int size)
 {
        unsigned int alloc_size;
+       int highmem_flag;
+       int index;
 
        alloc_size = dolby_size_byte*size;
        if (devp->dv.dv_dma_vaddr)
                dma_free_coherent(&devp->this_pdev->dev, alloc_size,
                        devp->dv.dv_dma_vaddr, devp->dv.dv_dma_paddr);
        devp->dv.dv_dma_vaddr = NULL;
+
+       if (devp->cma_config_flag & 0x100)
+               highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0]));
+       else
+               highmem_flag = PageHighMem(phys_to_page(devp->mem_start));
+
+       if (highmem_flag) {
+               for (index = 0; index < size; index++) {
+                       if (devp->vfp->dv_buf_ori[index]) {
+                               vdin_unmap_phyaddr(
+                                       devp->vfp->dv_buf_ori[index]);
+                               devp->vfp->dv_buf_ori[index] = NULL;
+                       }
+               }
+       }
 }
 
-static void vdin_dolby_metadata_swap(char *buf)
+static void vdin_dolby_metadata_swap(struct vdin_dev_s *devp, char *buf)
 {
        char ext;
        unsigned int i, j;
@@ -3592,6 +3685,8 @@ static void vdin_dolby_metadata_swap(char *buf)
                        buf[i*16+15-j] = ext;
                }
        }
+
+       vdin_dma_flush(devp, buf, dolby_size_byte, DMA_TO_DEVICE);
 }
 
 #define swap32(num) \
@@ -3689,7 +3784,8 @@ void vdin_dolby_buffer_update(struct vdin_dev_s *devp, unsigned int index)
        for (count = 0; count < META_RETRY_MAX; count++) {
                if (dv_dbg_mask & DV_READ_MODE_AXI) {
                        memcpy(p, devp->vfp->dv_buf_vmem[index], 128);
-                       vdin_dolby_metadata_swap(c);
+                       vdin_dma_flush(devp, p, 128, DMA_TO_DEVICE);
+                       vdin_dolby_metadata_swap(devp, c);
                } else {
                        wr(offset, VDIN_DOLBY_DSC_CTRL3, 0);
                        wr(offset, VDIN_DOLBY_DSC_CTRL2, 0xd180c0d5);
@@ -3702,7 +3798,9 @@ void vdin_dolby_buffer_update(struct vdin_dev_s *devp, unsigned int index)
                        if ((i == 31) && (multimeta_flag == 0))
                                break;
                        }
+                       vdin_dma_flush(devp, p, 128, DMA_TO_DEVICE);
                }
+
                meta_size = (c[3] << 8) | c[4];
                crc = p[31];
                crc_result = crc32(0, p, 124);
index 178c74a..fcdf297 100644 (file)
 
 #ifndef __TVIN_VDIN_CTL_H
 #define __TVIN_VDIN_CTL_H
-
+#include <linux/highmem.h>
+#include <linux/page-flags.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
 #include "vdin_drv.h"
 
 #define DV_SWAP_EN     (1 << 0)
@@ -111,10 +115,16 @@ struct ldim_max_s {
 #endif
 
 extern unsigned int game_mode;
+extern bool vdin_dbg_en;
 
 /* ************************************************************************ */
 /* ******** GLOBAL FUNCTION CLAIM ******** */
 /* ************************************************************************ */
+extern u8 *vdin_vmap(ulong addr, u32 size);
+extern void vdin_unmap_phyaddr(u8 *vaddr);
+extern void vdin_dma_flush(struct vdin_dev_s *devp, void *vaddr,
+               int size, enum dma_data_direction dir);
+
 extern void vdin_set_vframe_prop_info(struct vframe_s *vf,
                struct vdin_dev_s *devp);
 extern void LDIM_Initial_2(int pic_h, int pic_v, int BLK_Vnum,
index 6798f88..f29067a 100644 (file)
@@ -343,14 +343,15 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp,
 
                for (j = 0; j < count; j++) {
                        highaddr = phys + j * devp->canvas_w;
-                       buf = codec_mm_vmap(highaddr, span);
+                       buf = vdin_vmap(highaddr, span);
                        if (!buf) {
-                               pr_info("codec_mm_vmap error\n");
+                               pr_info("vdin_vmap error\n");
                                return;
                        }
 
+                       vdin_dma_flush(devp, buf, span, DMA_FROM_DEVICE);
                        vfs_write(filp, buf, span, &pos);
-                       codec_mm_unmap_phyaddr(buf);
+                       vdin_unmap_phyaddr(buf);
                }
                pr_info("high-mem write buffer %2d of %2u to %s.\n",
                                buf_num, devp->canvas_max_num, path);
@@ -448,14 +449,16 @@ static void vdin_dump_mem(char *path, struct vdin_dev_s *devp)
 
                        for (j = 0; j < count; j++) {
                                highaddr = phys + j * devp->canvas_w;
-                               buf = codec_mm_vmap(highaddr, span);
+                               buf = vdin_vmap(highaddr, span);
                                if (!buf) {
-                                       pr_info("codec_mm_vmap error\n");
+                                       pr_info("vdin_vmap error\n");
                                        return;
                                }
 
+                               vdin_dma_flush(devp, buf, span,
+                                       DMA_FROM_DEVICE);
                                vfs_write(filp, buf, span, &pos);
-                               codec_mm_unmap_phyaddr(buf);
+                               vdin_unmap_phyaddr(buf);
                        }
                        pr_info("high-mem write buffer %2d of %2u to %s.\n",
                                        i, devp->canvas_max_num, path);
@@ -496,10 +499,8 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
                return;
        }
 
-       if (devp->cma_config_flag == 0x101)
-               highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0]));
-       else
-               highmem_flag = PageHighMem(phys_to_page(devp->mem_start));
+       highmem_flag = PageHighMem(
+               phys_to_page(devp->afbce_info->fm_body_paddr[0]));
 
        if (highmem_flag == 0) {
                /*low mem area*/
@@ -532,11 +533,11 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
        } else {
                /*high mem area*/
                pr_info("high mem area\n");
-               buf_head = codec_mm_vmap(
+               buf_head = vdin_vmap(
                        devp->afbce_info->fm_head_paddr[buf_num],
                        devp->afbce_info->frame_head_size);
 
-               buf_table = codec_mm_vmap(
+               buf_table = vdin_vmap(
                        devp->afbce_info->fm_table_paddr[buf_num],
                        devp->afbce_info->frame_table_size);
 
@@ -557,8 +558,12 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
                return;
        }
 
+       vdin_dma_flush(devp, buf_head,
+               devp->afbce_info->frame_head_size,
+               DMA_FROM_DEVICE);
        vfs_write(filp, buf_head, devp->afbce_info->frame_head_size, &pos);
-       codec_mm_unmap_phyaddr(buf_head);
+       if (highmem_flag)
+               vdin_unmap_phyaddr(buf_head);
        pr_info("write buffer %2d of %2u head to %s.\n",
                        buf_num, devp->canvas_max_num, buff);
        vfs_fsync(filp, 0);
@@ -573,8 +578,12 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
                pr_info("create %s table error.\n", buff);
                return;
        }
+       vdin_dma_flush(devp, buf_table,
+               devp->afbce_info->frame_table_size,
+               DMA_FROM_DEVICE);
        vfs_write(filp, buf_table, devp->afbce_info->frame_table_size, &pos);
-       codec_mm_unmap_phyaddr(buf_table);
+       if (highmem_flag)
+               vdin_unmap_phyaddr(buf_table);
        pr_info("write buffer %2d of %2u table to %s.\n",
                buf_num, devp->canvas_max_num, buff);
        vfs_fsync(filp, 0);
@@ -600,27 +609,29 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
 
                for (j = 0; j < count; j++) {
                        highaddr = phys + j * span;
-                       vbuf = codec_mm_vmap(highaddr, span);
+                       vbuf = vdin_vmap(highaddr, span);
                        if (!vbuf) {
-                               pr_info("codec_mm_vmap error\n");
+                               pr_info("vdin_vmap error\n");
                                return;
                        }
 
+                       vdin_dma_flush(devp, vbuf, span, DMA_FROM_DEVICE);
                        vfs_write(filp, vbuf, span, &pos);
-                       codec_mm_unmap_phyaddr(vbuf);
+                       vdin_unmap_phyaddr(vbuf);
                }
 
                if (remain) {
                        span = devp->afbce_info->frame_body_size - remain;
                        highaddr = phys + span;
-                       vbuf = codec_mm_vmap(highaddr, remain);
+                       vbuf = vdin_vmap(highaddr, remain);
                        if (!vbuf) {
-                               pr_info("codec_mm_vmap1 error\n");
+                               pr_info("vdin_vmap1 error\n");
                                return;
                        }
 
-                       vfs_write(filp, vbuf, span, &pos);
-                       codec_mm_unmap_phyaddr(vbuf);
+                       vdin_dma_flush(devp, vbuf, remain, DMA_FROM_DEVICE);
+                       vfs_write(filp, vbuf, remain, &pos);
+                       vdin_unmap_phyaddr(vbuf);
                }
        }
        pr_info("write buffer %2d of %2u body to %s.\n",
@@ -631,119 +642,6 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
        set_fs(old_fs);
 }
 
-static void vdin_dump_afbce_mem(char *path, struct vdin_dev_s *devp)
-{
-       struct file *filp = NULL;
-       loff_t pos = 0;
-       void *buf_head = NULL;
-       void *buf_table = NULL;
-       void *buf_body = NULL;
-       unsigned char buff[100];
-       unsigned int i;
-       mm_segment_t old_fs = get_fs();
-
-       if ((devp->cma_config_flag & 0x1) &&
-               (devp->cma_mem_alloc == 0)) {
-               pr_info("%s:no cma alloc mem!!!\n", __func__);
-               return;
-       }
-
-       if (devp->cma_config_flag == 0x101) {
-               buf_head = codec_mm_phys_to_virt(
-                       devp->afbce_info->head_paddr);
-               buf_table = codec_mm_phys_to_virt(
-                       devp->afbce_info->table_paddr);
-               buf_body = codec_mm_phys_to_virt(
-                       devp->afbce_info->fm_body_paddr[0]);
-
-               pr_info(".head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n",
-                       devp->afbce_info->head_paddr,
-                       (devp->afbce_info->table_paddr),
-                       devp->afbce_info->fm_body_paddr[0]);
-       } else if (devp->cma_config_flag == 0) {
-               buf_head = phys_to_virt(
-                       devp->afbce_info->head_paddr);
-               buf_table = phys_to_virt(
-                       devp->afbce_info->table_paddr);
-               buf_body = phys_to_virt(
-                       devp->afbce_info->fm_body_paddr[0]);
-
-               pr_info("head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n",
-                       devp->afbce_info->head_paddr,
-                       (devp->afbce_info->table_paddr),
-                       devp->afbce_info->fm_body_paddr[0]);
-       }
-
-       set_fs(KERNEL_DS);
-
-       /* write header bin start */
-       strcpy(buff, path);
-       strcat(buff, "_header.bin");
-       filp = filp_open(buff, O_RDWR|O_CREAT, 0666);
-       if (IS_ERR(filp)) {
-               pr_info("create %s header error.\n", buff);
-               return;
-       }
-
-       for (i = 0; i < devp->vfmem_max_cnt; i++) {
-               vfs_write(filp, buf_head,
-                       devp->afbce_info->frame_head_size, &pos);
-               buf_head += devp->afbce_info->frame_head_size;
-               pr_info("write buffer %2d(0x%x bytes) of %2u head to %s.\n",
-                       i, devp->afbce_info->frame_head_size,
-                       devp->canvas_max_num, buff);
-       }
-       vfs_fsync(filp, 0);
-       filp_close(filp, NULL);
-       /* write header bin end */
-
-       /* write table bin start */
-       pos = 0;
-       strcpy(buff, path);
-       strcat(buff, "_table.bin");
-       filp = filp_open(buff, O_RDWR|O_CREAT, 0666);
-       if (IS_ERR(filp)) {
-               pr_info("create %s table error.\n", buff);
-               return;
-       }
-
-       for (i = 0; i < devp->vfmem_max_cnt; i++) {
-               vfs_write(filp, buf_table,
-                       devp->afbce_info->frame_table_size, &pos);
-               buf_table += devp->afbce_info->frame_table_size;
-               pr_info("write buffer %2d(0x%x bytes) of %2u table to %s.\n",
-                       i, devp->afbce_info->frame_table_size,
-                       devp->canvas_max_num, buff);
-       }
-       vfs_fsync(filp, 0);
-       filp_close(filp, NULL);
-       /* write table bin end */
-
-       /* write body bin start */
-       pos = 0;
-       strcpy(buff, path);
-       strcat(buff, "_body.bin");
-       filp = filp_open(buff, O_RDWR|O_CREAT, 0666);
-       if (IS_ERR(filp)) {
-               pr_info("create %s body error.\n", buff);
-               return;
-       }
-
-       for (i = 0; i < devp->vfmem_max_cnt; i++) {
-               vfs_write(filp, buf_body,
-                       devp->afbce_info->frame_body_size, &pos);
-               buf_body += devp->afbce_info->frame_body_size;
-               pr_info("write buffer %2d(0x%x bytes) of %2u body to %s.\n",
-                       i, devp->afbce_info->frame_body_size,
-                       devp->canvas_max_num, buff);
-       }
-       vfs_fsync(filp, 0);
-       filp_close(filp, NULL);
-       /* write body bin end */
-
-       set_fs(old_fs);
-}
-
 static void dump_other_mem(char *path,
                unsigned int start, unsigned int offset)
 {
@@ -1101,21 +999,30 @@ static void vdin_dump_histgram(struct vdin_dev_s *devp)
 }
 
 /*type: 1:nv21 2:yuv422 3:yuv444*/
-static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type)
+static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type,
+               char *path)
 {
-       char *md_path_head = "/storage/B8F7-DBD0/afbce/a0_1header.bin";
-       char *md_path_body = "/storage/B8F7-DBD0/afbce/a0_1body.bin";
-       unsigned int i;
+       char md_path_head[100], md_path_body[100];
+       unsigned int i, j;
+       int highmem_flag = 0;
        unsigned int size = 0;
+       unsigned int span = 0;
+       unsigned int remain = 0;
+       unsigned int count = 0;
+       unsigned long highaddr;
+       unsigned long phys;
        long val;
        struct file *filp = NULL;
        loff_t pos = 0;
        mm_segment_t old_fs;
        void *head_dts = NULL;
        void *body_dts = NULL;
+       void *vbuf = NULL;
 
        if (kstrtol(type, 10, &val) < 0)
                return;
+       if (!path)
+               return;
 
        if (!devp->curr_wr_vfe) {
                devp->curr_wr_vfe = provider_vf_get(devp->vfp);
@@ -1125,6 +1032,9 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type)
                }
        }
 
+       sprintf(md_path_head, "%s_1header.bin", path);
+       sprintf(md_path_body, "%s_1body.bin", path);
+
        i = devp->curr_wr_vfe->af_num;
        devp->curr_wr_vfe->vf.type = VIDTYPE_VIU_SINGLE_PLANE |
                        VIDTYPE_VIU_FIELD | VIDTYPE_COMPRESS | VIDTYPE_SCATTER;
@@ -1146,8 +1056,18 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type)
        devp->curr_wr_vfe->vf.compHeadAddr = devp->afbce_info->fm_head_paddr[i];
        devp->curr_wr_vfe->vf.compBodyAddr = devp->afbce_info->fm_body_paddr[i];
 
-       head_dts = codec_mm_phys_to_virt(devp->afbce_info->fm_head_paddr[i]);
-       body_dts = codec_mm_phys_to_virt(devp->afbce_info->fm_body_paddr[i]);
+       highmem_flag = PageHighMem(
+               phys_to_page(devp->afbce_info->fm_body_paddr[0]));
+       if (highmem_flag == 0) {
+               pr_info("low mem area\n");
+               head_dts = codec_mm_phys_to_virt(
+                       devp->afbce_info->fm_head_paddr[i]);
+       } else {
+               pr_info("high mem area\n");
+               head_dts = vdin_vmap(
+                       devp->afbce_info->fm_head_paddr[i],
+                       devp->afbce_info->frame_head_size);
+       }
 
        old_fs = get_fs();
        set_fs(KERNEL_DS);
@@ -1160,6 +1080,8 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type)
 
        size = vfs_read(filp, head_dts,
                devp->afbce_info->frame_head_size, &pos);
+       if (highmem_flag)
+               vdin_unmap_phyaddr(head_dts);
 
        vfs_fsync(filp, 0);
        filp_close(filp, NULL);
@@ -1175,8 +1097,30 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type)
                return;
        }
 
-       size = vfs_read(filp, body_dts,
-               devp->afbce_info->frame_body_size, &pos);
+       if (highmem_flag == 0) {
+               body_dts = codec_mm_phys_to_virt(
+                       devp->afbce_info->fm_body_paddr[i]);
+
+               size = vfs_read(filp, body_dts,
+                       devp->afbce_info->frame_body_size, &pos);
+       } else {
+               span = SZ_1M;
+               count = devp->afbce_info->frame_body_size/PAGE_ALIGN(span);
+               remain = devp->afbce_info->frame_body_size%PAGE_ALIGN(span);
+               phys = devp->afbce_info->fm_body_paddr[i];
+
+
+               for (j = 0; j < count; j++) {
+                       highaddr = phys + j * span;
+                       vbuf = vdin_vmap(highaddr, span);
+                       if (!vbuf) {
+                               pr_info("vdin_vmap error\n");
+                               return;
+                       }
+                       vfs_read(filp, vbuf, span, &pos);
+                       vdin_unmap_phyaddr(vbuf);
+               }
+       }
 
        vfs_fsync(filp, 0);
        filp_close(filp, NULL);
@@ -1187,6 +1131,7 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type)
        vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY,
                        NULL);
 }
+
 static void vdin_write_mem(
        struct vdin_dev_s *devp, char *type,
        char *path, char *md_path)
@@ -1272,13 +1217,14 @@ static void vdin_write_mem(
                span = devp->canvas_active_w;
                for (j = 0; j < count; j++) {
                        highaddr = addr + j * devp->canvas_w;
-                       dts = codec_mm_vmap(highaddr, span);
+                       dts = vdin_vmap(highaddr, span);
                        if (!dts) {
-                               pr_info("codec_mm_vmap error\n");
+                               pr_info("vdin_vmap error\n");
                                return;
                        }
                        vfs_read(filp, dts, span, &pos);
-                       codec_mm_unmap_phyaddr(dts);
+                       vdin_dma_flush(devp, dts, span, DMA_TO_DEVICE);
+                       vdin_unmap_phyaddr(dts);
                }
                vfs_fsync(filp, 0);
                filp_close(filp, NULL);
@@ -1802,8 +1748,8 @@ start_chk:
        } else if (!strcmp(parm[0], "force_recycle")) {
                devp->flags |= VDIN_FLAG_FORCE_RECYCLE;
        } else if (!strcmp(parm[0], "read_pic_afbce")) {
-               if (parm[1])
-                       vdin_write_afbce_mem(devp, parm[1]);
+               if (parm[1] && parm[2])
+                       vdin_write_afbce_mem(devp, parm[1], parm[2]);
                else
                        pr_err("miss parameters.\n");
        } else if (!strcmp(parm[0], "read_pic")) {
@@ -2172,7 +2118,7 @@ start_chk:
                                buf_num = val;
                        vdin_dump_one_afbce_mem(parm[1], devp, buf_num);
                } else if (parm[1] != NULL) {
-                       vdin_dump_afbce_mem(parm[1], devp);
+                       vdin_dump_one_afbce_mem(parm[1], devp, 0);
                }
        } else {
                pr_info("unknown command\n");
index 52491bc..6bbc951 100644 (file)
@@ -135,7 +135,7 @@ MODULE_PARM_DESC(game_mode_phlock_switch_frames,
                "game mode switch <n> frames for phase_lock");
 #endif
 
-static bool vdin_dbg_en;
+bool vdin_dbg_en;
 module_param(vdin_dbg_en, bool, 0664);
 MODULE_PARM_DESC(vdin_dbg_en, "enable/disable vdin debug information");
 
@@ -642,14 +642,6 @@ void vdin_start_dec(struct vdin_dev_s *devp)
 #endif
                vf_notify_receiver(devp->name,
                        VFRAME_EVENT_PROVIDER_START, NULL);
-       if ((devp->parm.port != TVIN_PORT_VIU1) ||
-               (viu_hw_irq != 0)) {
-               /*enable irq */
-               enable_irq(devp->irq);
-               if (vdin_dbg_en)
-                       pr_info("****[%s]enable_irq ifdef VDIN_V2****\n",
-                                       __func__);
-       }
 
        if (vdin_dbg_en)
                pr_info("****[%s]ok!****\n", __func__);
@@ -675,7 +667,6 @@ void vdin_start_dec(struct vdin_dev_s *devp)
 
        if ((devp->afbce_mode == 1) && is_meson_tl1_cpu() &&
                (devp->h_active >= 1920) && (devp->v_active >= 1080)) {
-               spin_lock_init(&tl1_preview_lock);
                tl1_vdin1_preview_flag = 1;
                max_ignore_frames[devp->index] = 9;
        }
@@ -745,14 +736,16 @@ void vdin_stop_dec(struct vdin_dev_s *devp)
        if (is_meson_tl1_cpu() && (devp->afbce_mode == 1))
                vdin_afbce_hw_disable();
 
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+       vdin_dolby_addr_release(devp, devp->vfp->size);
+#endif
+
 #ifdef CONFIG_CMA
        if (devp->afbce_mode == 1)
                vdin_afbce_cma_release(devp);
        else if (devp->afbce_mode == 0)
                vdin_cma_release(devp);
 #endif
-       vdin_dolby_addr_release(devp, devp->vfp->size);
-
        switch_vpu_mem_pd_vmod(devp->addr_offset?VPU_VIU_VDIN1:VPU_VIU_VDIN0,
                        VPU_MEM_POWER_DOWN);
        memset(&devp->prop, 0, sizeof(struct tvin_sig_property_s));
@@ -824,18 +817,7 @@ int start_tvin_service(int no, struct vdin_parm_s  *para)
                else
                        return -EBUSY;
        }
-       if ((para->port != TVIN_PORT_VIU1) ||
-               (viu_hw_irq != 0)) {
-               ret = request_irq(devp->irq, vdin_v4l2_isr, IRQF_SHARED,
-                               devp->irq_name, (void *)devp);
-               if (ret != 0) {
-                       pr_info("vdin_v4l2_isr request irq error.\n");
-                       return -1;
-               }
-               devp->flags |= VDIN_FLAG_ISR_REQ;
-               /*disable vsync irq until vdin configured completely*/
-               disable_irq_nosync(devp->irq);
-       }
+
        vdin_clk_onoff(devp, true);
        /*config the vdin use default value*/
        vdin_set_default_regmap(devp->addr_offset);
@@ -917,6 +899,16 @@ int start_tvin_service(int no, struct vdin_parm_s  *para)
        devp->flags |= VDIN_FLAG_DEC_OPENED;
        devp->flags |= VDIN_FLAG_DEC_STARTED;
 
+       if ((para->port != TVIN_PORT_VIU1) ||
+               (viu_hw_irq != 0)) {
+               ret = request_irq(devp->irq, vdin_v4l2_isr, IRQF_SHARED,
+                               devp->irq_name, (void *)devp);
+               if (ret != 0) {
+                       pr_info("vdin_v4l2_isr request irq error.\n");
+                       return -1;
+               }
+               devp->flags |= VDIN_FLAG_ISR_REQ;
+       }
        return 0;
 }
 EXPORT_SYMBOL(start_tvin_service);
@@ -2373,6 +2365,16 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        break;
                }
                vdin_start_dec(devp);
+
+               if ((devp->parm.port != TVIN_PORT_VIU1) ||
+                       (viu_hw_irq != 0)) {
+                       /*enable irq */
+                       enable_irq(devp->irq);
+                       if (vdin_dbg_en)
+                               pr_info("****[%s]enable_irq ifdef VDIN_V2****\n",
+                                               __func__);
+               }
+
                devp->flags |= VDIN_FLAG_DEC_STARTED;
                if (vdin_dbg_en)
                        pr_info("TVIN_IOC_START_DEC port %s, decode started ok\n\n",
@@ -2383,29 +2385,19 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                mutex_lock(&devp_vdin1->fe_lock);
                if ((tl1_vdin1_preview_flag == 1) &&
                        !(devp_vdin1->flags & VDIN_FLAG_DEC_STARTED)) {
-                       msleep(150);
+                       /*msleep(150);*/
                        devp_vdin1->flags |= VDIN_FLAG_FS_OPENED;
-                       if (!(devp_vdin1->flags & VDIN_FLAG_ISR_REQ)) {
-                               ret = request_irq(devp_vdin1->irq, vdin_isr,
-                                       IRQF_SHARED,
-                                       devp_vdin1->irq_name,
-                                       (void *)devp_vdin1);
-                               if (ret != 0) {
-                                       pr_info("tl1_vdin1_preview request irq error.\n");
-                                       return -1;
-                               }
-                               devp_vdin1->flags |= VDIN_FLAG_ISR_REQ;
-                               disable_irq_nosync(devp_vdin1->irq);
-                               /*init queue*/
-                               init_waitqueue_head(&devp_vdin1->queue);
-                       }
 
                        devp_vdin1->unstable_flag = false;
                        devp_vdin1->parm.info.fmt = fmt;
                        devp_vdin1->parm.port = devp->parm.port;
                        devp_vdin1->fmt_info_p = (struct tvin_format_s *)
-                               tvin_get_fmt_info(fmt);
+                       tvin_get_fmt_info(fmt);
+
                        if (!(devp_vdin1->flags & VDIN_FLAG_DEC_OPENED)) {
+                               /*init queue*/
+                               init_waitqueue_head(&devp_vdin1->queue);
+
                                ret = vdin_open_fe(devp_vdin1->parm.port,
                                        0, devp_vdin1);
                                if (ret) {
@@ -2430,6 +2422,23 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        vdin_start_dec(devp_vdin1);
                        devp_vdin1->flags |= VDIN_FLAG_DEC_STARTED;
 
+                       if (!(devp_vdin1->flags & VDIN_FLAG_ISR_REQ)) {
+                               ret = request_irq(devp_vdin1->irq, vdin_isr,
+                                       IRQF_SHARED,
+                                       devp_vdin1->irq_name,
+                                       (void *)devp_vdin1);
+                               if (ret != 0) {
+                                       pr_info("tl1_vdin1_preview request irq error.\n");
+                                       return -1;
+                               }
+                               devp_vdin1->flags |= VDIN_FLAG_ISR_REQ;
+                       } else {
+                               enable_irq(devp_vdin1->irq);
+                               if (vdin_dbg_en)
+                                       pr_info("****[%s]enable_vdin1_irq****\n",
+                                               __func__);
+                       }
+
                        pr_info("TVIN_IOC_START_DEC port %s, vdin1 used for preview\n",
                                tvin_port_str(devp_vdin1->parm.port));
                }
@@ -3112,6 +3121,8 @@ static int vdin_drv_probe(struct platform_device *pdev)
        else
                vdevp->color_depth_mode = 0;
 
+       /* use for tl1 vdin1 preview */
+       spin_lock_init(&tl1_preview_lock);
        /*set afbce mode*/
        ret = of_property_read_u32(pdev->dev.of_node,
                "afbce_bit_mode", &val);