X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fvideo%2Fvfb.c;h=072638a9528aa71573626f959c290525ec9f6643;hb=9e124fe16ff24746d6de5a2ad685266d7bce0e08;hp=77eed1fd994366d4140ae74d319eee2a94fe396d;hpb=1b9a3917366028cc451a98dd22e3bcd537d4e5c1;p=linux-2.6-omap-h63xx.git diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 77eed1fd994..072638a9528 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,7 +413,33 @@ 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 @@ -398,12 +466,6 @@ static int __init vfb_setup(char *options) * Initialisation */ -static void vfb_platform_release(struct device *device) -{ - // This is called when the reference count goes to zero. - dev_err(device, "This driver is broken, please bug the authors so they will fix it.\n"); -} - static int __init vfb_probe(struct platform_device *dev) { struct fb_info *info; @@ -412,7 +474,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; /* @@ -435,6 +497,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; @@ -458,7 +522,7 @@ err2: err1: framebuffer_release(info); err: - vfree(videomemory); + rvfree(videomemory, videomemorysize); return retval; } @@ -468,7 +532,7 @@ static int vfb_remove(struct platform_device *dev) if (info) { unregister_framebuffer(info); - vfree(videomemory); + rvfree(videomemory, videomemorysize); framebuffer_release(info); } return 0; @@ -482,13 +546,7 @@ static struct platform_driver vfb_driver = { }, }; -static struct platform_device vfb_device = { - .name = "vfb", - .id = 0, - .dev = { - .release = vfb_platform_release, - } -}; +static struct platform_device *vfb_device; static int __init vfb_init(void) { @@ -508,10 +566,19 @@ static int __init vfb_init(void) ret = platform_driver_register(&vfb_driver); if (!ret) { - ret = platform_device_register(&vfb_device); - if (ret) + vfb_device = platform_device_alloc("vfb", 0); + + if (vfb_device) + ret = platform_device_add(vfb_device); + else + ret = -ENOMEM; + + if (ret) { + platform_device_put(vfb_device); platform_driver_unregister(&vfb_driver); + } } + return ret; } @@ -520,7 +587,7 @@ module_init(vfb_init); #ifdef MODULE static void __exit vfb_exit(void) { - platform_device_unregister(&vfb_device); + platform_device_unregister(vfb_device); platform_driver_unregister(&vfb_driver); }