X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=drivers%2Fvideo%2Fvfb.c;h=93fe08d6c78f6f2a36b84c8977ad95c2781ff6f1;hp=d073ffb6e1f9f0d600c585f46ffa802fca4b0286;hb=5c402355adf8f920531f02099f4ec0d2bccd4c64;hpb=6fa0cb1141da80eed4f86155fb51931bc1c31888 diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index d073ffb6e1f9..93fe08d6c78f 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -15,14 +15,12 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include @@ -39,6 +37,48 @@ static void *videomemory; static u_long videomemorysize = VIDEOMEMSIZE; module_param(videomemorysize, ulong, 0); +/********************************************************************** + * + * Memory management + * + **********************************************************************/ +static void *rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr; + + size = PAGE_ALIGN(size); + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + return mem; +} + +static void rvfree(void *mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + adr = (unsigned long) mem; + while ((long) size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); +} + static struct fb_var_screeninfo vfb_default __initdata = { .xres = 640, .yres = 480, @@ -85,13 +125,15 @@ static int vfb_mmap(struct fb_info *info, struct vm_area_struct *vma); static struct fb_ops vfb_ops = { + .fb_read = fb_sys_read, + .fb_write = fb_sys_write, .fb_check_var = vfb_check_var, .fb_set_par = vfb_set_par, .fb_setcolreg = vfb_setcolreg, .fb_pan_display = vfb_pan_display, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, + .fb_fillrect = sys_fillrect, + .fb_copyarea = sys_copyarea, + .fb_imageblit = sys_imageblit, .fb_mmap = vfb_mmap, }; @@ -371,23 +413,59 @@ static int vfb_pan_display(struct fb_var_screeninfo *var, static int vfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { - return -EINVAL; + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end - vma->vm_start; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long page, pos; + + if (offset + size > info->fix.smem_len) { + return -EINVAL; + } + + pos = (unsigned long)info->fix.smem_start + offset; + + while (size > 0) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ + return 0; + } #ifndef MODULE +/* + * The virtual framebuffer driver is only enabled if explicitly + * requested by passing 'video=vfb:' (or any actual options). + */ static int __init vfb_setup(char *options) { char *this_opt; + vfb_enable = 0; + + if (!options) + return 1; + vfb_enable = 1; - if (!options || !*options) + if (!*options) return 1; while ((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; - if (!strncmp(this_opt, "disable", 7)) + /* Test disable for backwards compatibility */ + if (!strcmp(this_opt, "disable")) vfb_enable = 0; } return 1; @@ -406,7 +484,7 @@ static int __init vfb_probe(struct platform_device *dev) /* * For real video cards we use ioremap. */ - if (!(videomemory = vmalloc(videomemorysize))) + if (!(videomemory = rvmalloc(videomemorysize))) return retval; /* @@ -429,6 +507,8 @@ static int __init vfb_probe(struct platform_device *dev) if (!retval || (retval == 4)) info->var = vfb_default; + vfb_fix.smem_start = (unsigned long) videomemory; + vfb_fix.smem_len = videomemorysize; info->fix = vfb_fix; info->pseudo_palette = info->par; info->par = NULL; @@ -452,7 +532,7 @@ err2: err1: framebuffer_release(info); err: - vfree(videomemory); + rvfree(videomemory, videomemorysize); return retval; } @@ -462,7 +542,7 @@ static int vfb_remove(struct platform_device *dev) if (info) { unregister_framebuffer(info); - vfree(videomemory); + rvfree(videomemory, videomemorysize); framebuffer_release(info); } return 0;