osd: add dd functions used phys_to_page and vmap [1/1]
authorPengcheng Chen <pengcheng.chen@amlogic.com>
Tue, 11 Dec 2018 04:55:59 +0000 (12:55 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Thu, 20 Dec 2018 06:46:53 +0000 (22:46 -0800)
PD#SWPL-3153

Problem:
remove phys_to_vir caused dd functions disable.

Solution:
add dd functions used phys_to_page and vmap

Verify:
franklin

Change-Id: Ic28ac0107adfee58933d0b19a2a7c2893c06b789
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
drivers/amlogic/media/osd/osd.h
drivers/amlogic/media/osd/osd_drm.c
drivers/amlogic/media/osd/osd_fb.c
drivers/amlogic/media/osd/osd_hw.c
drivers/amlogic/media/osd/osd_hw.h

index fc9c419..f6b658e 100644 (file)
@@ -733,11 +733,10 @@ struct hw_para_s {
        u32 osd_fps;
        u32 osd_fps_start;
        u32 osd_display_debug;
-       char __iomem *screen_base[HW_OSD_COUNT];
-       u32 screen_size[HW_OSD_COUNT];
-       char __iomem *screen_base_backup[HW_OSD_COUNT];
-       u32 screen_size_backup[HW_OSD_COUNT];
-       u32 osd_clear[HW_OSD_COUNT];
+       ulong screen_base[HW_OSD_COUNT];
+       ulong screen_size[HW_OSD_COUNT];
+       ulong screen_base_backup[HW_OSD_COUNT];
+       ulong screen_size_backup[HW_OSD_COUNT];
        u32 vinfo_width;
        u32 vinfo_height;
        u32 fb_drvier_probe;
index 0fe7be3..d2cb627 100644 (file)
@@ -133,10 +133,12 @@ static ssize_t logmodule_write_file(
        char buf[128];
        int ret = 0;
 
-       count = min_t(size_t, count, (sizeof(buf)-1));
+       if (count > sizeof(buf) || count <= 0)
+               return -EINVAL;
        if (copy_from_user(buf, userbuf, count))
                return -EFAULT;
-       buf[count] = 0;
+       if (buf[count - 1] == '\n')
+               buf[count - 1] = '\0';
        ret = kstrtoint(buf, 0, &log_module);
        osd_log_info("log_level: %d->%d\n", osd_log_module, log_module);
        osd_log_module = log_module;
@@ -470,7 +472,8 @@ static ssize_t osd_clear_write_file(struct file *file,
                return -EFAULT;
        buf[count] = 0;
        ret = kstrtoint(buf, 0, &osd_clear);
-       osd_set_clear(osd_id, osd_clear);
+       if (osd_clear)
+               osd_set_clear(osd_id);
        return count;
 }
 
@@ -478,12 +481,12 @@ static ssize_t osd_dump_read_file(struct file *file,
                                char __user *userbuf,
                                size_t count, loff_t *ppos)
 {
-       char __iomem *buf;
+       u8 __iomem *buf = NULL;
        struct seq_file *s = file->private_data;
        int osd_id = *(int *)s;
-       unsigned long len;
+       unsigned long len = 0;
 
-       osd_restore_screen_info(osd_id, &buf, &len);
+       len = get_vmap_addr(osd_id, &buf);
        if (buf && len)
                return simple_read_from_buffer(userbuf, count, ppos, buf, len);
        else
@@ -494,7 +497,14 @@ static ssize_t osd_dump_write_file(struct file *file,
                                const char __user *userbuf,
                                size_t count, loff_t *ppos)
 {
+#if 1
        return 0;
+#else
+       struct seq_file *s = file->private_data;
+       int osd_id = *(int *)s;
+
+       return dd_vmap_write(osd_id,  userbuf, count, ppos);
+#endif
 }
 
 static void parse_param(char *buf_orig, char **parm)
index de68fbb..22384f3 100644 (file)
@@ -1010,7 +1010,7 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
                                osd_sync_request_render(info->node,
                                info->var.yres,
                                sync_request_render, phys_addr, len);
-                       osd_restore_screen_info(info->node,
+                       osd_get_screen_info(info->node,
                                &info->screen_base, &info->screen_size);
                        ret = copy_to_user(argp,
                                &sync_request,
@@ -1400,8 +1400,10 @@ static int malloc_osd_memory(struct fb_info *info)
        fix->smem_len = fbdev->fb_len;
        info->screen_base = (char __iomem *)fbdev->fb_mem_vaddr;
        info->screen_size = fix->smem_len;
+       osd_hw.screen_base[fb_index] = fbdev->fb_mem_paddr;
+       osd_hw.screen_size[fb_index] = fix->smem_len;
        osd_backup_screen_info(fb_index,
-               info->screen_base, info->screen_size);
+               osd_hw.screen_base[fb_index], osd_hw.screen_size[fb_index]);
        logo_index = osd_get_logo_index();
        osd_log_info("logo_index=%x,fb_index=%d\n",
                logo_index, fb_index);
@@ -1539,6 +1541,275 @@ static int osd_mmap(struct fb_info *info, struct vm_area_struct *vma)
        return vm_iomap_memory(vma, start, len);
 }
 
+static int is_new_page(unsigned long addr, unsigned long pos)
+{
+       static ulong pre_addr;
+       u32 offset;
+       int ret = 0;
+
+       /* ret == 0 : in same page*/
+       if (pos == 0)
+               ret = 1;
+       else {
+               offset = pre_addr & ~PAGE_MASK;
+               if ((offset + addr - pre_addr) >= PAGE_SIZE)
+                       ret = 1;
+       }
+       pre_addr = addr;
+       return ret;
+}
+
+static ssize_t osd_read(struct fb_info *info, char __user *buf,
+       size_t count, loff_t *ppos)
+{
+       u32 fb_index;
+       struct osd_fb_dev_s *fbdev;
+       unsigned long p = *ppos;
+       unsigned long total_size;
+       static u8 *vaddr;
+       ulong phys;
+       u32 offset, npages;
+       struct page **pages = NULL;
+       struct page *pages_array[2] = {};
+       pgprot_t pgprot;
+       u8 *buffer, *dst;
+       u8 __iomem *src;
+       int i, c, cnt = 0, err = 0;
+
+       fbdev = (struct osd_fb_dev_s *)info->par;
+       fb_index = fbdev->fb_index;
+       total_size = osd_hw.screen_size[fb_index];
+       if (total_size == 0)
+               total_size = info->fix.smem_len;
+
+       if (p >= total_size)
+               return 0;
+
+       if (count >= total_size)
+               count = total_size;
+
+       if (count + p > total_size)
+               count = total_size - p;
+       if (count <= PAGE_SIZE) {
+               /* small than one page, need not vmalloc */
+               npages = PAGE_ALIGN(count) / PAGE_SIZE;
+               phys = osd_hw.screen_base[fb_index] + p;
+               if (is_new_page(phys, p)) {
+                       /* new page, need call vmap*/
+                       offset = phys & ~PAGE_MASK;
+                       if ((offset + count) > PAGE_SIZE)
+                               npages++;
+                       for (i = 0; i < npages; i++) {
+                               pages_array[i] = phys_to_page(phys);
+                               phys += PAGE_SIZE;
+                       }
+                       /*nocache*/
+                       pgprot = pgprot_writecombine(PAGE_KERNEL);
+                       if (vaddr) {
+                               /*  unmap prevois vaddr */
+                               vunmap(vaddr);
+                               vaddr = NULL;
+                       }
+                       vaddr = vmap(pages_array, npages, VM_MAP, pgprot);
+                       if (!vaddr) {
+                               pr_err("the phy(%lx) vmaped fail, size: %d\n",
+                                       phys, npages << PAGE_SHIFT);
+                               return -ENOMEM;
+                       }
+                       src = (u8 __iomem *) (vaddr);
+               } else {
+                       /* in same page just get vaddr + p*/
+                       src = (u8 __iomem *) (vaddr + (p & ~PAGE_MASK));
+               }
+       } else {
+               npages = PAGE_ALIGN(count) / PAGE_SIZE;
+               phys = osd_hw.screen_base[fb_index] + p;
+               offset = phys & ~PAGE_MASK;
+               if ((offset + count) > PAGE_SIZE)
+                       npages++;
+               pages = vmalloc(sizeof(struct page *) * npages);
+               if (!pages)
+                       return -ENOMEM;
+               for (i = 0; i < npages; i++) {
+                       pages[i] = phys_to_page(phys);
+                       phys += PAGE_SIZE;
+               }
+               /*nocache*/
+               pgprot = pgprot_writecombine(PAGE_KERNEL);
+               if (vaddr) {
+                       /*unmap prevois vaddr */
+                       vunmap(vaddr);
+                       vaddr = NULL;
+               }
+               vaddr = vmap(pages, npages, VM_MAP, pgprot);
+               if (!vaddr) {
+                       pr_err("the phy(%lx) vmaped fail, size: %d\n",
+                               phys, npages << PAGE_SHIFT);
+                       vfree(pages);
+                       return -ENOMEM;
+               }
+               vfree(pages);
+               src = (u8 __iomem *) (vaddr);
+       }
+
+       buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
+                        GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+       /* osd_sync(info); */
+
+       while (count) {
+               c  = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+               dst = buffer;
+               fb_memcpy_fromfb(dst, src, c);
+               dst += c;
+               src += c;
+
+               if (copy_to_user(buf, buffer, c)) {
+                       err = -EFAULT;
+                       break;
+               }
+               *ppos += c;
+               buf += c;
+               cnt += c;
+               count -= c;
+       }
+
+       kfree(buffer);
+
+       return (err) ? err : cnt;
+
+}
+
+static ssize_t osd_write(struct fb_info *info, const char __user *buf,
+       size_t count, loff_t *ppos)
+{
+       u32 fb_index;
+       struct osd_fb_dev_s *fbdev;
+       unsigned long p = *ppos;
+       unsigned long total_size;
+       static u8 *vaddr;
+       ulong phys;
+       u32 offset, npages;
+       struct page **pages = NULL;
+       struct page *pages_array[2] = {};
+       pgprot_t pgprot;
+       u8 *buffer, *src;
+       u8 __iomem *dst;
+       int i, c, cnt = 0, err = 0;
+
+       fbdev = (struct osd_fb_dev_s *)info->par;
+       fb_index = fbdev->fb_index;
+       total_size = osd_hw.screen_size[fb_index];
+
+       if (total_size == 0)
+               total_size = info->fix.smem_len;
+
+       if (p > total_size)
+               return -EFBIG;
+
+       if (count > total_size) {
+               err = -EFBIG;
+               count = total_size;
+       }
+
+       if (count + p > total_size) {
+               if (!err)
+                       err = -ENOSPC;
+
+               count = total_size - p;
+       }
+       if (count <= PAGE_SIZE) {
+               /* small than one page, need not vmalloc */
+               npages = PAGE_ALIGN(count) / PAGE_SIZE;
+               phys = osd_hw.screen_base[fb_index] + p;
+               if (is_new_page(phys, p)) {
+                       /* new page, need call vmap*/
+                       offset = phys & ~PAGE_MASK;
+                       if ((offset + count) > PAGE_SIZE)
+                               npages++;
+                       for (i = 0; i < npages; i++) {
+                               pages_array[i] = phys_to_page(phys);
+                               phys += PAGE_SIZE;
+                       }
+                       /*nocache*/
+                       pgprot = pgprot_writecombine(PAGE_KERNEL);
+                       if (vaddr) {
+                               /* unmap prevois vaddr */
+                               vunmap(vaddr);
+                               vaddr = NULL;
+                       }
+                       vaddr = vmap(pages_array, npages, VM_MAP, pgprot);
+                       if (!vaddr) {
+                               pr_err("the phy(%lx) vmaped fail, size: %d\n",
+                                       phys, npages << PAGE_SHIFT);
+                               return -ENOMEM;
+                       }
+                       dst = (u8 __iomem *) (vaddr);
+               } else {
+                       /* in same page just get vaddr + p*/
+                       dst = (u8 __iomem *) (vaddr + (p & ~PAGE_MASK));
+               }
+       } else {
+               npages = PAGE_ALIGN(count) / PAGE_SIZE;
+               phys = osd_hw.screen_base[fb_index] + p;
+               offset = phys & ~PAGE_MASK;
+               if ((offset + count) > PAGE_SIZE)
+                       npages++;
+               pages = vmalloc(sizeof(struct page *) * npages);
+               if (!pages)
+                       return -ENOMEM;
+               for (i = 0; i < npages; i++) {
+                       pages[i] = phys_to_page(phys);
+                       phys += PAGE_SIZE;
+               }
+               /*nocache*/
+               pgprot = pgprot_writecombine(PAGE_KERNEL);
+               if (vaddr) {
+                       /*  unmap prevois vaddr */
+                       vunmap(vaddr);
+                       vaddr = NULL;
+               }
+               vaddr = vmap(pages, npages, VM_MAP, pgprot);
+               if (!vaddr) {
+                       pr_err("the phy(%lx) vmaped fail, size: %d\n",
+                               phys, npages << PAGE_SHIFT);
+                       vfree(pages);
+                       return -ENOMEM;
+               }
+               vfree(pages);
+               dst = (u8 __iomem *) (vaddr);
+
+       }
+       buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
+                        GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       /* osd_sync() */
+
+       while (count) {
+               c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+               src = buffer;
+
+               if (copy_from_user(src, buf, c)) {
+                       err = -EFAULT;
+                       break;
+               }
+
+               fb_memcpy_tofb(dst, src, c);
+               dst += c;
+               *ppos += c;
+               buf += c;
+               cnt += c;
+               count -= c;
+       }
+
+       kfree(buffer);
+
+       return (cnt) ? cnt : err;
+
+}
 
 static int osd_release(struct fb_info *info, int arg)
 {
@@ -1560,21 +1831,6 @@ static int osd_release(struct fb_info *info, int arg)
 done:
        return err;
 }
-static ssize_t osd_clear(struct device *device, struct device_attribute *attr,
-               const char *buf, size_t count)
-{
-       u32 res = 0;
-       int ret = 0;
-
-       ret = kstrtoint(buf, 0, &res);
-       osd_log_info("clear: osd %d\n", res);
-
-       memset(fb_rmem_vaddr[res],
-                       0x0,
-                       fb_rmem_size[res]);
-
-       return count;
-}
 
 int osd_blank(int blank_mode, struct fb_info *info)
 {
@@ -1639,6 +1895,8 @@ static struct fb_ops osd_ops = {
 #endif
        .fb_open        = osd_open,
        .fb_mmap        = osd_mmap,
+       .fb_read        = osd_read,
+       .fb_write       = osd_write,
        .fb_blank       = osd_blank,
        .fb_pan_display = osd_pan_display,
        .fb_sync        = osd_sync,
@@ -2393,6 +2651,22 @@ static ssize_t store_afbcd(struct device *device, struct device_attribute *attr,
        return count;
 }
 
+static ssize_t osd_clear(struct device *device, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       u32 res = 0;
+       int ret = 0;
+       struct fb_info *fb_info = dev_get_drvdata(device);
+
+       ret = kstrtoint(buf, 0, &res);
+       osd_log_info("clear: osd %d\n", fb_info->node);
+
+       if (res)
+               osd_set_clear(fb_info->node);
+
+       return count;
+}
+
 static ssize_t show_log_level(struct device *device,
                          struct device_attribute *attr,
                          char *buf)
index 439abd0..51b9eb5 100644 (file)
@@ -30,6 +30,9 @@
 #include <linux/kthread.h>
 #include <linux/ktime.h>
 #include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/sysfs.h>
+#include <linux/uaccess.h>
 
 /* Android Headers */
 
@@ -72,7 +75,6 @@
 #include "osd_fb.h"
 
 #define OSD_BLEND_SHIFT_WORKAROUND
-#define REMOVE_PHYS_TO_VIRT
 #ifdef CONFIG_AMLOGIC_VSYNC_FIQ_ENABLE
 #define FIQ_VSYNC
 #endif
@@ -3736,9 +3738,6 @@ static bool osd_ge2d_compose_pan_display(struct osd_fence_map_s *fence_map)
 {
        u32 index = fence_map->fb_index;
        bool free_scale_set = false;
-       #ifndef REMOVE_PHYS_TO_VIRT
-       void *vaddr = NULL;
-       #endif
 
        canvas_config(osd_hw.fb_gem[index].canvas_idx,
                fence_map->ext_addr,
@@ -3746,13 +3745,10 @@ static bool osd_ge2d_compose_pan_display(struct osd_fence_map_s *fence_map)
                (osd_hw.color_info[index]->bpp >> 3)),
                fence_map->height,
                CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
-       #ifndef REMOVE_PHYS_TO_VIRT
-       vaddr = phys_to_virt(fence_map->ext_addr);
-       osd_hw.screen_base[index] = vaddr;
+       osd_hw.screen_base[index] = fence_map->ext_addr;
        osd_hw.screen_size[index] =
                CANVAS_ALIGNED(fence_map->width *
                osd_hw.color_info[index]->bpp) * fence_map->height;
-       #endif
        osd_hw.pandata[index].x_start = 0;
        osd_hw.pandata[index].x_end = fence_map->width - 1;
        osd_hw.pandata[index].y_start = 0;
@@ -3817,14 +3813,8 @@ static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map)
        u32 x_start, x_end, y_start, y_end;
        bool freescale_update = false;
        struct pandata_s freescale_dst[HW_OSD_COUNT];
-       #ifndef REMOVE_PHYS_TO_VIRT
-       void *vaddr = NULL;
-       #endif
 
        ext_addr = ext_addr + fence_map->byte_stride * fence_map->yoffset;
-       #ifndef REMOVE_PHYS_TO_VIRT
-       vaddr = phys_to_virt(ext_addr);
-       #endif
 
        if (!osd_hw.osd_afbcd[index].enable) {
                canvas_config(osd_hw.fb_gem[index].canvas_idx,
@@ -3832,11 +3822,9 @@ static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map)
                        fence_map->byte_stride,
                        fence_map->height,
                        CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
-               #ifndef REMOVE_PHYS_TO_VIRT
-               osd_hw.screen_base[index] = vaddr;
+               osd_hw.screen_base[index] = ext_addr;
                osd_hw.screen_size[index] =
                        fence_map->byte_stride * fence_map->height;
-               #endif
        } else {
                osd_hw.osd_afbcd[index].phy_addr = ext_addr;
                osd_hw.osd_afbcd[index].frame_width =
@@ -3857,10 +3845,8 @@ static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map)
                        else
                                osd_hw.osd_afbcd[index].conv_lbuf_len = 1024;
                }
-               #ifndef REMOVE_PHYS_TO_VIRT
-               osd_hw.screen_base[index] = vaddr;
+               osd_hw.screen_base[index] = ext_addr;
                osd_hw.screen_size[index] = fence_map->afbc_len;
-               #endif
        }
        width_dst = osd_hw.free_dst_data_backup[index].x_end -
                osd_hw.free_dst_data_backup[index].x_start + 1;
@@ -4282,9 +4268,6 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map)
        u32 index = layer_map->fb_index;
        const struct color_bit_define_s *color = NULL;
        u32 ext_addr = 0;
-       #ifndef REMOVE_PHYS_TO_VIRT
-       void *vaddr = NULL;
-       #endif
        u32 format = 0;
 
        if (index > OSD_MAX)
@@ -4354,10 +4337,6 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map)
                        layer_map->byte_stride *
                        layer_map->src_y;
                #endif
-
-               #ifndef REMOVE_PHYS_TO_VIRT
-               vaddr = phys_to_virt(ext_addr);
-               #endif
                if (!osd_hw.osd_afbcd[index].enable) {
                        /*ext_addr is no crop, so height =
                         * layer_map->src_h + layer_map->src_y
@@ -4368,11 +4347,9 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map)
                                layer_map->src_h + layer_map->src_y,
                                CANVAS_ADDR_NOWRAP,
                                CANVAS_BLKMODE_LINEAR);
-                       #ifndef REMOVE_PHYS_TO_VIRT
-                       osd_hw.screen_base[index] = vaddr;
+                       osd_hw.screen_base[index] = ext_addr;
                        osd_hw.screen_size[index] =
                                layer_map->byte_stride * layer_map->src_h;
-                       #endif
                } else {
                        osd_hw.osd_afbcd[index].phy_addr = ext_addr;
                        if (osd_hw.osd_meson_dev.afbc_type ==
@@ -4399,11 +4376,9 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map)
                                else
                                        osd_hw.osd_afbcd[index]
                                                .conv_lbuf_len = 1024;
-                               #ifndef REMOVE_PHYS_TO_VIRT
-                               osd_hw.screen_base[index] = vaddr;
+                               osd_hw.screen_base[index] = ext_addr;
                                osd_hw.screen_size[index] =
                                        layer_map->afbc_len;
-                               #endif
                        } else if (osd_hw.osd_meson_dev
                                .afbc_type == MALI_AFBC) {
                                osd_hw.osd_afbcd[index].frame_width =
@@ -4411,11 +4386,9 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map)
                                        //BYTE_32_ALIGNED(layer_map->src_w);
                                osd_hw.osd_afbcd[index].frame_height =
                                        BYTE_8_ALIGNED(layer_map->src_h);
-                               #ifndef REMOVE_PHYS_TO_VIRT
-                               osd_hw.screen_base[index] = vaddr;
+                               osd_hw.screen_base[index] = ext_addr;
                                osd_hw.screen_size[index] =
                                        layer_map->afbc_len;
-                               #endif
                        }
                }
                /* just get para, need update via do_hwc */
@@ -4496,7 +4469,7 @@ static void osd_pan_display_layers_fence(
                layer_map = &fence_map->layer_map[i];
                index = layer_map->fb_index;
                if (i != layer_map->fb_index) {
-                       osd_hw.screen_base[i] = NULL;
+                       osd_hw.screen_base[i] = 0;
                        osd_hw.screen_size[i] = 0;
                        osd_hw.enable[i] = 0;
                        continue;
@@ -8756,7 +8729,6 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
                osd_hw.free_src_data_backup[idx].y_end = 0;
                osd_hw.free_scale_mode[idx] = 0;
                osd_hw.buffer_alloc[idx] = 0;
-               osd_hw.osd_clear[idx] = 0;
                osd_hw.osd_afbcd[idx].enable = 0;
                osd_hw.use_h_filter_mode[idx] = -1;
                osd_hw.use_v_filter_mode[idx] = -1;
@@ -9410,28 +9382,255 @@ void osd_get_blending_para(struct hw_osd_blending_s **para)
 }
 void osd_backup_screen_info(
        u32 index,
-       char __iomem *screen_base,
-       u32 screen_size)
+       unsigned long screen_base,
+       unsigned long screen_size)
 {
        osd_hw.screen_base_backup[index] = screen_base;
        osd_hw.screen_size_backup[index] = screen_size;
-       osd_hw.screen_base[index] = screen_base;
-       osd_hw.screen_size[index] = screen_size;
 }
 
-void osd_restore_screen_info(
+void osd_get_screen_info(
        u32 index,
        char __iomem **screen_base,
        unsigned long *screen_size)
 {
-       *screen_base = osd_hw.screen_base[index];
-       *screen_size = (unsigned long)osd_hw.screen_size[index];
-
+       *screen_base = (char __iomem *)osd_hw.screen_base[index];
+       *screen_size = osd_hw.screen_size[index];
 }
 
-void osd_set_clear(u32 index, u32 osd_clear)
+int get_vmap_addr(u32 index, u8 __iomem **buf)
+{
+       unsigned long total_size;
+       ulong phys;
+       u32 offset, npages;
+       struct page **pages = NULL;
+       pgprot_t pgprot;
+       static u8 *vaddr;
+       int i;
+
+       total_size = osd_hw.screen_size[index];
+
+       npages = PAGE_ALIGN(total_size) / PAGE_SIZE;
+       phys = osd_hw.screen_base[index];
+       offset = phys & ~PAGE_MASK;
+       if (offset)
+               npages++;
+       pages = vmalloc(sizeof(struct page *) * npages);
+       if (!pages)
+               return -ENOMEM;
+       for (i = 0; i < npages; i++) {
+               pages[i] = phys_to_page(phys);
+               phys += PAGE_SIZE;
+       }
+       /*nocache*/
+       pgprot = pgprot_writecombine(PAGE_KERNEL);
+       if (vaddr) {
+               /*  unmap prevois vaddr */
+               vunmap(vaddr);
+               vaddr = NULL;
+       }
+       vaddr = vmap(pages, npages, VM_MAP, pgprot);
+       if (!vaddr) {
+               pr_err("the phy(%lx) vmaped fail, size: %d\n",
+                       phys, npages << PAGE_SHIFT);
+               vfree(pages);
+               return -ENOMEM;
+       }
+       vfree(pages);
+       *buf = (u8 __iomem *) (vaddr);
+
+       return osd_hw.screen_size[index];
+}
+#if 0
+static int is_new_page(unsigned long addr, unsigned long pos)
 {
-       osd_hw.osd_clear[index] = osd_clear;
+       static ulong pre_addr;
+       u32 offset;
+       int ret = 0;
+
+       /* ret == 0 : in same page*/
+       if (pos == 0)
+               ret = 1;
+       else {
+               offset = pre_addr & ~PAGE_MASK;
+               if ((offset + addr - pre_addr) >= PAGE_SIZE)
+                       ret = 1;
+       }
+       pre_addr = addr;
+       return ret;
+}
+
+ssize_t dd_vmap_write(u32 index, const char __user *buf,
+       size_t count, loff_t *ppos)
+{
+       unsigned long p = *ppos;
+       unsigned long total_size;
+       static u8 *vaddr;
+       ulong phys;
+       u32 offset, npages;
+       struct page **pages = NULL;
+       struct page *pages_array[2] = {};
+       pgprot_t pgprot;
+       u8 *buffer, *src;
+       u8 __iomem *dst;
+       int i, c, cnt = 0, err = 0;
+
+       total_size = osd_hw.screen_size[index];
+       if (p > total_size)
+               return -EFBIG;
+
+       if (count > total_size) {
+               err = -EFBIG;
+               count = total_size;
+       }
+
+       if (count + p > total_size) {
+               if (!err)
+                       err = -ENOSPC;
+
+               count = total_size - p;
+       }
+       if (count < PAGE_SIZE) {
+               /* small than one page, need not vmalloc */
+               npages = PAGE_ALIGN(count) / PAGE_SIZE;
+               phys = osd_hw.screen_base[index] + p;
+               if (is_new_page(phys, p)) {
+                       /* new page, need call vmap*/
+                       offset = phys & ~PAGE_MASK;
+                       if ((offset + count) > PAGE_SIZE)
+                               npages++;
+                       for (i = 0; i < npages; i++) {
+                               pages_array[i] = phys_to_page(phys);
+                               phys += PAGE_SIZE;
+                       }
+                       /*nocache*/
+                       pgprot = pgprot_writecombine(PAGE_KERNEL);
+                       if (vaddr) {
+                               /* unmap prevois vaddr */
+                               vunmap(vaddr);
+                               vaddr = NULL;
+                       }
+                       vaddr = vmap(pages_array, npages, VM_MAP, pgprot);
+                       if (!vaddr) {
+                               pr_err("the phy(%lx) vmaped fail, size: %d\n",
+                                       phys, npages << PAGE_SHIFT);
+                               return -ENOMEM;
+                       }
+                       dst = (u8 __iomem *) (vaddr);
+               } else {
+                       /* in same page just get vaddr + p*/
+                       dst = (u8 __iomem *) (vaddr + (p & ~PAGE_MASK));
+               }
+       } else {
+               npages = PAGE_ALIGN(count) / PAGE_SIZE;
+               phys = osd_hw.screen_base[index] + p;
+               offset = phys & ~PAGE_MASK;
+               if ((offset + count) > PAGE_SIZE)
+                       npages++;
+               pages = vmalloc(sizeof(struct page *) * npages);
+               if (!pages)
+                       return -ENOMEM;
+               for (i = 0; i < npages; i++) {
+                       pages[i] = phys_to_page(phys);
+                       phys += PAGE_SIZE;
+               }
+               /*nocache*/
+               pgprot = pgprot_writecombine(PAGE_KERNEL);
+               //pgprot = PAGE_KERNEL;
+               if (vaddr) {
+                       /*  unmap prevois vaddr */
+                       vunmap(vaddr);
+                       vaddr = NULL;
+               }
+               vaddr = vmap(pages, npages, VM_MAP, pgprot);
+               if (!vaddr) {
+                       pr_err("the phy(%lx) vmaped fail, size: %d\n",
+                               phys, npages << PAGE_SHIFT);
+                       vfree(pages);
+                       return -ENOMEM;
+               }
+               vfree(pages);
+               dst = (u8 __iomem *) (vaddr);
+       }
+       buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
+                        GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       /* osd_sync() */
+
+       while (count) {
+               c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+               src = buffer;
+
+               if (copy_from_user(src, buf, c)) {
+                       err = -EFAULT;
+                       break;
+               }
+
+               fb_memcpy_tofb(dst, src, c);
+               dst += c;
+               *ppos += c;
+               buf += c;
+               cnt += c;
+               count -= c;
+       }
+       kfree(buffer);
+       return (cnt) ? cnt : err;
+}
+#endif
+int osd_set_clear(u32 index)
+{
+       unsigned long total_size;
+       ulong phys;
+       u32 offset, npages;
+       struct page **pages = NULL;
+       pgprot_t pgprot;
+       static u8 *vaddr;
+       u8 __iomem *dst;
+       int i, c, count, cnt = 0;
+
+       total_size = osd_hw.screen_size[index];
+       npages = PAGE_ALIGN(total_size) / PAGE_SIZE;
+       phys = osd_hw.screen_base[index];
+       offset = phys & (~PAGE_MASK);
+       if (offset)
+               npages++;
+       pages = vmalloc(sizeof(struct page *) * npages);
+       if (!pages)
+               return -ENOMEM;
+       for (i = 0; i < npages; i++) {
+               pages[i] = phys_to_page(phys);
+               phys += PAGE_SIZE;
+       }
+       /*nocache*/
+       pgprot = pgprot_writecombine(PAGE_KERNEL);
+
+       vaddr = vmap(pages, npages, VM_MAP, pgprot);
+       if (!vaddr) {
+               pr_err("the phy(%lx) vmaped fail, size: %d\n",
+                       phys, npages << PAGE_SHIFT);
+               vfree(pages);
+               return -ENOMEM;
+       }
+       vfree(pages);
+       dst = (u8 __iomem *) (vaddr);
+
+       count = total_size;
+       while (count) {
+               c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+               memset(dst, 0, c);
+               dst += c;
+               cnt += c;
+               count -= c;
+       }
+       if (vaddr) {
+               /*  unmap prevois vaddr */
+               vunmap(vaddr);
+               vaddr = NULL;
+       }
+
+       return cnt;
 }
 
 static const struct color_bit_define_s *convert_panel_format(u32 format)
@@ -9480,23 +9679,10 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map)
        bool freescale_update = false;
        struct pandata_s freescale_dst[HW_OSD_COUNT];
 
-       #ifndef REMOVE_PHYS_TO_VIRT
-       void *vaddr = NULL;
-       #endif
-
        phy_addr = phy_addr + plane_map->byte_stride * plane_map->src_y;
-
-       #ifndef REMOVE_PHYS_TO_VIRT
-       vaddr = phys_to_virt(phy_addr);
-       osd_hw.screen_base[index] = vaddr;
+       osd_hw.screen_base[index] = phy_addr;
        osd_hw.screen_size[index] =
                plane_map->byte_stride * plane_map->src_h;
-       if (osd_hw.osd_clear[index]) {
-               if (vaddr)
-                       memset(vaddr, 0x0,
-                               plane_map->byte_stride*plane_map->src_h);
-       }
-       #endif
        osd_log_dbg(MODULE_RENDER, "canvas_id=%x, phy_addr=%x\n",
                osd_hw.fb_gem[index].canvas_idx, phy_addr);
        canvas_config(osd_hw.fb_gem[index].canvas_idx,
@@ -9734,29 +9920,15 @@ static void osd_cursor_move(struct osd_plane_map_s *plane_map)
        u32 phy_addr = plane_map->phy_addr;
        u32 x_start, x_end, y_start, y_end;
        u32 x, y;
-
-       #ifndef REMOVE_PHYS_TO_VIRT
-       void *vaddr = NULL;
-       #endif
-
        struct pandata_s disp_tmp;
        struct pandata_s free_dst_data_backup;
 
        if (index != OSD2)
                return;
        phy_addr = phy_addr + plane_map->byte_stride * plane_map->src_y;
-
-       #ifndef REMOVE_PHYS_TO_VIRT
-       vaddr = phys_to_virt(phy_addr);
-       osd_hw.screen_base[index] = vaddr;
+       osd_hw.screen_base[index] = phy_addr;
        osd_hw.screen_size[index] =
                plane_map->byte_stride * plane_map->src_h;
-       if (osd_hw.osd_clear[index]) {
-               if (vaddr)
-                       memset(vaddr, 0x0,
-                               plane_map->byte_stride*plane_map->src_h);
-       }
-       #endif
        canvas_config(osd_hw.fb_gem[index].canvas_idx,
                phy_addr,
                plane_map->byte_stride,
index ee43d39..61c14dc 100644 (file)
@@ -191,13 +191,16 @@ void osd_do_hwc(void);
 int osd_get_capbility(u32 index);
 void osd_backup_screen_info(
        u32 index,
-       char __iomem *screen_base,
-       u32 screen_size);
-void osd_restore_screen_info(
+       unsigned long screen_base,
+       unsigned long screen_size);
+void osd_get_screen_info(
        u32 index,
        char __iomem **screen_base,
        unsigned long *screen_size);
-void osd_set_clear(u32 index, u32 osd_clear);
+int get_vmap_addr(u32 index, u8 __iomem **buf);
+ssize_t dd_vmap_write(u32 index, const char __user *buf,
+       size_t count, loff_t *ppos);
+int osd_set_clear(u32 index);
 void osd_page_flip(struct osd_plane_map_s *plane_map);
 void walk_through_update_list(void);
 int osd_setting_blend(void);