diff options
author | Ilya Yanok <ilya.yanok@gmail.com> | 2007-10-16 04:29:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:43:18 -0400 |
commit | 68e5e9d734503695915734e50e9427624cf8f3b2 (patch) | |
tree | c784682bd229dd03e04fd9444cd9345dccf578c3 /drivers | |
parent | 1ddc28d7e7cb5f501e224a5868d34442c6203eb1 (diff) |
vfb: make virtual framebuffer mmapable
Changed things:
1. vmalloc()/vfree() replaced with rvmalloc()/rvfree() (taken from
drivers/media/video/se401.c)
2. mmap method implemented (mostly taken from drivers/media/video/se401.c)
3. smem_start and smem_len fields of struct fb_fix_screeninfo initialized.
(smem_start initialized with virtual address, don't know if it is really
bad...)
[adaplas: sparse warning fix]
Signed-off-by: Antonino Daplas <adaplas@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/vfb.c | 78 |
1 files changed, 74 insertions, 4 deletions
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 02cfc6a45b0d..072638a9528a 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c | |||
@@ -37,6 +37,48 @@ static void *videomemory; | |||
37 | static u_long videomemorysize = VIDEOMEMSIZE; | 37 | static u_long videomemorysize = VIDEOMEMSIZE; |
38 | module_param(videomemorysize, ulong, 0); | 38 | module_param(videomemorysize, ulong, 0); |
39 | 39 | ||
40 | /********************************************************************** | ||
41 | * | ||
42 | * Memory management | ||
43 | * | ||
44 | **********************************************************************/ | ||
45 | static void *rvmalloc(unsigned long size) | ||
46 | { | ||
47 | void *mem; | ||
48 | unsigned long adr; | ||
49 | |||
50 | size = PAGE_ALIGN(size); | ||
51 | mem = vmalloc_32(size); | ||
52 | if (!mem) | ||
53 | return NULL; | ||
54 | |||
55 | memset(mem, 0, size); /* Clear the ram out, no junk to the user */ | ||
56 | adr = (unsigned long) mem; | ||
57 | while (size > 0) { | ||
58 | SetPageReserved(vmalloc_to_page((void *)adr)); | ||
59 | adr += PAGE_SIZE; | ||
60 | size -= PAGE_SIZE; | ||
61 | } | ||
62 | |||
63 | return mem; | ||
64 | } | ||
65 | |||
66 | static void rvfree(void *mem, unsigned long size) | ||
67 | { | ||
68 | unsigned long adr; | ||
69 | |||
70 | if (!mem) | ||
71 | return; | ||
72 | |||
73 | adr = (unsigned long) mem; | ||
74 | while ((long) size > 0) { | ||
75 | ClearPageReserved(vmalloc_to_page((void *)adr)); | ||
76 | adr += PAGE_SIZE; | ||
77 | size -= PAGE_SIZE; | ||
78 | } | ||
79 | vfree(mem); | ||
80 | } | ||
81 | |||
40 | static struct fb_var_screeninfo vfb_default __initdata = { | 82 | static struct fb_var_screeninfo vfb_default __initdata = { |
41 | .xres = 640, | 83 | .xres = 640, |
42 | .yres = 480, | 84 | .yres = 480, |
@@ -371,7 +413,33 @@ static int vfb_pan_display(struct fb_var_screeninfo *var, | |||
371 | static int vfb_mmap(struct fb_info *info, | 413 | static int vfb_mmap(struct fb_info *info, |
372 | struct vm_area_struct *vma) | 414 | struct vm_area_struct *vma) |
373 | { | 415 | { |
374 | return -EINVAL; | 416 | unsigned long start = vma->vm_start; |
417 | unsigned long size = vma->vm_end - vma->vm_start; | ||
418 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
419 | unsigned long page, pos; | ||
420 | |||
421 | if (offset + size > info->fix.smem_len) { | ||
422 | return -EINVAL; | ||
423 | } | ||
424 | |||
425 | pos = (unsigned long)info->fix.smem_start + offset; | ||
426 | |||
427 | while (size > 0) { | ||
428 | page = vmalloc_to_pfn((void *)pos); | ||
429 | if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { | ||
430 | return -EAGAIN; | ||
431 | } | ||
432 | start += PAGE_SIZE; | ||
433 | pos += PAGE_SIZE; | ||
434 | if (size > PAGE_SIZE) | ||
435 | size -= PAGE_SIZE; | ||
436 | else | ||
437 | size = 0; | ||
438 | } | ||
439 | |||
440 | vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ | ||
441 | return 0; | ||
442 | |||
375 | } | 443 | } |
376 | 444 | ||
377 | #ifndef MODULE | 445 | #ifndef MODULE |
@@ -406,7 +474,7 @@ static int __init vfb_probe(struct platform_device *dev) | |||
406 | /* | 474 | /* |
407 | * For real video cards we use ioremap. | 475 | * For real video cards we use ioremap. |
408 | */ | 476 | */ |
409 | if (!(videomemory = vmalloc(videomemorysize))) | 477 | if (!(videomemory = rvmalloc(videomemorysize))) |
410 | return retval; | 478 | return retval; |
411 | 479 | ||
412 | /* | 480 | /* |
@@ -429,6 +497,8 @@ static int __init vfb_probe(struct platform_device *dev) | |||
429 | 497 | ||
430 | if (!retval || (retval == 4)) | 498 | if (!retval || (retval == 4)) |
431 | info->var = vfb_default; | 499 | info->var = vfb_default; |
500 | vfb_fix.smem_start = (unsigned long) videomemory; | ||
501 | vfb_fix.smem_len = videomemorysize; | ||
432 | info->fix = vfb_fix; | 502 | info->fix = vfb_fix; |
433 | info->pseudo_palette = info->par; | 503 | info->pseudo_palette = info->par; |
434 | info->par = NULL; | 504 | info->par = NULL; |
@@ -452,7 +522,7 @@ err2: | |||
452 | err1: | 522 | err1: |
453 | framebuffer_release(info); | 523 | framebuffer_release(info); |
454 | err: | 524 | err: |
455 | vfree(videomemory); | 525 | rvfree(videomemory, videomemorysize); |
456 | return retval; | 526 | return retval; |
457 | } | 527 | } |
458 | 528 | ||
@@ -462,7 +532,7 @@ static int vfb_remove(struct platform_device *dev) | |||
462 | 532 | ||
463 | if (info) { | 533 | if (info) { |
464 | unregister_framebuffer(info); | 534 | unregister_framebuffer(info); |
465 | vfree(videomemory); | 535 | rvfree(videomemory, videomemorysize); |
466 | framebuffer_release(info); | 536 | framebuffer_release(info); |
467 | } | 537 | } |
468 | return 0; | 538 | return 0; |