aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlya Yanok <ilya.yanok@gmail.com>2007-10-16 04:29:17 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:18 -0400
commit68e5e9d734503695915734e50e9427624cf8f3b2 (patch)
treec784682bd229dd03e04fd9444cd9345dccf578c3
parent1ddc28d7e7cb5f501e224a5868d34442c6203eb1 (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>
-rw-r--r--drivers/video/vfb.c78
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;
37static u_long videomemorysize = VIDEOMEMSIZE; 37static u_long videomemorysize = VIDEOMEMSIZE;
38module_param(videomemorysize, ulong, 0); 38module_param(videomemorysize, ulong, 0);
39 39
40/**********************************************************************
41 *
42 * Memory management
43 *
44 **********************************************************************/
45static 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
66static 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
40static struct fb_var_screeninfo vfb_default __initdata = { 82static 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,
371static int vfb_mmap(struct fb_info *info, 413static 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:
452err1: 522err1:
453 framebuffer_release(info); 523 framebuffer_release(info);
454err: 524err:
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;