From 2d82eff6fef4eb56bf1abdb8660ec10509cf4aed Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Tue, 11 Dec 2018 12:55:59 +0800 Subject: [PATCH] osd: add dd functions used phys_to_page and vmap [1/1] 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 --- drivers/amlogic/media/osd/osd.h | 9 +- drivers/amlogic/media/osd/osd_drm.c | 22 ++- drivers/amlogic/media/osd/osd_fb.c | 308 ++++++++++++++++++++++++++++++++-- drivers/amlogic/media/osd/osd_hw.c | 326 +++++++++++++++++++++++++++--------- drivers/amlogic/media/osd/osd_hw.h | 11 +- 5 files changed, 567 insertions(+), 109 deletions(-) diff --git a/drivers/amlogic/media/osd/osd.h b/drivers/amlogic/media/osd/osd.h index fc9c419..f6b658e 100644 --- a/drivers/amlogic/media/osd/osd.h +++ b/drivers/amlogic/media/osd/osd.h @@ -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; diff --git a/drivers/amlogic/media/osd/osd_drm.c b/drivers/amlogic/media/osd/osd_drm.c index 0fe7be3..d2cb627 100644 --- a/drivers/amlogic/media/osd/osd_drm.c +++ b/drivers/amlogic/media/osd/osd_drm.c @@ -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) diff --git a/drivers/amlogic/media/osd/osd_fb.c b/drivers/amlogic/media/osd/osd_fb.c index de68fbb..22384f3 100644 --- a/drivers/amlogic/media/osd/osd_fb.c +++ b/drivers/amlogic/media/osd/osd_fb.c @@ -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) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 439abd0..51b9eb5 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -30,6 +30,9 @@ #include #include #include +#include +#include +#include /* 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, diff --git a/drivers/amlogic/media/osd/osd_hw.h b/drivers/amlogic/media/osd/osd_hw.h index ee43d39..61c14dc 100644 --- a/drivers/amlogic/media/osd/osd_hw.h +++ b/drivers/amlogic/media/osd/osd_hw.h @@ -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); -- 2.7.4