X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fvideo%2Fgbefb.c;h=bf0e60b5a3b645c71e64430657e22366250ae141;hb=refs%2Fheads%2Fvserver;hp=2afc4148b929ccad22c540c2c12318be54779c8c;hpb=e812ccbe0c915857ebea6a632bfadc631f7504a9;p=linux-2.6.git diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index 2afc4148b..bf0e60b5a 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -9,9 +9,8 @@ * more details. */ -#include #include -#include +#include #include #include #include @@ -85,7 +84,6 @@ static struct { static int gbe_revision; -static struct fb_info fb_info; static int ypan, ywrap; static uint32_t pseudo_palette[256]; @@ -190,8 +188,6 @@ struct fb_var_screeninfo *default_var = &default_var_CRT; static int flat_panel_enabled = 0; -static struct gbefb_par par_current; - static void gbe_reset(void) { /* Turn on dotclock PLL */ @@ -384,11 +380,11 @@ static int gbefb_blank(int blank, struct fb_info *info) { /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ switch (blank) { - case 0: /* unblank */ + case FB_BLANK_UNBLANK: /* unblank */ gbe_turn_on(); break; - case 1: /* blank */ + case FB_BLANK_NORMAL: /* blank */ gbe_turn_off(); break; @@ -659,12 +655,15 @@ static int gbefb_set_par(struct fb_info *info) switch (bytesPerPixel) { case 1: SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_I8); + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; break; case 2: SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_ARGB5); + info->fix.visual = FB_VISUAL_TRUECOLOR; break; case 4: SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_RGB8); + info->fix.visual = FB_VISUAL_TRUECOLOR; break; } SET_GBE_FIELD(WID, BUF, val, GBE_BMODE_BOTH); @@ -982,7 +981,7 @@ static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) return 0; } -static int gbefb_mmap(struct fb_info *info, struct file *file, +static int gbefb_mmap(struct fb_info *info, struct vm_area_struct *vma) { unsigned long size = vma->vm_end - vma->vm_start; @@ -1003,7 +1002,6 @@ static int gbefb_mmap(struct fb_info *info, struct file *file, pgprot_fb(pgprot_val(vma->vm_page_prot)); vma->vm_flags |= VM_IO | VM_RESERVED; - vma->vm_file = file; /* look for the starting tile */ tile = &gbe_tiles.cpu[offset >> TILE_SHIFT]; @@ -1018,8 +1016,8 @@ static int gbefb_mmap(struct fb_info *info, struct file *file, else phys_size = TILE_SIZE - offset; - if (remap_page_range - (vma, addr, phys_addr, phys_size, vma->vm_page_prot)) + if (remap_pfn_range(vma, addr, phys_addr >> PAGE_SHIFT, + phys_size, vma->vm_page_prot)) return -EAGAIN; offset = 0; @@ -1041,9 +1039,38 @@ static struct fb_ops gbefb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; +/* + * sysfs + */ + +static ssize_t gbefb_show_memsize(struct device *dev, struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", gbe_mem_size); +} + +static DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL); + +static ssize_t gbefb_show_rev(struct device *device, struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", gbe_revision); +} + +static DEVICE_ATTR(revision, S_IRUGO, gbefb_show_rev, NULL); + +static void __devexit gbefb_remove_sysfs(struct device *dev) +{ + device_remove_file(dev, &dev_attr_size); + device_remove_file(dev, &dev_attr_revision); +} + +static void gbefb_create_sysfs(struct device *dev) +{ + device_create_file(dev, &dev_attr_size); + device_create_file(dev, &dev_attr_revision); +} + /* * Initialization */ @@ -1079,13 +1106,29 @@ int __init gbefb_setup(char *options) return 0; } -int __init gbefb_init(void) +static int __init gbefb_probe(struct platform_device *p_dev) { int i, ret = 0; + struct fb_info *info; + struct gbefb_par *par; +#ifndef MODULE + char *options = NULL; +#endif + + info = framebuffer_alloc(sizeof(struct gbefb_par), &p_dev->dev); + if (!info) + return -ENOMEM; - if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) { +#ifndef MODULE + if (fb_get_options("gbefb", &options)) + return -ENODEV; + gbefb_setup(options); +#endif + + if (!request_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) { printk(KERN_ERR "gbefb: couldn't reserve mmio region\n"); - return -EBUSY; + ret = -EBUSY; + goto out_release_framebuffer; } gbe = (struct sgi_gbe *) ioremap(GBE_BASE, sizeof(struct sgi_gbe)); @@ -1105,16 +1148,27 @@ int __init gbefb_init(void) goto out_unmap; } - if (gbe_mem_phys) { /* memory was allocated at boot time */ gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size); + if (!gbe_mem) { + printk(KERN_ERR "gbefb: couldn't map framebuffer\n"); + ret = -ENOMEM; + goto out_tiles_free; + } + gbe_dma_addr = 0; } else { /* try to allocate memory with the classical allocator * this has high chance to fail on low memory machines */ gbe_mem = dma_alloc_coherent(NULL, gbe_mem_size, &gbe_dma_addr, GFP_KERNEL); + if (!gbe_mem) { + printk(KERN_ERR "gbefb: couldn't allocate framebuffer memory\n"); + ret = -ENOMEM; + goto out_tiles_free; + } + gbe_mem_phys = (unsigned long) gbe_dma_addr; } @@ -1122,43 +1176,39 @@ int __init gbefb_init(void) mtrr_add(gbe_mem_phys, gbe_mem_size, MTRR_TYPE_WRCOMB, 1); #endif - if (!gbe_mem) { - printk(KERN_ERR "gbefb: couldn't map framebuffer\n"); - ret = -ENXIO; - goto out_tiles_free; - } - /* map framebuffer memory into tiles table */ for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++) gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i; - fb_info.currcon = -1; - fb_info.fbops = &gbefb_ops; - fb_info.pseudo_palette = pseudo_palette; - fb_info.flags = FBINFO_FLAG_DEFAULT; - fb_info.screen_base = gbe_mem; - fb_alloc_cmap(&fb_info.cmap, 256, 0); + info->fbops = &gbefb_ops; + info->pseudo_palette = pseudo_palette; + info->flags = FBINFO_DEFAULT; + info->screen_base = gbe_mem; + fb_alloc_cmap(&info->cmap, 256, 0); /* reset GBE */ gbe_reset(); + par = info->par; /* turn on default video mode */ - if (fb_find_mode(&par_current.var, &fb_info, mode_option, NULL, 0, + if (fb_find_mode(&par->var, info, mode_option, NULL, 0, default_mode, 8) == 0) - par_current.var = *default_var; - fb_info.var = par_current.var; - gbefb_check_var(&par_current.var, &fb_info); - gbefb_encode_fix(&fb_info.fix, &fb_info.var); - fb_info.par = &par_current; + par->var = *default_var; + info->var = par->var; + gbefb_check_var(&par->var, info); + gbefb_encode_fix(&info->fix, &info->var); - if (register_framebuffer(&fb_info) < 0) { - ret = -ENXIO; + if (register_framebuffer(info) < 0) { printk(KERN_ERR "gbefb: couldn't register framebuffer\n"); + ret = -ENXIO; goto out_gbe_unmap; } + platform_set_drvdata(p_dev, info); + gbefb_create_sysfs(&p_dev->dev); + printk(KERN_INFO "fb%d: %s rev %d @ 0x%08x using %dkB memory\n", - fb_info.node, fb_info.fix.id, gbe_revision, (unsigned) GBE_BASE, + info->node, info->fix.id, gbe_revision, (unsigned) GBE_BASE, gbe_mem_size >> 10); return 0; @@ -1175,12 +1225,17 @@ out_unmap: iounmap(gbe); out_release_mem_region: release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); +out_release_framebuffer: + framebuffer_release(info); + return ret; } -void __exit gbefb_exit(void) +static int __devexit gbefb_remove(struct platform_device* p_dev) { - unregister_framebuffer(&fb_info); + struct fb_info *info = platform_get_drvdata(p_dev); + + unregister_framebuffer(info); gbe_turn_off(); if (gbe_dma_addr) dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys); @@ -1190,11 +1245,47 @@ void __exit gbefb_exit(void) (void *)gbe_tiles.cpu, gbe_tiles.dma); release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); iounmap(gbe); + gbefb_remove_sysfs(&p_dev->dev); + framebuffer_release(info); + + return 0; +} + +static struct platform_driver gbefb_driver = { + .probe = gbefb_probe, + .remove = __devexit_p(gbefb_remove), + .driver = { + .name = "gbefb", + }, +}; + +static struct platform_device *gbefb_device; + +int __init gbefb_init(void) +{ + int ret = platform_driver_register(&gbefb_driver); + if (!ret) { + gbefb_device = platform_device_alloc("gbefb", 0); + if (gbefb_device) { + ret = platform_device_add(gbefb_device); + } else { + ret = -ENOMEM; + } + if (ret) { + platform_device_put(gbefb_device); + platform_driver_unregister(&gbefb_driver); + } + } + return ret; +} + +void __exit gbefb_exit(void) +{ + platform_device_unregister(gbefb_device); + platform_driver_unregister(&gbefb_driver); } -#ifdef MODULE module_init(gbefb_init); module_exit(gbefb_exit); -#endif MODULE_LICENSE("GPL");