* more details.
*/
-#include <linux/config.h>
#include <linux/delay.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/errno.h>
#include <linux/fb.h>
static int gbe_revision;
-static struct fb_info fb_info;
static int ypan, ywrap;
static uint32_t pseudo_palette[256];
static int flat_panel_enabled = 0;
-static struct gbefb_par par_current;
-
static void gbe_reset(void)
{
/* Turn on dotclock PLL */
{
/* 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;
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);
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;
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];
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;
.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
*/
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 *option = NULL;
+ char *options = NULL;
+#endif
+
+ info = framebuffer_alloc(sizeof(struct gbefb_par), &p_dev->dev);
+ if (!info)
+ return -ENOMEM;
- if (fb_get_options("gbefb", &option))
+#ifndef MODULE
+ if (fb_get_options("gbefb", &options))
return -ENODEV;
gbefb_setup(options);
#endif
- if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
+ 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));
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;
}
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_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;
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);
(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;
}
-module_init(gbefb_init);
+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;
+}
-#ifdef MODULE
+void __exit gbefb_exit(void)
+{
+ platform_device_unregister(gbefb_device);
+ platform_driver_unregister(&gbefb_driver);
+}
+
+module_init(gbefb_init);
module_exit(gbefb_exit);
-#endif
MODULE_LICENSE("GPL");