From: Oliver Z. <oz...@co...> - 2007-10-08 14:00:55
|
Hi all, I wrote a framebuffer driver for an Atmel AVR32 microcontroller with a simple monochrome LCD wired to GPIO. The fb uses system RAM. My problem is that I need 8 PAGES of mem (256*64*16 bpp) and cannot find code which is able to mmap more than 1 PAGE. Here's my code: ------------------------------------------------------------------------------- #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/mm.h> #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <asm/uaccess.h> #include <linux/fb.h> #include <linux/init.h> #include <linux/types.h> #define MEM_SIZE (256*64*2) #define SCREEN_SIZE (256*64*2) #define LINE_LEN (256*2) u8 *lm6800_buffer; EXPORT_SYMBOL_GPL(lm6800_buffer); static struct fb_var_screeninfo meinfb_var __initdata = { .xres = 256, .yres = 64, .xres_virtual = 256, .yres_virtual = 64, .bits_per_pixel = 16, .red = { 11,5, 0 }, .green = { 5, 6, 0 }, .blue = { 0, 5, 0 }, .left_margin = 0, .right_margin = 0, .upper_margin = 0, .lower_margin = 0, .vmode = FB_VMODE_NONINTERLACED, }; static struct fb_fix_screeninfo meinfb_fix __initdata = { .id = "LM6800 COLOR FB", .type = FB_TYPE_PACKED_PIXELS, .smem_len = MEM_SIZE, .visual = FB_VISUAL_TRUECOLOR, .xpanstep = 0, .ypanstep = 0, .ywrapstep = 0, .line_length = LINE_LEN, .accel = FB_ACCEL_NONE, }; //do I need this at all? static int meinfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { info->cmap = *fb_default_cmap(16); return 0; } static int meinfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { return vm_insert_page(vma, vma->vm_start, virt_to_page(lm6800_buffer)); } static struct fb_ops meinfb_ops = { .owner = THIS_MODULE, .fb_read = fb_sys_read, .fb_write = fb_sys_write, .fb_setcolreg = meinfb_setcolreg, .fb_fillrect = sys_fillrect, .fb_copyarea = sys_copyarea, .fb_imageblit = sys_imageblit, .fb_mmap = meinfb_mmap, }; static int __init meinfb_probe(struct platform_device *dev) { struct fb_info *info; int retval = -ENOMEM; // allocate in lcd driver? // PAGE_SIZE is 4096 so I need 8 pages (256*64*2 / 4096 = 8) if (!(lm6800_buffer = (u8 *) __get_free_pages(GFP_KERNEL, 3))) return retval; memset(lm6800_buffer, 0, MEM_SIZE); info = framebuffer_alloc(0, &dev->dev); if (!info) goto err; info->screen_base = (char __iomem *)lm6800_buffer; info->screen_size = SCREEN_SIZE; info->fbops = &meinfb_ops; info->var = meinfb_var; info->fix = meinfb_fix; info->pseudo_palette = NULL; info->par = NULL; info->flags = FBINFO_FLAG_DEFAULT; fb_alloc_cmap(&info->cmap, 16, 0); info->cmap = *fb_default_cmap(16); retval = register_framebuffer(info); if (retval < 0) goto err1; platform_set_drvdata(dev, info); return 0; err1: framebuffer_release(info); err: free_pages((unsigned long) lm6800_buffer, 3); return retval; } static int meinfb_remove(struct platform_device *dev) { struct fb_info *info = platform_get_drvdata(dev); if (info) { unregister_framebuffer(info); free_pages((unsigned long) lm6800_buffer, 3); framebuffer_release(info); } return 0; } static struct platform_driver meinfb_driver = { .probe = meinfb_probe, .remove = meinfb_remove, .driver = { .name = "meinfb", }, }; static struct platform_device *meinfb_device; static int __init meinfb_init(void) { int ret = 0; ret = platform_driver_register(&meinfb_driver); if (!ret) { meinfb_device = platform_device_alloc("meinfb", 0); if (meinfb_device) ret = platform_device_add(meinfb_device); else ret = -ENOMEM; if (ret) { platform_device_put(meinfb_device); platform_driver_unregister(&meinfb_driver); } } return ret; } static void __exit meinfb_exit(void) { platform_device_unregister(meinfb_device); platform_driver_unregister(&meinfb_driver); } module_init(meinfb_init); module_exit(meinfb_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Oliver Zander"); MODULE_DESCRIPTION("LM6800 framebuffer driver with color support"); ------------------------------------------------------------------------------- I'm very new to Linux and driver development so please be forgiving :) TIA O.Zander |