#include <linux/fb.h>
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
#include <asm/io.h>
#include <asm/mtrr.h>
#define INCLUDE_TIMING_TABLE_DATA
-#define DBE_REG_BASE default_par.regs
+#define DBE_REG_BASE par->regs
#include <video/sgivw.h>
struct sgivw_par {
extern unsigned long sgivwfb_mem_phys;
extern unsigned long sgivwfb_mem_size;
-static struct sgivw_par default_par;
-static u32 pseudo_palette[17];
-static struct fb_info fb_info;
static int ypan = 0;
static int ywrap = 0;
static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp,
struct fb_info *info);
-static int sgivwfb_mmap(struct fb_info *info, struct file *file,
+static int sgivwfb_mmap(struct fb_info *info,
struct vm_area_struct *vma);
static struct fb_ops sgivwfb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
.fb_mmap = sgivwfb_mmap,
};
* console.
*/
-static void dbe_TurnOffDma(void)
+static void dbe_TurnOffDma(struct sgivw_par *par)
{
unsigned int readVal;
int i;
/*
* Setup flatpanel related registers.
*/
-static void sgivwfb_setup_flatpanel(struct dbe_timing_info *currentTiming)
+static void sgivwfb_setup_flatpanel(struct sgivw_par *par, struct dbe_timing_info *currentTiming)
{
int fp_wid, fp_hgt, fp_vbs, fp_vbe;
u32 outputVal = 0;
/* Turn on dotclock PLL */
DBE_SETREG(ctrlstat, 0x20000000);
- dbe_TurnOffDma();
+ dbe_TurnOffDma(par);
/* dbe_CalculateScreenParams(); */
maxPixelsPerTileX = 512 / bytesPerPixel;
DBE_SETREG(vt_xy, 0x00000000);
udelay(1);
} else
- dbe_TurnOffDma();
+ dbe_TurnOffDma(par);
/* dbe_Initdbe(); */
for (i = 0; i < 256; i++) {
DBE_SETREG(vt_hcmap, outputVal);
if (flatpanel_id != -1)
- sgivwfb_setup_flatpanel(currentTiming);
+ sgivwfb_setup_flatpanel(par, currentTiming);
outputVal = 0;
temp = currentTiming->vblank_start - currentTiming->vblank_end - 1;
return 0;
}
-static int sgivwfb_mmap(struct fb_info *info, struct file *file,
+static int sgivwfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
unsigned long size = vma->vm_end - vma->vm_start;
pgprot_val(vma->vm_page_prot) =
pgprot_val(vma->vm_page_prot) | _PAGE_PCD;
vma->vm_flags |= VM_IO;
- if (remap_page_range
- (vma, vma->vm_start, offset, size, vma->vm_page_prot))
+ if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
+ size, vma->vm_page_prot))
return -EAGAIN;
- vma->vm_file = file;
printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n",
offset, vma->vm_start);
return 0;
/*
* Initialisation
*/
-int __init sgivwfb_init(void)
+static int __init sgivwfb_probe(struct platform_device *dev)
{
+ struct sgivw_par *par;
+ struct fb_info *info;
char *monitor;
+ info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 256, &dev->dev);
+ if (!info)
+ return -ENOMEM;
+ par = info->par;
+
if (!request_mem_region(DBE_REG_PHYS, DBE_REG_SIZE, "sgivwfb")) {
printk(KERN_ERR "sgivwfb: couldn't reserve mmio region\n");
+ framebuffer_release(info);
return -EBUSY;
}
- default_par.regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
- if (!default_par.regs) {
+
+ par->regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
+ if (!par->regs) {
printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n");
goto fail_ioremap_regs;
}
sgivwfb_fix.ywrapstep = ywrap;
sgivwfb_fix.ypanstep = ypan;
- fb_info.fix = sgivwfb_fix;
+ info->fix = sgivwfb_fix;
switch (flatpanel_id) {
case FLATPANEL_SGI_1600SW:
- fb_info.var = sgivwfb_var1600sw;
+ info->var = sgivwfb_var1600sw;
monitor = "SGI 1600SW flatpanel";
break;
default:
- fb_info.var = sgivwfb_var;
+ info->var = sgivwfb_var;
monitor = "CRT";
}
printk(KERN_INFO "sgivwfb: %s monitor selected\n", monitor);
- fb_info.fbops = &sgivwfb_ops;
- fb_info.pseudo_palette = pseudo_palette;
- fb_info.par = &default_par;
- fb_info.flags = FBINFO_FLAG_DEFAULT;
+ info->fbops = &sgivwfb_ops;
+ info->pseudo_palette = (void *) (par + 1);
+ info->flags = FBINFO_DEFAULT;
- fb_info.screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
- if (!fb_info.screen_base) {
+ info->screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
+ if (!info->screen_base) {
printk(KERN_ERR "sgivwfb: couldn't ioremap screen_base\n");
goto fail_ioremap_fbmem;
}
- fb_alloc_cmap(&fb_info.cmap, 256, 0);
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+ goto fail_color_map;
- if (register_framebuffer(&fb_info) < 0) {
+ if (register_framebuffer(info) < 0) {
printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n");
goto fail_register_framebuffer;
}
+ platform_set_drvdata(dev, info);
+
printk(KERN_INFO "fb%d: SGI DBE frame buffer device, using %ldK of video memory at %#lx\n",
- fb_info.node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
+ info->node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
return 0;
fail_register_framebuffer:
- iounmap((char *) fb_info.screen_base);
+ fb_dealloc_cmap(&info->cmap);
+fail_color_map:
+ iounmap((char *) info->screen_base);
fail_ioremap_fbmem:
- iounmap(default_par.regs);
+ iounmap(par->regs);
fail_ioremap_regs:
release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+ framebuffer_release(info);
return -ENXIO;
}
-#ifdef MODULE
-MODULE_LICENSE("GPL");
+static int sgivwfb_remove(struct platform_device *dev)
+{
+ struct fb_info *info = platform_get_drvdata(dev);
+
+ if (info) {
+ struct sgivw_par *par = info->par;
+
+ unregister_framebuffer(info);
+ dbe_TurnOffDma(par);
+ iounmap(par->regs);
+ iounmap(info->screen_base);
+ release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+ }
+ return 0;
+}
-int init_module(void)
+static struct platform_driver sgivwfb_driver = {
+ .probe = sgivwfb_probe,
+ .remove = sgivwfb_remove,
+ .driver = {
+ .name = "sgivwfb",
+ },
+};
+
+static struct platform_device *sgivwfb_device;
+
+int __init sgivwfb_init(void)
{
- return sgivwfb_init();
+ int ret;
+
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("sgivwfb", &option))
+ return -ENODEV;
+ sgivwfb_setup(option);
+#endif
+ ret = platform_driver_register(&sgivwfb_driver);
+ if (!ret) {
+ sgivwfb_device = platform_device_alloc("sgivwfb", 0);
+ if (sgivwfb_device) {
+ ret = platform_device_add(sgivwfb_device);
+ } else
+ ret = -ENOMEM;
+ if (ret) {
+ platform_driver_unregister(&sgivwfb_driver);
+ platform_device_put(sgivwfb_device);
+ }
+ }
+ return ret;
}
-void cleanup_module(void)
+module_init(sgivwfb_init);
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+static void __exit sgivwfb_exit(void)
{
- unregister_framebuffer(&fb_info);
- dbe_TurnOffDma();
- iounmap(regs);
- iounmap(&fb_info.screen_base);
- release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+ platform_device_unregister(sgivwfb_device);
+ platform_driver_unregister(&sgivwfb_driver);
}
+module_exit(sgivwfb_exit);
+
#endif /* MODULE */