fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / video / vga16fb.c
index bdcc8ec..6aff63d 100644 (file)
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/tty.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/screen_info.h>
 
 #include <asm/io.h>
 #include <video/vga.h>
  * card parameters
  */
 
-static struct fb_info vga16fb; 
-
-static struct vga16fb_par {
+struct vga16fb_par {
        /* structure holding original VGA register settings when the
            screen is blanked */
        struct {
-               unsigned char   SeqCtrlIndex;           /* Sequencer Index reg.   */
-               unsigned char   CrtCtrlIndex;           /* CRT-Contr. Index reg.  */
-               unsigned char   CrtMiscIO;              /* Miscellaneous register */
-               unsigned char   HorizontalTotal;        /* CRT-Controller:00h */
-               unsigned char   HorizDisplayEnd;        /* CRT-Controller:01h */
-               unsigned char   StartHorizRetrace;      /* CRT-Controller:04h */
-               unsigned char   EndHorizRetrace;        /* CRT-Controller:05h */
-               unsigned char   Overflow;               /* CRT-Controller:07h */
-               unsigned char   StartVertRetrace;       /* CRT-Controller:10h */
-               unsigned char   EndVertRetrace;         /* CRT-Controller:11h */
-               unsigned char   ModeControl;            /* CRT-Controller:17h */
-               unsigned char   ClockingMode;           /* Seq-Controller:01h */
+               unsigned char   SeqCtrlIndex;     /* Sequencer Index reg.   */
+               unsigned char   CrtCtrlIndex;     /* CRT-Contr. Index reg.  */
+               unsigned char   CrtMiscIO;        /* Miscellaneous register */
+               unsigned char   HorizontalTotal;  /* CRT-Controller:00h */
+               unsigned char   HorizDisplayEnd;  /* CRT-Controller:01h */
+               unsigned char   StartHorizRetrace;/* CRT-Controller:04h */
+               unsigned char   EndHorizRetrace;  /* CRT-Controller:05h */
+               unsigned char   Overflow;         /* CRT-Controller:07h */
+               unsigned char   StartVertRetrace; /* CRT-Controller:10h */
+               unsigned char   EndVertRetrace;   /* CRT-Controller:11h */
+               unsigned char   ModeControl;      /* CRT-Controller:17h */
+               unsigned char   ClockingMode;     /* Seq-Controller:01h */
        } vga_state;
        struct vgastate state;
        atomic_t ref_count;
        int palette_blanked, vesa_blanked, mode, isVGA;
        u8 misc, pel_msk, vss, clkdiv;
        u8 crtc[VGA_CRT_C];
-} vga16_par;
+};
 
 /* --------------------------------------------------------------------- */
 
-static struct fb_var_screeninfo vga16fb_defined = {
+static struct fb_var_screeninfo vga16fb_defined __initdata = {
        .xres           = 640,
        .yres           = 480,
        .xres_virtual   = 640,
@@ -91,8 +90,8 @@ static struct fb_var_screeninfo vga16fb_defined = {
        .pixclock       = 39721,
        .left_margin    = 48,
        .right_margin   = 16,
-       .upper_margin   = 39,
-       .lower_margin   = 8,
+       .upper_margin   = 33,
+       .lower_margin   = 10,
        .hsync_len      = 96,
        .vsync_len      = 2,
        .vmode          = FB_VMODE_NONINTERLACED,
@@ -123,7 +122,7 @@ static struct fb_fix_screeninfo vga16fb_fix __initdata = {
    suitable instruction is the x86 bitwise OR.  The following
    read-modify-write routine should optimize to one such bitwise
    OR. */
-static inline void rmw(volatile char *p)
+static inline void rmw(volatile char __iomem *p)
 {
        readb(p);
        writeb(1, p);
@@ -205,7 +204,7 @@ static inline void setindex(int index)
 static void vga16fb_pan_var(struct fb_info *info, 
                            struct fb_var_screeninfo *var)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
        u32 xoffset, pos;
 
        xoffset = var->xoffset;
@@ -265,7 +264,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par,
                               const struct fb_info *info,
                               int mul, int div)
 {
-       static struct {
+       static const struct {
                u32 pixclock;
                u8  misc;
                u8  seq_clock_mode;
@@ -300,7 +299,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par,
 
 static int vga16fb_open(struct fb_info *info, int user)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
        int cnt = atomic_read(&par->ref_count);
 
        if (!cnt) {
@@ -315,7 +314,7 @@ static int vga16fb_open(struct fb_info *info, int user)
 
 static int vga16fb_release(struct fb_info *info, int user)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
        int cnt = atomic_read(&par->ref_count);
 
        if (!cnt)
@@ -330,7 +329,7 @@ static int vga16fb_release(struct fb_info *info, int user)
 static int vga16fb_check_var(struct fb_var_screeninfo *var,
                             struct fb_info *info)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
        u32 xres, right, hslen, left, xtotal;
        u32 yres, lower, vslen, upper, ytotal;
        u32 vxres, xoffset, vyres, yoffset;
@@ -535,7 +534,7 @@ static int vga16fb_check_var(struct fb_var_screeninfo *var,
 
 static int vga16fb_set_par(struct fb_info *info)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
        u8 gdc[VGA_GFX_C];
        u8 seq[VGA_SEQ_C];
        u8 atc[VGA_ATT_C];
@@ -653,7 +652,7 @@ static int vga16fb_set_par(struct fb_info *info)
 
 static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
 {
-       static unsigned char map[] = { 000, 001, 010, 011 };
+       static const unsigned char map[] = { 000, 001, 010, 011 };
        int val;
        
        if (regno >= 16)
@@ -677,7 +676,7 @@ static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
                             unsigned blue, unsigned transp,
                             struct fb_info *info)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
        int gray;
 
        /*
@@ -706,15 +705,7 @@ static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
 static int vga16fb_pan_display(struct fb_var_screeninfo *var,
                               struct fb_info *info) 
 {
-       if (var->xoffset + info->var.xres > info->var.xres_virtual ||
-           var->yoffset + info->var.yres > info->var.yres_virtual)
-               return -EINVAL;
-
        vga16fb_pan_var(info, var);
-
-       info->var.xoffset = var->xoffset;
-       info->var.yoffset = var->yoffset;
-       info->var.vmode &= ~FB_VMODE_YWRAP;
        return 0;
 }
 
@@ -771,7 +762,7 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
         * <Start of vertical Retrace> to maximum (incl. overflow)
         * Result: turn off vertical sync (VSync) pulse.
         */
-       if (mode & VESA_VSYNC_SUSPEND) {
+       if (mode & FB_BLANK_VSYNC_SUSPEND) {
                outb_p(0x10,vga_video_port_reg);        /* StartVertRetrace */
                outb_p(0xff,vga_video_port_val);        /* maximum value */
                outb_p(0x11,vga_video_port_reg);        /* EndVertRetrace */
@@ -780,7 +771,7 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
                outb_p(par->vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */
        }
 
-       if (mode & VESA_HSYNC_SUSPEND) {
+       if (mode & FB_BLANK_HSYNC_SUSPEND) {
                /*
                 * Set <End of horizontal retrace> to minimum (0) and
                 *  <Start of horizontal Retrace> to maximum
@@ -850,32 +841,31 @@ static void vga_pal_blank(void)
 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
 static int vga16fb_blank(int blank, struct fb_info *info)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
 
        switch (blank) {
-       case 0:                         /* Unblank */
+       case FB_BLANK_UNBLANK:                          /* Unblank */
                if (par->vesa_blanked) {
                        vga_vesa_unblank(par);
                        par->vesa_blanked = 0;
                }
                if (par->palette_blanked) {
-                       //do_install_cmap(info->currcon, info);
                        par->palette_blanked = 0;
                }
                break;
-       case 1:                         /* blank */
+       case FB_BLANK_NORMAL:                           /* blank */
                vga_pal_blank();
                par->palette_blanked = 1;
                break;
        default:                        /* VESA blanking */
-               vga_vesa_blank(par, blank-1);
+               vga_vesa_blank(par, blank);
                par->vesa_blanked = 1;
                break;
        }
        return 0;
 }
 
-void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+static void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
        u32 dx = rect->dx, width = rect->width;
         char oldindex = getindex();
@@ -883,7 +873,7 @@ void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
         char oldmask = selectmask();
         int line_ofs, height;
         char oldop, oldsr;
-        char *where;
+        char __iomem *where;
 
         dx /= 4;
         where = info->screen_base + dx + rect->dy * info->fix.line_length;
@@ -929,10 +919,10 @@ void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
         setindex(oldindex);
 }
 
-void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+static void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
        int x, x2, y2, vxres, vyres, width, height, line_ofs;
-       char *dst;
+       char __iomem *dst;
 
        vxres = info->var.xres_virtual;
        vyres = info->var.yres_virtual;
@@ -1004,7 +994,7 @@ void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
        }
 }
 
-void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
         char oldindex = getindex();
         char oldmode = setmode(0x41);
@@ -1012,7 +1002,8 @@ void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
         char oldsr = setsr(0xf);
         int height, line_ofs, x;
        u32 sx, dx, width;
-       char *dest, *src;
+       char __iomem *dest;
+       char __iomem *src;
 
         height = area->height;
 
@@ -1058,12 +1049,13 @@ void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
         setindex(oldindex);
 }
 
-void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
        u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; 
        int x, x2, y2, old_dx, old_dy, vxres, vyres;
        int height, width, line_ofs;
-       char *dst = NULL, *src = NULL;
+       char __iomem *dst = NULL;
+       char __iomem *src = NULL;
 
        vxres = info->var.xres_virtual;
        vyres = info->var.yres_virtual;
@@ -1147,25 +1139,21 @@ void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
        }
 }
 
-#ifdef __LITTLE_ENDIAN
-static unsigned int transl_l[] =
-{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF};
-static unsigned int transl_h[] =
-{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00,
- 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00};
-#else
-#ifdef __BIG_ENDIAN
-static unsigned int transl_h[] =
-{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF};
-static unsigned int transl_l[] =
-{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00,
- 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00};
+#define TRANS_MASK_LOW  {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}
+#define TRANS_MASK_HIGH {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, \
+                        0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}
+
+#if defined(__LITTLE_ENDIAN)
+static const u16 transl_l[] = TRANS_MASK_LOW;
+static const u16 transl_h[] = TRANS_MASK_HIGH;
+#elif defined(__BIG_ENDIAN)
+static const u16 transl_l[] = TRANS_MASK_HIGH;
+static const u16 transl_h[] = TRANS_MASK_LOW;
 #else
 #error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes"
 #endif
-#endif
 
-void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
+static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
 {
         char oldindex = getindex();
         char oldmode = setmode(0x40);
@@ -1174,7 +1162,7 @@ void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
         char oldmask = selectmask();
         const char *cdat = image->data;
        u32 dx = image->dx;
-        char *where;
+        char __iomem *where;
         int y;
 
         dx /= 4;
@@ -1196,12 +1184,13 @@ void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
         setindex(oldindex);
 }
 
-void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
+static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
 {
-       char *where = info->screen_base + (image->dx/8) + 
+       char __iomem *where = info->screen_base + (image->dx/8) +
                image->dy * info->fix.line_length;
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
-       char *cdat = (char *) image->data, *dst;
+       struct vga16fb_par *par = info->par;
+       char *cdat = (char *) image->data;
+       char __iomem *dst;
        int x, y;
 
        switch (info->fix.type) {
@@ -1259,15 +1248,17 @@ void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
        }
 }
 
-void vga_imageblit_color(struct fb_info *info, const struct fb_image *image) 
+static void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
 {
        /*
         * Draw logo 
         */
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
-       char *where = info->screen_base + image->dy * info->fix.line_length + 
+       struct vga16fb_par *par = info->par;
+       char __iomem *where =
+               info->screen_base + image->dy * info->fix.line_length +
                image->dx/8;
-       const char *cdat = image->data, *dst;
+       const char *cdat = image->data;
+       char __iomem *dst;
        int x, y;
 
        switch (info->fix.type) {
@@ -1302,11 +1293,11 @@ void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
        }
 }
                                
-void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
+static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
        if (image->depth == 1)
                vga_imageblit_expand(info, image);
-       else if (image->depth <= info->var.bits_per_pixel)
+       else
                vga_imageblit_color(info, image);
 }
 
@@ -1322,10 +1313,10 @@ static struct fb_ops vga16fb_ops = {
        .fb_fillrect    = vga16fb_fillrect,
        .fb_copyarea    = vga16fb_copyarea,
        .fb_imageblit   = vga16fb_imageblit,
-       .fb_cursor      = soft_cursor,
 };
 
-int vga16fb_setup(char *options)
+#ifndef MODULE
+static int vga16fb_setup(char *options)
 {
        char *this_opt;
        
@@ -1337,88 +1328,153 @@ int vga16fb_setup(char *options)
        }
        return 0;
 }
+#endif
 
-int __init vga16fb_init(void)
+static int __init vga16fb_probe(struct platform_device *dev)
 {
+       struct fb_info *info;
+       struct vga16fb_par *par;
        int i;
-       int ret;
+       int ret = 0;
 
        printk(KERN_DEBUG "vga16fb: initializing\n");
+       info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev);
+
+       if (!info) {
+               ret = -ENOMEM;
+               goto err_fb_alloc;
+       }
 
        /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
+       info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0);
 
-       vga16fb.screen_base = (void *)VGA_MAP_MEM(VGA_FB_PHYS);
-       if (!vga16fb.screen_base) {
+       if (!info->screen_base) {
                printk(KERN_ERR "vga16fb: unable to map device\n");
                ret = -ENOMEM;
                goto err_ioremap;
        }
-       printk(KERN_INFO "vga16fb: mapped to 0x%p\n", vga16fb.screen_base);
 
-       vga16_par.isVGA = ORIG_VIDEO_ISVGA;
-       vga16_par.palette_blanked = 0;
-       vga16_par.vesa_blanked = 0;
+       printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
+       par = info->par;
 
-       i = vga16_par.isVGA? 6 : 2;
+       par->isVGA = ORIG_VIDEO_ISVGA;
+       par->palette_blanked = 0;
+       par->vesa_blanked = 0;
+
+       i = par->isVGA? 6 : 2;
        
        vga16fb_defined.red.length   = i;
        vga16fb_defined.green.length = i;
        vga16fb_defined.blue.length  = i;       
 
        /* name should not depend on EGA/VGA */
-       vga16fb.fbops = &vga16fb_ops;
-       vga16fb.var = vga16fb_defined;
-       vga16fb.fix = vga16fb_fix;
-       vga16fb.par = &vga16_par;
-       vga16fb.flags = FBINFO_FLAG_DEFAULT;
-
-       i = (vga16fb_defined.bits_per_pixel == 8) ? 256 : 16;
-       ret = fb_alloc_cmap(&vga16fb.cmap, i, 0);
+       info->fbops = &vga16fb_ops;
+       info->var = vga16fb_defined;
+       info->fix = vga16fb_fix;
+       info->flags = FBINFO_FLAG_DEFAULT |
+               FBINFO_HWACCEL_YPAN;
+
+       i = (info->var.bits_per_pixel == 8) ? 256 : 16;
+       ret = fb_alloc_cmap(&info->cmap, i, 0);
        if (ret) {
                printk(KERN_ERR "vga16fb: unable to allocate colormap\n");
                ret = -ENOMEM;
                goto err_alloc_cmap;
        }
 
-       if (vga16fb_check_var(&vga16fb.var, &vga16fb)) {
+       if (vga16fb_check_var(&info->var, info)) {
                printk(KERN_ERR "vga16fb: unable to validate variable\n");
                ret = -EINVAL;
                goto err_check_var;
        }
 
-       vga16fb_update_fix(&vga16fb);
+       vga16fb_update_fix(info);
 
-       if (register_framebuffer(&vga16fb) < 0) {
+       if (register_framebuffer(info) < 0) {
                printk(KERN_ERR "vga16fb: unable to register framebuffer\n");
                ret = -EINVAL;
                goto err_check_var;
        }
 
        printk(KERN_INFO "fb%d: %s frame buffer device\n",
-              vga16fb.node, vga16fb.fix.id);
+              info->node, info->fix.id);
+       platform_set_drvdata(dev, info);
 
        return 0;
 
  err_check_var:
-       fb_dealloc_cmap(&vga16fb.cmap);
+       fb_dealloc_cmap(&info->cmap);
  err_alloc_cmap:
-       iounmap(vga16fb.screen_base);
+       iounmap(info->screen_base);
  err_ioremap:
+       framebuffer_release(info);
+ err_fb_alloc:
+       return ret;
+}
+
+static int vga16fb_remove(struct platform_device *dev)
+{
+       struct fb_info *info = platform_get_drvdata(dev);
+
+       if (info) {
+               unregister_framebuffer(info);
+               iounmap(info->screen_base);
+               fb_dealloc_cmap(&info->cmap);
+       /* XXX unshare VGA regions */
+               framebuffer_release(info);
+       }
+
+       return 0;
+}
+
+static struct platform_driver vga16fb_driver = {
+       .probe = vga16fb_probe,
+       .remove = vga16fb_remove,
+       .driver = {
+               .name = "vga16fb",
+       },
+};
+
+static struct platform_device *vga16fb_device;
+
+static int __init vga16fb_init(void)
+{
+       int ret;
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("vga16fb", &option))
+               return -ENODEV;
+
+       vga16fb_setup(option);
+#endif
+       ret = platform_driver_register(&vga16fb_driver);
+
+       if (!ret) {
+               vga16fb_device = platform_device_alloc("vga16fb", 0);
+
+               if (vga16fb_device)
+                       ret = platform_device_add(vga16fb_device);
+               else
+                       ret = -ENOMEM;
+
+               if (ret) {
+                       platform_device_put(vga16fb_device);
+                       platform_driver_unregister(&vga16fb_driver);
+               }
+       }
+
        return ret;
 }
 
 static void __exit vga16fb_exit(void)
 {
-    unregister_framebuffer(&vga16fb);
-    iounmap(vga16fb.screen_base);
-    fb_dealloc_cmap(&vga16fb.cmap);
-    /* XXX unshare VGA regions */
+       platform_device_unregister(vga16fb_device);
+       platform_driver_unregister(&vga16fb_driver);
 }
 
-#ifdef MODULE
 MODULE_LICENSE("GPL");
 module_init(vga16fb_init);
-#endif
 module_exit(vga16fb_exit);