Merge branch 'fbdev-next' of git://github.com/schandinat/linux-2.6
[pandora-kernel.git] / drivers / staging / xgifb / XGI_main_26.c
index f8b88ad..277e408 100644 (file)
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 
-#ifndef XGIFB_PAN
-#define XGIFB_PAN
-#endif
-
 #include <linux/io.h>
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
 #include "vb_setmode.h"
 
 #define Index_CR_GPIO_Reg1 0x48
-#define Index_CR_GPIO_Reg2 0x49
 #define Index_CR_GPIO_Reg3 0x4a
 
 #define GPIOG_EN    (1<<6)
-#define GPIOG_WRITE (1<<6)
 #define GPIOG_READ  (1<<1)
 
 #define XGIFB_ROM_SIZE 65536
 
+static char *mode;
+static int vesa = -1;
+static unsigned int refresh_rate;
+
 /* -------------------- Macro definitions ---------------------------- */
 
 #undef XGIFBDEBUG
@@ -143,9 +141,6 @@ static inline void dumpVGAReg(void)
 }
 #endif
 
-/* data for XGI components */
-struct video_info xgi_video_info;
-
 #if 1
 #define DEBUGPRN(x)
 #else
@@ -390,44 +385,6 @@ static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
 
 }
 
-/* ------------ Interface for init & mode switching code ------------- */
-
-static unsigned char XGIfb_query_VGA_config_space(
-               struct xgi_hw_device_info *pXGIhw_ext, unsigned long offset,
-               unsigned long set, unsigned long *value)
-{
-       static struct pci_dev *pdev = NULL;
-       static unsigned char init = 0, valid_pdev = 0;
-
-       if (!set)
-               DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
-       else
-               DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
-
-       if (!init) {
-               init = 1;
-               pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id,
-                               pdev);
-               if (pdev) {
-                       valid_pdev = 1;
-                       pci_dev_put(pdev);
-               }
-       }
-
-       if (!valid_pdev) {
-               printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
-                               xgi_video_info.chip_id);
-               return 0;
-       }
-
-       if (set == 0)
-               pci_read_config_dword(pdev, offset, (u32 *) value);
-       else
-               pci_write_config_dword(pdev, offset, (u32)(*value));
-
-       return 1;
-}
-
 /* ------------------ Internal helper routines ----------------- */
 
 static int XGIfb_GetXG21DefaultLVDSModeIdx(void)
@@ -445,48 +402,26 @@ static int XGIfb_GetXG21DefaultLVDSModeIdx(void)
                                && (XGIbios_mode[XGIfb_mode_idx].yres
                                                == XGI21_LCDCapList[0].LVDSVDE)
                                && (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) {
-                       XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
                        found_mode = 1;
                        break;
                }
                XGIfb_mode_idx++;
        }
        if (!found_mode)
-               XGIfb_mode_idx = 0;
+               XGIfb_mode_idx = -1;
 
        return XGIfb_mode_idx;
 }
 
-static void XGIfb_search_mode(const char *name)
+static void XGIfb_search_mode(struct xgifb_video_info *xgifb_info,
+                             const char *name)
 {
        int i = 0, j = 0, l;
 
-       if (name == NULL) {
-               printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
-               xgifb_mode_idx = DEFAULT_MODE;
-               if ((xgi_video_info.chip == XG21)
-                               && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
-                                               == DISPTYPE_LCD)) {
-                       xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
-               }
-               return;
-       }
-
-       if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
-               printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
-               xgifb_mode_idx = DEFAULT_MODE;
-               if ((xgi_video_info.chip == XG21)
-                               && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
-                                               == DISPTYPE_LCD)) {
-                       xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
-               }
-               return;
-       }
-
        while (XGIbios_mode[i].mode_no != 0) {
                l = min(strlen(name), strlen(XGIbios_mode[i].name));
                if (!strncmp(name, XGIbios_mode[i].name, l)) {
-                       xgifb_mode_idx = i;
+                       xgifb_info->mode_idx = i;
                        j = 1;
                        break;
                }
@@ -496,82 +431,66 @@ static void XGIfb_search_mode(const char *name)
                printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
 }
 
-static void XGIfb_search_vesamode(unsigned int vesamode)
+static void XGIfb_search_vesamode(struct xgifb_video_info *xgifb_info,
+                                 unsigned int vesamode)
 {
        int i = 0, j = 0;
 
-       if (vesamode == 0) {
-
-               printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
-               xgifb_mode_idx = DEFAULT_MODE;
-               if ((xgi_video_info.chip == XG21)
-                               && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
-                                               == DISPTYPE_LCD)) {
-                       xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
-               }
-               return;
-       }
+       if (vesamode == 0)
+               goto invalid;
 
        vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
 
        while (XGIbios_mode[i].mode_no != 0) {
                if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
                    (XGIbios_mode[i].vesa_mode_no_2 == vesamode)) {
-                       xgifb_mode_idx = i;
+                       xgifb_info->mode_idx = i;
                        j = 1;
                        break;
                }
                i++;
        }
+
+invalid:
        if (!j)
                printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
 }
 
-static int XGIfb_GetXG21LVDSData(void)
+static int XGIfb_GetXG21LVDSData(struct xgifb_video_info *xgifb_info)
 {
        u8 tmp;
-       unsigned char *pData;
+       void __iomem *data = xgifb_info->mmio_vbase + 0x20000;
        int i, j, k;
 
        tmp = xgifb_reg_get(XGISR, 0x1e);
        xgifb_reg_set(XGISR, 0x1e, tmp | 4);
 
-       pData = xgi_video_info.mmio_vbase + 0x20000;
-       if ((pData[0x0] == 0x55) &&
-           (pData[0x1] == 0xAA) &&
-           (pData[0x65] & 0x1)) {
-               i = pData[0x316] | (pData[0x317] << 8);
-               j = pData[i - 1];
+       if ((readb(data) == 0x55) &&
+           (readb(data + 1) == 0xAA) &&
+           (readb(data + 0x65) & 0x1)) {
+               i = readw(data + 0x316);
+               j = readb(data + i - 1);
                if (j == 0xff)
                        j = 1;
 
                k = 0;
                do {
-                       XGI21_LCDCapList[k].LVDS_Capability = pData[i]
-                                       | (pData[i + 1] << 8);
-                       XGI21_LCDCapList[k].LVDSHT = pData[i + 2] | (pData[i
-                                       + 3] << 8);
-                       XGI21_LCDCapList[k].LVDSVT = pData[i + 4] | (pData[i
-                                       + 5] << 8);
-                       XGI21_LCDCapList[k].LVDSHDE = pData[i + 6] | (pData[i
-                                       + 7] << 8);
-                       XGI21_LCDCapList[k].LVDSVDE = pData[i + 8] | (pData[i
-                                       + 9] << 8);
-                       XGI21_LCDCapList[k].LVDSHFP = pData[i + 10] | (pData[i
-                                       + 11] << 8);
-                       XGI21_LCDCapList[k].LVDSVFP = pData[i + 12] | (pData[i
-                                       + 13] << 8);
-                       XGI21_LCDCapList[k].LVDSHSYNC = pData[i + 14]
-                                       | (pData[i + 15] << 8);
-                       XGI21_LCDCapList[k].LVDSVSYNC = pData[i + 16]
-                                       | (pData[i + 17] << 8);
-                       XGI21_LCDCapList[k].VCLKData1 = pData[i + 18];
-                       XGI21_LCDCapList[k].VCLKData2 = pData[i + 19];
-                       XGI21_LCDCapList[k].PSC_S1 = pData[i + 20];
-                       XGI21_LCDCapList[k].PSC_S2 = pData[i + 21];
-                       XGI21_LCDCapList[k].PSC_S3 = pData[i + 22];
-                       XGI21_LCDCapList[k].PSC_S4 = pData[i + 23];
-                       XGI21_LCDCapList[k].PSC_S5 = pData[i + 24];
+                       XGI21_LCDCapList[k].LVDS_Capability = readw(data + i);
+                       XGI21_LCDCapList[k].LVDSHT = readw(data + i + 2);
+                       XGI21_LCDCapList[k].LVDSVT = readw(data + i + 4);
+                       XGI21_LCDCapList[k].LVDSHDE = readw(data + i + 6);
+                       XGI21_LCDCapList[k].LVDSVDE = readw(data + i + 8);
+                       XGI21_LCDCapList[k].LVDSHFP = readw(data + i + 10);
+                       XGI21_LCDCapList[k].LVDSVFP = readw(data + i + 12);
+                       XGI21_LCDCapList[k].LVDSHSYNC = readw(data + i + 14);
+                       XGI21_LCDCapList[k].LVDSVSYNC = readw(data + i + 16);
+                       XGI21_LCDCapList[k].VCLKData1 = readb(data + i + 18);
+                       XGI21_LCDCapList[k].VCLKData2 = readb(data + i + 19);
+                       XGI21_LCDCapList[k].PSC_S1 = readb(data + i + 20);
+                       XGI21_LCDCapList[k].PSC_S2 = readb(data + i + 21);
+                       XGI21_LCDCapList[k].PSC_S3 = readb(data + i + 22);
+                       XGI21_LCDCapList[k].PSC_S4 = readb(data + i + 23);
+                       XGI21_LCDCapList[k].PSC_S5 = readb(data + i + 24);
                        i += 25;
                        j--;
                        k++;
@@ -582,13 +501,13 @@ static int XGIfb_GetXG21LVDSData(void)
        return 0;
 }
 
-static int XGIfb_validate_mode(int myindex)
+static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex)
 {
        u16 xres, yres;
+       struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info;
 
-       if (xgi_video_info.chip == XG21) {
-               if ((xgi_video_info.disp_state & DISPTYPE_DISP2)
-                               == DISPTYPE_LCD) {
+       if (xgifb_info->chip == XG21) {
+               if (xgifb_info->display2 == XGIFB_DISP_LCD) {
                        xres = XGI21_LCDCapList[0].LVDSHDE;
                        yres = XGI21_LCDCapList[0].LVDSVDE;
                        if (XGIbios_mode[myindex].xres > xres)
@@ -607,15 +526,15 @@ static int XGIfb_validate_mode(int myindex)
        }
 
        /* FIXME: for now, all is valid on XG27 */
-       if (xgi_video_info.chip == XG27)
+       if (xgifb_info->chip == XG27)
                return myindex;
 
        if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
                return -1;
 
-       switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
-       case DISPTYPE_LCD:
-               switch (XGIhw_ext.ulCRT2LCDType) {
+       switch (xgifb_info->display2) {
+       case XGIFB_DISP_LCD:
+               switch (hw_info->ulCRT2LCDType) {
                case LCD_640x480:
                        xres = 640;
                        yres = 480;
@@ -671,13 +590,13 @@ static int XGIfb_validate_mode(int myindex)
                        return -1;
                if (XGIbios_mode[myindex].yres > yres)
                        return -1;
-               if ((XGIhw_ext.ulExternalChip == 0x01) || /* LVDS */
-                   (XGIhw_ext.ulExternalChip == 0x05)) { /* LVDS+Chrontel */
+               if ((hw_info->ulExternalChip == 0x01) || /* LVDS */
+                   (hw_info->ulExternalChip == 0x05)) { /* LVDS+Chrontel */
                        switch (XGIbios_mode[myindex].xres) {
                        case 512:
                                if (XGIbios_mode[myindex].yres != 512)
                                        return -1;
-                               if (XGIhw_ext.ulCRT2LCDType == LCD_1024x600)
+                               if (hw_info->ulCRT2LCDType == LCD_1024x600)
                                        return -1;
                                break;
                        case 640:
@@ -695,13 +614,13 @@ static int XGIfb_validate_mode(int myindex)
                                    (XGIbios_mode[myindex].yres != 768))
                                        return -1;
                                if ((XGIbios_mode[myindex].yres == 600) &&
-                                   (XGIhw_ext.ulCRT2LCDType != LCD_1024x600))
+                                   (hw_info->ulCRT2LCDType != LCD_1024x600))
                                        return -1;
                                break;
                        case 1152:
                                if ((XGIbios_mode[myindex].yres) != 768)
                                        return -1;
-                               if (XGIhw_ext.ulCRT2LCDType != LCD_1152x768)
+                               if (hw_info->ulCRT2LCDType != LCD_1152x768)
                                        return -1;
                                break;
                        case 1280:
@@ -709,7 +628,7 @@ static int XGIfb_validate_mode(int myindex)
                                    (XGIbios_mode[myindex].yres != 1024))
                                        return -1;
                                if ((XGIbios_mode[myindex].yres == 768) &&
-                                   (XGIhw_ext.ulCRT2LCDType != LCD_1280x768))
+                                   (hw_info->ulCRT2LCDType != LCD_1280x768))
                                        return -1;
                                break;
                        case 1400:
@@ -747,7 +666,7 @@ static int XGIfb_validate_mode(int myindex)
                                    (XGIbios_mode[myindex].yres != 1024))
                                        return -1;
                                if (XGIbios_mode[myindex].yres == 960) {
-                                       if (XGIhw_ext.ulCRT2LCDType ==
+                                       if (hw_info->ulCRT2LCDType ==
                                            LCD_1400x1050)
                                                return -1;
                                }
@@ -765,28 +684,28 @@ static int XGIfb_validate_mode(int myindex)
                        }
                }
                break;
-       case DISPTYPE_TV:
+       case XGIFB_DISP_TV:
                switch (XGIbios_mode[myindex].xres) {
                case 512:
                case 640:
                case 800:
                        break;
                case 720:
-                       if (xgi_video_info.TV_type == TVMODE_NTSC) {
+                       if (xgifb_info->TV_type == TVMODE_NTSC) {
                                if (XGIbios_mode[myindex].yres != 480)
                                        return -1;
-                       } else if (xgi_video_info.TV_type == TVMODE_PAL) {
+                       } else if (xgifb_info->TV_type == TVMODE_PAL) {
                                if (XGIbios_mode[myindex].yres != 576)
                                        return -1;
                        }
                        /*  TW: LVDS/CHRONTEL does not support 720 */
-                       if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
-                           xgi_video_info.hasVB == HASVB_CHRONTEL) {
+                       if (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL ||
+                           xgifb_info->hasVB == HASVB_CHRONTEL) {
                                return -1;
                        }
                        break;
                case 1024:
-                       if (xgi_video_info.TV_type == TVMODE_NTSC) {
+                       if (xgifb_info->TV_type == TVMODE_NTSC) {
                                if (XGIbios_mode[myindex].bpp == 32)
                                        return -1;
                        }
@@ -795,10 +714,12 @@ static int XGIfb_validate_mode(int myindex)
                        return -1;
                }
                break;
-       case DISPTYPE_CRT2:
+       case XGIFB_DISP_CRT:
                if (XGIbios_mode[myindex].xres > 1280)
                        return -1;
                break;
+       case XGIFB_DISP_NONE:
+               break;
        }
        return myindex;
 
@@ -823,49 +744,52 @@ static void XGIfb_search_crt2type(const char *name)
                printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
 }
 
-static u8 XGIfb_search_refresh_rate(unsigned int rate)
+static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info,
+                                   unsigned int rate)
 {
        u16 xres, yres;
        int i = 0;
 
-       xres = XGIbios_mode[xgifb_mode_idx].xres;
-       yres = XGIbios_mode[xgifb_mode_idx].yres;
+       xres = XGIbios_mode[xgifb_info->mode_idx].xres;
+       yres = XGIbios_mode[xgifb_info->mode_idx].yres;
 
-       XGIfb_rate_idx = 0;
+       xgifb_info->rate_idx = 0;
        while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
                if ((XGIfb_vrate[i].xres == xres) &&
                    (XGIfb_vrate[i].yres == yres)) {
                        if (XGIfb_vrate[i].refresh == rate) {
-                               XGIfb_rate_idx = XGIfb_vrate[i].idx;
+                               xgifb_info->rate_idx = XGIfb_vrate[i].idx;
                                break;
                        } else if (XGIfb_vrate[i].refresh > rate) {
                                if ((XGIfb_vrate[i].refresh - rate) <= 3) {
                                        DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
                                                rate, XGIfb_vrate[i].refresh);
-                                       XGIfb_rate_idx = XGIfb_vrate[i].idx;
-                                       xgi_video_info.refresh_rate =
+                                       xgifb_info->rate_idx =
+                                               XGIfb_vrate[i].idx;
+                                       xgifb_info->refresh_rate =
                                                XGIfb_vrate[i].refresh;
                                } else if (((rate - XGIfb_vrate[i - 1].refresh)
                                                <= 2) && (XGIfb_vrate[i].idx
                                                != 1)) {
                                        DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
                                                rate, XGIfb_vrate[i-1].refresh);
-                                       XGIfb_rate_idx = XGIfb_vrate[i - 1].idx;
-                                       xgi_video_info.refresh_rate =
+                                       xgifb_info->rate_idx =
+                                               XGIfb_vrate[i - 1].idx;
+                                       xgifb_info->refresh_rate =
                                                XGIfb_vrate[i - 1].refresh;
                                }
                                break;
                        } else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
                                DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
                                        rate, XGIfb_vrate[i].refresh);
-                               XGIfb_rate_idx = XGIfb_vrate[i].idx;
+                               xgifb_info->rate_idx = XGIfb_vrate[i].idx;
                                break;
                        }
                }
                i++;
        }
-       if (XGIfb_rate_idx > 0) {
-               return XGIfb_rate_idx;
+       if (xgifb_info->rate_idx > 0) {
+               return xgifb_info->rate_idx;
        } else {
                printk(KERN_INFO "XGIfb: Unsupported rate %d for %dx%d\n",
                       rate, xres, yres);
@@ -891,13 +815,14 @@ static void XGIfb_search_tvstd(const char *name)
 
 /* ----------- FBDev related routines for all series ----------- */
 
-static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
+static void XGIfb_bpp_to_var(struct xgifb_video_info *xgifb_info,
+                            struct fb_var_screeninfo *var)
 {
        switch (var->bits_per_pixel) {
        case 8:
                var->red.offset = var->green.offset = var->blue.offset = 0;
                var->red.length = var->green.length = var->blue.length = 6;
-               xgi_video_info.video_cmap_len = 256;
+               xgifb_info->video_cmap_len = 256;
                break;
        case 16:
                var->red.offset = 11;
@@ -908,7 +833,7 @@ static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
                var->blue.length = 5;
                var->transp.offset = 0;
                var->transp.length = 0;
-               xgi_video_info.video_cmap_len = 16;
+               xgifb_info->video_cmap_len = 16;
                break;
        case 32:
                var->red.offset = 16;
@@ -919,45 +844,45 @@ static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
                var->blue.length = 8;
                var->transp.offset = 24;
                var->transp.length = 8;
-               xgi_video_info.video_cmap_len = 16;
+               xgifb_info->video_cmap_len = 16;
                break;
        }
 }
 
 /* --------------------- SetMode routines ------------------------- */
 
-static void XGIfb_pre_setmode(void)
+static void XGIfb_pre_setmode(struct xgifb_video_info *xgifb_info)
 {
        u8 cr30 = 0, cr31 = 0;
 
        cr31 = xgifb_reg_get(XGICR, 0x31);
        cr31 &= ~0x60;
 
-       switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
-       case DISPTYPE_CRT2:
+       switch (xgifb_info->display2) {
+       case XGIFB_DISP_CRT:
                cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
                cr31 |= XGI_DRIVER_MODE;
                break;
-       case DISPTYPE_LCD:
+       case XGIFB_DISP_LCD:
                cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
                cr31 |= XGI_DRIVER_MODE;
                break;
-       case DISPTYPE_TV:
-               if (xgi_video_info.TV_type == TVMODE_HIVISION)
+       case XGIFB_DISP_TV:
+               if (xgifb_info->TV_type == TVMODE_HIVISION)
                        cr30 = (XGI_VB_OUTPUT_HIVISION
                                        | XGI_SIMULTANEOUS_VIEW_ENABLE);
-               else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
+               else if (xgifb_info->TV_plug == TVPLUG_SVIDEO)
                        cr30 = (XGI_VB_OUTPUT_SVIDEO
                                        | XGI_SIMULTANEOUS_VIEW_ENABLE);
-               else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
+               else if (xgifb_info->TV_plug == TVPLUG_COMPOSITE)
                        cr30 = (XGI_VB_OUTPUT_COMPOSITE
                                        | XGI_SIMULTANEOUS_VIEW_ENABLE);
-               else if (xgi_video_info.TV_plug == TVPLUG_SCART)
+               else if (xgifb_info->TV_plug == TVPLUG_SCART)
                        cr30 = (XGI_VB_OUTPUT_SCART
                                        | XGI_SIMULTANEOUS_VIEW_ENABLE);
                cr31 |= XGI_DRIVER_MODE;
 
-               if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
+               if (XGIfb_tvmode == 1 || xgifb_info->TV_type == TVMODE_PAL)
                        cr31 |= 0x01;
                else
                        cr31 &= ~0x01;
@@ -969,10 +894,11 @@ static void XGIfb_pre_setmode(void)
 
        xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
        xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
-       xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
+       xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR33,
+                                               (xgifb_info->rate_idx & 0x0F));
 }
 
-static void XGIfb_post_setmode(void)
+static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info)
 {
        u8 reg;
        unsigned char doit = 1;
@@ -982,21 +908,21 @@ static void XGIfb_post_setmode(void)
        xgifb_reg_and_or(XGISR,0x0E, 0xF0, 0x01);
        *test*
        */
-       if (xgi_video_info.video_bpp == 8) {
+       if (xgifb_info->video_bpp == 8) {
                /* TW: We can't switch off CRT1 on LVDS/Chrontel
                 * in 8bpp Modes */
-               if ((xgi_video_info.hasVB == HASVB_LVDS) ||
-                   (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
+               if ((xgifb_info->hasVB == HASVB_LVDS) ||
+                   (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL)) {
                        doit = 0;
                }
                /* TW: We can't switch off CRT1 on 301B-DH
                 * in 8bpp Modes if using LCD */
-               if (xgi_video_info.disp_state & DISPTYPE_LCD)
+               if (xgifb_info->display2 == XGIFB_DISP_LCD)
                        doit = 0;
        }
 
        /* TW: We can't switch off CRT1 if bridge is in slave mode */
-       if (xgi_video_info.hasVB != HASVB_NONE) {
+       if (xgifb_info->hasVB != HASVB_NONE) {
                reg = xgifb_reg_get(XGIPART1, 0x00);
 
                if ((reg & 0x50) == 0x10)
@@ -1015,49 +941,54 @@ static void XGIfb_post_setmode(void)
 
        xgifb_reg_and(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
 
-       if ((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB
-                       == HASVB_301)) {
+       if (xgifb_info->display2 == XGIFB_DISP_TV &&
+           xgifb_info->hasVB == HASVB_301) {
 
                reg = xgifb_reg_get(XGIPART4, 0x01);
 
                if (reg < 0xB0) { /* Set filter for XGI301 */
-                       switch (xgi_video_info.video_width) {
+                       int filter_tb;
+
+                       switch (xgifb_info->video_width) {
                        case 320:
-                               filter_tb = (xgi_video_info.TV_type ==
+                               filter_tb = (xgifb_info->TV_type ==
                                             TVMODE_NTSC) ? 4 : 12;
                                break;
                        case 640:
-                               filter_tb = (xgi_video_info.TV_type ==
+                               filter_tb = (xgifb_info->TV_type ==
                                             TVMODE_NTSC) ? 5 : 13;
                                break;
                        case 720:
-                               filter_tb = (xgi_video_info.TV_type ==
+                               filter_tb = (xgifb_info->TV_type ==
                                             TVMODE_NTSC) ? 6 : 14;
                                break;
                        case 800:
-                               filter_tb = (xgi_video_info.TV_type ==
+                               filter_tb = (xgifb_info->TV_type ==
                                             TVMODE_NTSC) ? 7 : 15;
                                break;
                        default:
+                               filter_tb = 0;
                                filter = -1;
                                break;
                        }
-                       xgifb_reg_or(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
+                       xgifb_reg_or(XGIPART1,
+                                    IND_XGI_CRT2_WRITE_ENABLE_315,
+                                    0x01);
 
-                       if (xgi_video_info.TV_type == TVMODE_NTSC) {
+                       if (xgifb_info->TV_type == TVMODE_NTSC) {
 
                                xgifb_reg_and(XGIPART2, 0x3a, 0x1f);
 
-                               if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
+                               if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
 
                                        xgifb_reg_and(XGIPART2, 0x30, 0xdf);
 
-                               } else if (xgi_video_info.TV_plug
+                               } else if (xgifb_info->TV_plug
                                                == TVPLUG_COMPOSITE) {
 
                                        xgifb_reg_or(XGIPART2, 0x30, 0x20);
 
-                                       switch (xgi_video_info.video_width) {
+                                       switch (xgifb_info->video_width) {
                                        case 640:
                                                xgifb_reg_set(XGIPART2,
                                                              0x35,
@@ -1103,20 +1034,20 @@ static void XGIfb_post_setmode(void)
                                        }
                                }
 
-                       } else if (xgi_video_info.TV_type == TVMODE_PAL) {
+                       } else if (xgifb_info->TV_type == TVMODE_PAL) {
 
                                xgifb_reg_and(XGIPART2, 0x3A, 0x1F);
 
-                               if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
+                               if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
 
                                        xgifb_reg_and(XGIPART2, 0x30, 0xDF);
 
-                               } else if (xgi_video_info.TV_plug
+                               } else if (xgifb_info->TV_plug
                                                == TVPLUG_COMPOSITE) {
 
                                        xgifb_reg_or(XGIPART2, 0x30, 0x20);
 
-                                       switch (xgi_video_info.video_width) {
+                                       switch (xgifb_info->video_width) {
                                        case 640:
                                                xgifb_reg_set(XGIPART2,
                                                              0x35,
@@ -1203,7 +1134,8 @@ static void XGIfb_post_setmode(void)
 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
                struct fb_info *info)
 {
-
+       struct xgifb_video_info *xgifb_info = info->par;
+       struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info;
        unsigned int htotal = var->left_margin + var->xres + var->right_margin
                        + var->hsync_len;
        unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
@@ -1241,58 +1173,61 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
        if (var->pixclock && htotal && vtotal) {
                drate = 1000000000 / var->pixclock;
                hrate = (drate * 1000) / htotal;
-               xgi_video_info.refresh_rate = (unsigned int) (hrate * 2
+               xgifb_info->refresh_rate = (unsigned int) (hrate * 2
                                / vtotal);
        } else {
-               xgi_video_info.refresh_rate = 60;
+               xgifb_info->refresh_rate = 60;
        }
 
        printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
               var->xres,
               var->yres,
               var->bits_per_pixel,
-              xgi_video_info.refresh_rate);
+              xgifb_info->refresh_rate);
 
-       old_mode = xgifb_mode_idx;
-       xgifb_mode_idx = 0;
+       old_mode = xgifb_info->mode_idx;
+       xgifb_info->mode_idx = 0;
 
-       while ((XGIbios_mode[xgifb_mode_idx].mode_no != 0)
-                       && (XGIbios_mode[xgifb_mode_idx].xres <= var->xres)) {
-               if ((XGIbios_mode[xgifb_mode_idx].xres == var->xres)
-                               && (XGIbios_mode[xgifb_mode_idx].yres
-                                               == var->yres)
-                               && (XGIbios_mode[xgifb_mode_idx].bpp
+       while ((XGIbios_mode[xgifb_info->mode_idx].mode_no != 0) &&
+              (XGIbios_mode[xgifb_info->mode_idx].xres <= var->xres)) {
+               if ((XGIbios_mode[xgifb_info->mode_idx].xres == var->xres) &&
+                   (XGIbios_mode[xgifb_info->mode_idx].yres == var->yres) &&
+                   (XGIbios_mode[xgifb_info->mode_idx].bpp
                                                == var->bits_per_pixel)) {
-                       XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
                        found_mode = 1;
                        break;
                }
-               xgifb_mode_idx++;
+               xgifb_info->mode_idx++;
        }
 
        if (found_mode)
-               xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
+               xgifb_info->mode_idx = XGIfb_validate_mode(xgifb_info,
+                                                       xgifb_info->mode_idx);
        else
-               xgifb_mode_idx = -1;
+               xgifb_info->mode_idx = -1;
 
-       if (xgifb_mode_idx < 0) {
+       if (xgifb_info->mode_idx < 0) {
                printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n",
                       var->xres, var->yres, var->bits_per_pixel);
-               xgifb_mode_idx = old_mode;
+               xgifb_info->mode_idx = old_mode;
                return -EINVAL;
        }
 
-       if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
-               XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
-               xgi_video_info.refresh_rate = 60;
+       if (XGIfb_search_refresh_rate(xgifb_info,
+                                     xgifb_info->refresh_rate) == 0) {
+               xgifb_info->rate_idx =
+                       XGIbios_mode[xgifb_info->mode_idx].rate_idx;
+               xgifb_info->refresh_rate = 60;
        }
 
        if (isactive) {
 
-               XGIfb_pre_setmode();
-               if (XGISetModeNew(&XGIhw_ext, XGIfb_mode_no) == 0) {
+               XGIfb_pre_setmode(xgifb_info);
+               if (XGISetModeNew(hw_info,
+                                 XGIbios_mode[xgifb_info->mode_idx].mode_no)
+                                       == 0) {
                        printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n",
-                              XGIfb_mode_no);
+                              XGIbios_mode[xgifb_info->mode_idx].mode_no);
                        return -EINVAL;
                }
                info->fix.line_length = ((info->var.xres_virtual
@@ -1305,67 +1240,69 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
                              0x0E,
                              (info->fix.line_length & 0xff00) >> 8);
 
-               XGIfb_post_setmode();
+               XGIfb_post_setmode(xgifb_info);
 
                DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
-                               XGIbios_mode[xgifb_mode_idx].xres,
-                               XGIbios_mode[xgifb_mode_idx].yres,
-                               XGIbios_mode[xgifb_mode_idx].bpp,
-                               xgi_video_info.refresh_rate);
-
-               xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
-               xgi_video_info.video_vwidth = info->var.xres_virtual;
-               xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
-               xgi_video_info.video_vheight = info->var.yres_virtual;
-               xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
-               xgi_video_info.org_x = xgi_video_info.org_y = 0;
-               xgi_video_info.video_linelength = info->var.xres_virtual
-                               * (xgi_video_info.video_bpp >> 3);
-               switch (xgi_video_info.video_bpp) {
+                               XGIbios_mode[xgifb_info->mode_idx].xres,
+                               XGIbios_mode[xgifb_info->mode_idx].yres,
+                               XGIbios_mode[xgifb_info->mode_idx].bpp,
+                               xgifb_info->refresh_rate);
+
+               xgifb_info->video_bpp = XGIbios_mode[xgifb_info->mode_idx].bpp;
+               xgifb_info->video_vwidth = info->var.xres_virtual;
+               xgifb_info->video_width =
+                       XGIbios_mode[xgifb_info->mode_idx].xres;
+               xgifb_info->video_vheight = info->var.yres_virtual;
+               xgifb_info->video_height =
+                       XGIbios_mode[xgifb_info->mode_idx].yres;
+               xgifb_info->org_x = xgifb_info->org_y = 0;
+               xgifb_info->video_linelength = info->var.xres_virtual
+                               * (xgifb_info->video_bpp >> 3);
+               switch (xgifb_info->video_bpp) {
                case 8:
-                       xgi_video_info.DstColor = 0x0000;
-                       xgi_video_info.XGI310_AccelDepth = 0x00000000;
-                       xgi_video_info.video_cmap_len = 256;
+                       xgifb_info->DstColor = 0x0000;
+                       xgifb_info->XGI310_AccelDepth = 0x00000000;
+                       xgifb_info->video_cmap_len = 256;
 #if defined(__powerpc__)
                        cr_data = xgifb_reg_get(XGICR, 0x4D);
                        xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0));
 #endif
                        break;
                case 16:
-                       xgi_video_info.DstColor = 0x8000;
-                       xgi_video_info.XGI310_AccelDepth = 0x00010000;
+                       xgifb_info->DstColor = 0x8000;
+                       xgifb_info->XGI310_AccelDepth = 0x00010000;
 #if defined(__powerpc__)
                        cr_data = xgifb_reg_get(XGICR, 0x4D);
                        xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
 #endif
-                       xgi_video_info.video_cmap_len = 16;
+                       xgifb_info->video_cmap_len = 16;
                        break;
                case 32:
-                       xgi_video_info.DstColor = 0xC000;
-                       xgi_video_info.XGI310_AccelDepth = 0x00020000;
-                       xgi_video_info.video_cmap_len = 16;
+                       xgifb_info->DstColor = 0xC000;
+                       xgifb_info->XGI310_AccelDepth = 0x00020000;
+                       xgifb_info->video_cmap_len = 16;
 #if defined(__powerpc__)
                        cr_data = xgifb_reg_get(XGICR, 0x4D);
                        xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
 #endif
                        break;
                default:
-                       xgi_video_info.video_cmap_len = 16;
+                       xgifb_info->video_cmap_len = 16;
                        printk(KERN_ERR "XGIfb: Unsupported depth %d",
-                              xgi_video_info.video_bpp);
+                              xgifb_info->video_bpp);
                        break;
                }
        }
-       XGIfb_bpp_to_var(var); /*update ARGB info*/
+       XGIfb_bpp_to_var(xgifb_info, var); /*update ARGB info*/
        DEBUGPRN("End of do_set_var");
 
        dumpVGAReg();
        return 0;
 }
 
-#ifdef XGIFB_PAN
 static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+       struct xgifb_video_info *xgifb_info = info->par;
        unsigned int base;
 
        /* printk("Inside pan_var"); */
@@ -1393,8 +1330,8 @@ static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
        xgifb_reg_set(XGISR, 0x37, (base >> 24) & 0x03);
        xgifb_reg_and_or(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
 
-       if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
-               xgifb_reg_or(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
+       if (xgifb_info->display2 != XGIFB_DISP_NONE) {
+               xgifb_reg_or(XGIPART1, IND_XGI_CRT2_WRITE_ENABLE_315, 0x01);
                xgifb_reg_set(XGIPART1, 0x06, (base & 0xFF));
                xgifb_reg_set(XGIPART1, 0x05, ((base >> 8) & 0xFF));
                xgifb_reg_set(XGIPART1, 0x04, ((base >> 16) & 0xFF));
@@ -1406,7 +1343,6 @@ static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
        /* printk("End of pan_var"); */
        return 0;
 }
-#endif
 
 static int XGIfb_open(struct fb_info *info, int user)
 {
@@ -1439,6 +1375,8 @@ static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
                unsigned blue, unsigned transp, struct fb_info *info)
 {
+       struct xgifb_video_info *xgifb_info = info->par;
+
        if (regno >= XGIfb_get_cmap_len(&info->var))
                return 1;
 
@@ -1448,7 +1386,7 @@ static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
                outb((red >> 10), XGIDACD);
                outb((green >> 10), XGIDACD);
                outb((blue >> 10), XGIDACD);
-               if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
+               if (xgifb_info->display2 != XGIFB_DISP_NONE) {
                        outb(regno, XGIDAC2A);
                        outb((red >> 8), XGIDAC2D);
                        outb((green >> 8), XGIDAC2D);
@@ -1476,30 +1414,28 @@ static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
                struct fb_info *info)
 {
+       struct xgifb_video_info *xgifb_info = info->par;
+
        DEBUGPRN("inside get_fix");
        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
-       strcpy(fix->id, myid);
+       fix->smem_start = xgifb_info->video_base;
 
-       fix->smem_start = xgi_video_info.video_base;
+       fix->smem_len = xgifb_info->video_size;
 
-       fix->smem_len = xgi_video_info.video_size;
-
-       fix->type = video_type;
+       fix->type = FB_TYPE_PACKED_PIXELS;
        fix->type_aux = 0;
-       if (xgi_video_info.video_bpp == 8)
+       if (xgifb_info->video_bpp == 8)
                fix->visual = FB_VISUAL_PSEUDOCOLOR;
        else
                fix->visual = FB_VISUAL_DIRECTCOLOR;
        fix->xpanstep = 0;
-#ifdef XGIFB_PAN
        if (XGIfb_ypan)
                fix->ypanstep = 1;
-#endif
        fix->ywrapstep = 0;
-       fix->line_length = xgi_video_info.video_linelength;
-       fix->mmio_start = xgi_video_info.mmio_base;
-       fix->mmio_len = xgi_video_info.mmio_size;
+       fix->line_length = xgifb_info->video_linelength;
+       fix->mmio_start = xgifb_info->mmio_base;
+       fix->mmio_len = xgifb_info->mmio_size;
        fix->accel = FB_ACCEL_XGI_XABRE;
 
        DEBUGPRN("end of get_fix");
@@ -1521,6 +1457,7 @@ static int XGIfb_set_par(struct fb_info *info)
 
 static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+       struct xgifb_video_info *xgifb_info = info->par;
        unsigned int htotal = var->left_margin + var->xres + var->right_margin
                        + var->hsync_len;
        unsigned int vtotal = 0;
@@ -1551,15 +1488,15 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        if (var->pixclock && htotal && vtotal) {
                drate = 1000000000 / var->pixclock;
                hrate = (drate * 1000) / htotal;
-               xgi_video_info.refresh_rate =
+               xgifb_info->refresh_rate =
                        (unsigned int) (hrate * 2 / vtotal);
                printk(KERN_DEBUG
                        "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
                        "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
                        __func__, var->pixclock, htotal, vtotal,
-                       __func__, drate, hrate, xgi_video_info.refresh_rate);
+                       __func__, drate, hrate, xgifb_info->refresh_rate);
        } else {
-               xgi_video_info.refresh_rate = 60;
+               xgifb_info->refresh_rate = 60;
        }
 
        /*
@@ -1581,7 +1518,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
                if ((XGIbios_mode[search_idx].xres == var->xres) &&
                        (XGIbios_mode[search_idx].yres == var->yres) &&
                        (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
-                       if (XGIfb_validate_mode(search_idx) > 0) {
+                       if (XGIfb_validate_mode(xgifb_info, search_idx) > 0) {
                                found_mode = 1;
                                break;
                        }
@@ -1599,7 +1536,8 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
                            (var->yres <= XGIbios_mode[search_idx].yres) &&
                            (var->bits_per_pixel ==
                             XGIbios_mode[search_idx].bpp)) {
-                               if (XGIfb_validate_mode(search_idx) > 0) {
+                               if (XGIfb_validate_mode(xgifb_info,
+                                                       search_idx) > 0) {
                                        found_mode = 1;
                                        break;
                                }
@@ -1622,7 +1560,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        /* TW: TODO: Check the refresh rate */
 
        /* Adapt RGB settings */
-       XGIfb_bpp_to_var(var);
+       XGIfb_bpp_to_var(xgifb_info, var);
 
        /* Sanity check for offsets */
        if (var->xoffset < 0)
@@ -1638,7 +1576,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        } /* else { */
                /* TW: Now patch yres_virtual if we use panning */
                /* May I do this? */
-               /* var->yres_virtual = xgi_video_info.heapstart /
+               /* var->yres_virtual = xgifb_info->heapstart /
                        (var->xres * (var->bits_per_pixel >> 3)); */
                /* if (var->yres_virtual <= var->yres) { */
                /* TW: Paranoia check */
@@ -1663,7 +1601,6 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        return 0;
 }
 
-#ifdef XGIFB_PAN
 static int XGIfb_pan_display(struct fb_var_screeninfo *var,
                struct fb_info *info)
 {
@@ -1700,10 +1637,10 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var,
        /* printk("End of pan_display\n"); */
        return 0;
 }
-#endif
 
 static int XGIfb_blank(int blank, struct fb_info *info)
 {
+       struct xgifb_video_info *xgifb_info = info->par;
        u8 reg;
 
        reg = xgifb_reg_get(XGICR, 0x17);
@@ -1726,9 +1663,7 @@ static struct fb_ops XGIfb_ops = {
        .fb_check_var = XGIfb_check_var,
        .fb_set_par = XGIfb_set_par,
        .fb_setcolreg = XGIfb_setcolreg,
-#ifdef XGIFB_PAN
        .fb_pan_display = XGIfb_pan_display,
-#endif
        .fb_blank = XGIfb_blank,
        .fb_fillrect = cfb_fillrect,
        .fb_copyarea = cfb_copyarea,
@@ -1740,51 +1675,51 @@ static struct fb_ops XGIfb_ops = {
 
 /* for XGI 315/550/650/740/330 */
 
-static int XGIfb_get_dram_size(void)
+static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info)
 {
 
        u8 ChannelNum, tmp;
        u8 reg = 0;
 
        /* xorg driver sets 32MB * 1 channel */
-       if (xgi_video_info.chip == XG27)
+       if (xgifb_info->chip == XG27)
                xgifb_reg_set(XGISR, IND_XGI_DRAM_SIZE, 0x51);
 
        reg = xgifb_reg_get(XGISR, IND_XGI_DRAM_SIZE);
        switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
        case XGI_DRAM_SIZE_1MB:
-               xgi_video_info.video_size = 0x100000;
+               xgifb_info->video_size = 0x100000;
                break;
        case XGI_DRAM_SIZE_2MB:
-               xgi_video_info.video_size = 0x200000;
+               xgifb_info->video_size = 0x200000;
                break;
        case XGI_DRAM_SIZE_4MB:
-               xgi_video_info.video_size = 0x400000;
+               xgifb_info->video_size = 0x400000;
                break;
        case XGI_DRAM_SIZE_8MB:
-               xgi_video_info.video_size = 0x800000;
+               xgifb_info->video_size = 0x800000;
                break;
        case XGI_DRAM_SIZE_16MB:
-               xgi_video_info.video_size = 0x1000000;
+               xgifb_info->video_size = 0x1000000;
                break;
        case XGI_DRAM_SIZE_32MB:
-               xgi_video_info.video_size = 0x2000000;
+               xgifb_info->video_size = 0x2000000;
                break;
        case XGI_DRAM_SIZE_64MB:
-               xgi_video_info.video_size = 0x4000000;
+               xgifb_info->video_size = 0x4000000;
                break;
        case XGI_DRAM_SIZE_128MB:
-               xgi_video_info.video_size = 0x8000000;
+               xgifb_info->video_size = 0x8000000;
                break;
        case XGI_DRAM_SIZE_256MB:
-               xgi_video_info.video_size = 0x10000000;
+               xgifb_info->video_size = 0x10000000;
                break;
        default:
                return -1;
        }
 
        tmp = (reg & 0x0c) >> 2;
-       switch (xgi_video_info.chip) {
+       switch (xgifb_info->chip) {
        case XG20:
        case XG21:
        case XG27:
@@ -1820,25 +1755,25 @@ static int XGIfb_get_dram_size(void)
                break;
        }
 
-       xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
+       xgifb_info->video_size = xgifb_info->video_size * ChannelNum;
        /* PLiad fixed for benchmarking and fb set */
-       /* xgi_video_info.video_size = 0x200000; */ /* 1024x768x16 */
-       /* xgi_video_info.video_size = 0x1000000; */ /* benchmark */
+       /* xgifb_info->video_size = 0x200000; */ /* 1024x768x16 */
+       /* xgifb_info->video_size = 0x1000000; */ /* benchmark */
 
        printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",
               reg,
-              xgi_video_info.video_size, ChannelNum);
+              xgifb_info->video_size, ChannelNum);
        return 0;
 
 }
 
-static void XGIfb_detect_VB(void)
+static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info)
 {
        u8 cr32, temp = 0;
 
-       xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
+       xgifb_info->TV_plug = xgifb_info->TV_type = 0;
 
-       switch (xgi_video_info.hasVB) {
+       switch (xgifb_info->hasVB) {
        case HASVB_LVDS_CHRONTEL:
        case HASVB_CHRONTEL:
                break;
@@ -1861,35 +1796,35 @@ static void XGIfb_detect_VB(void)
 
        if (XGIfb_crt2type != -1)
                /* TW: Override with option */
-               xgi_video_info.disp_state = XGIfb_crt2type;
+               xgifb_info->display2 = XGIfb_crt2type;
        else if (cr32 & XGI_VB_TV)
-               xgi_video_info.disp_state = DISPTYPE_TV;
+               xgifb_info->display2 = XGIFB_DISP_TV;
        else if (cr32 & XGI_VB_LCD)
-               xgi_video_info.disp_state = DISPTYPE_LCD;
+               xgifb_info->display2 = XGIFB_DISP_LCD;
        else if (cr32 & XGI_VB_CRT2)
-               xgi_video_info.disp_state = DISPTYPE_CRT2;
+               xgifb_info->display2 = XGIFB_DISP_CRT;
        else
-               xgi_video_info.disp_state = 0;
+               xgifb_info->display2 = XGIFB_DISP_NONE;
 
        if (XGIfb_tvplug != -1)
                /* PR/TW: Override with option */
-               xgi_video_info.TV_plug = XGIfb_tvplug;
+               xgifb_info->TV_plug = XGIfb_tvplug;
        else if (cr32 & XGI_VB_HIVISION) {
-               xgi_video_info.TV_type = TVMODE_HIVISION;
-               xgi_video_info.TV_plug = TVPLUG_SVIDEO;
+               xgifb_info->TV_type = TVMODE_HIVISION;
+               xgifb_info->TV_plug = TVPLUG_SVIDEO;
        } else if (cr32 & XGI_VB_SVIDEO)
-               xgi_video_info.TV_plug = TVPLUG_SVIDEO;
+               xgifb_info->TV_plug = TVPLUG_SVIDEO;
        else if (cr32 & XGI_VB_COMPOSITE)
-               xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
+               xgifb_info->TV_plug = TVPLUG_COMPOSITE;
        else if (cr32 & XGI_VB_SCART)
-               xgi_video_info.TV_plug = TVPLUG_SCART;
+               xgifb_info->TV_plug = TVPLUG_SCART;
 
-       if (xgi_video_info.TV_type == 0) {
+       if (xgifb_info->TV_type == 0) {
                temp = xgifb_reg_get(XGICR, 0x38);
                if (temp & 0x10)
-                       xgi_video_info.TV_type = TVMODE_PAL;
+                       xgifb_info->TV_type = TVMODE_PAL;
                else
-                       xgi_video_info.TV_type = TVMODE_NTSC;
+                       xgifb_info->TV_type = TVMODE_NTSC;
        }
 
        /* TW: Copy forceCRT1 option to CRT1off if option is given */
@@ -1901,37 +1836,37 @@ static void XGIfb_detect_VB(void)
        }
 }
 
-static int XGIfb_has_VB(void)
+static int XGIfb_has_VB(struct xgifb_video_info *xgifb_info)
 {
        u8 vb_chipid;
 
        vb_chipid = xgifb_reg_get(XGIPART4, 0x00);
        switch (vb_chipid) {
        case 0x01:
-               xgi_video_info.hasVB = HASVB_301;
+               xgifb_info->hasVB = HASVB_301;
                break;
        case 0x02:
-               xgi_video_info.hasVB = HASVB_302;
+               xgifb_info->hasVB = HASVB_302;
                break;
        default:
-               xgi_video_info.hasVB = HASVB_NONE;
+               xgifb_info->hasVB = HASVB_NONE;
                return 0;
        }
        return 1;
 }
 
-static void XGIfb_get_VB_type(void)
+static void XGIfb_get_VB_type(struct xgifb_video_info *xgifb_info)
 {
        u8 reg;
 
-       if (!XGIfb_has_VB()) {
+       if (!XGIfb_has_VB(xgifb_info)) {
                reg = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR37);
                switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
                case XGI310_EXTERNAL_CHIP_LVDS:
-                       xgi_video_info.hasVB = HASVB_LVDS;
+                       xgifb_info->hasVB = HASVB_LVDS;
                        break;
                case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
-                       xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
+                       xgifb_info->hasVB = HASVB_LVDS_CHRONTEL;
                        break;
                default:
                        break;
@@ -1939,49 +1874,47 @@ static void XGIfb_get_VB_type(void)
        }
 }
 
-XGIINITSTATIC int __init XGIfb_setup(char *options)
+static int __init xgifb_optval(char *fullopt, int validx)
 {
-       char *this_opt;
+       unsigned long lres;
 
-       xgi_video_info.refresh_rate = 0;
+       if (kstrtoul(fullopt + validx, 0, &lres) < 0 || lres > INT_MAX) {
+               pr_err("xgifb: invalid value for option: %s\n", fullopt);
+               return 0;
+       }
+       return lres;
+}
 
-       printk(KERN_INFO "XGIfb: Options %s\n", options);
+static int __init XGIfb_setup(char *options)
+{
+       char *this_opt;
 
        if (!options || !*options)
                return 0;
 
+       pr_info("xgifb: options: %s\n", options);
+
        while ((this_opt = strsep(&options, ",")) != NULL) {
 
                if (!*this_opt)
                        continue;
 
                if (!strncmp(this_opt, "mode:", 5)) {
-                       XGIfb_search_mode(this_opt + 5);
-               } else if (!strncmp(this_opt, "vesa:", 5)) {
-                       XGIfb_search_vesamode(simple_strtoul(
-                                               this_opt + 5, NULL, 0));
-               } else if (!strncmp(this_opt, "mode:", 5)) {
-                       XGIfb_search_mode(this_opt + 5);
+                       mode = this_opt + 5;
                } else if (!strncmp(this_opt, "vesa:", 5)) {
-                       XGIfb_search_vesamode(simple_strtoul(
-                                               this_opt + 5, NULL, 0));
+                       vesa = xgifb_optval(this_opt, 5);
                } else if (!strncmp(this_opt, "vrate:", 6)) {
-                       xgi_video_info.refresh_rate = simple_strtoul(
-                                               this_opt + 6, NULL, 0);
+                       refresh_rate = xgifb_optval(this_opt, 6);
                } else if (!strncmp(this_opt, "rate:", 5)) {
-                       xgi_video_info.refresh_rate = simple_strtoul(
-                                               this_opt + 5, NULL, 0);
-               } else if (!strncmp(this_opt, "off", 3)) {
-                       XGIfb_off = 1;
+                       refresh_rate = xgifb_optval(this_opt, 5);
                } else if (!strncmp(this_opt, "crt1off", 7)) {
                        XGIfb_crt1off = 1;
                } else if (!strncmp(this_opt, "filter:", 7)) {
-                       filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
+                       filter = xgifb_optval(this_opt, 7);
                } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
                        XGIfb_search_crt2type(this_opt + 14);
                } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
-                       XGIfb_forcecrt1 = (int)simple_strtoul(
-                                               this_opt + 10, NULL, 0);
+                       XGIfb_forcecrt1 = xgifb_optval(this_opt, 10);
                } else if (!strncmp(this_opt, "tvmode:", 7)) {
                        XGIfb_search_tvstd(this_opt + 7);
                } else if (!strncmp(this_opt, "tvstandard:", 11)) {
@@ -1989,32 +1922,15 @@ XGIINITSTATIC int __init XGIfb_setup(char *options)
                } else if (!strncmp(this_opt, "dstn", 4)) {
                        enable_dstn = 1;
                        /* TW: DSTN overrules forcecrt2type */
-                       XGIfb_crt2type = DISPTYPE_LCD;
-               } else if (!strncmp(this_opt, "pdc:", 4)) {
-                       XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
-                       if (XGIfb_pdc & ~0x3c) {
-                               printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
-                               XGIfb_pdc = 0;
-                       }
+                       XGIfb_crt2type = XGIFB_DISP_LCD;
                } else if (!strncmp(this_opt, "noypan", 6)) {
                        XGIfb_ypan = 0;
                } else if (!strncmp(this_opt, "userom:", 7)) {
-                       XGIfb_userom = (int)simple_strtoul(
-                                               this_opt + 7, NULL, 0);
-                       /* } else if (!strncmp(this_opt, "useoem:", 7)) { */
-                       /* XGIfb_useoem = (int)simple_strtoul(
-                                               this_opt + 7, NULL, 0); */
+                       XGIfb_userom = xgifb_optval(this_opt, 7);
                } else {
-                       XGIfb_search_mode(this_opt);
-                       /* printk(KERN_INFO "XGIfb: Invalid option %s\n",
-                                 this_opt); */
+                       mode = this_opt;
                }
-
-               /* TW: Panning only with acceleration */
-               XGIfb_ypan = 0;
-
        }
-       printk("\nxgifb: outa xgifb_setup 3450");
        return 0;
 }
 
@@ -2046,44 +1962,46 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
        u8 reg, reg1;
        u8 CR48, CR38;
        int ret;
+       bool xgi21_drvlcdcaplist = false;
+       struct fb_info *fb_info;
+       struct xgifb_video_info *xgifb_info;
+       struct xgi_hw_device_info *hw_info;
 
-       if (XGIfb_off)
-               return -ENXIO;
-
-       XGIfb_registered = 0;
-
-       memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
-       fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
+       fb_info = framebuffer_alloc(sizeof(*xgifb_info), &pdev->dev);
        if (!fb_info)
                return -ENOMEM;
 
-       xgi_video_info.chip_id = pdev->device;
+       xgifb_info = fb_info->par;
+       hw_info = &xgifb_info->hw_info;
+       xgifb_info->fb_info = fb_info;
+       xgifb_info->chip_id = pdev->device;
        pci_read_config_byte(pdev,
                             PCI_REVISION_ID,
-                            &xgi_video_info.revision_id);
-       XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
-
-       xgi_video_info.pcibus = pdev->bus->number;
-       xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
-       xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
-       xgi_video_info.subsysvendor = pdev->subsystem_vendor;
-       xgi_video_info.subsysdevice = pdev->subsystem_device;
-
-       xgi_video_info.video_base = pci_resource_start(pdev, 0);
-       xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
-       xgi_video_info.mmio_size = pci_resource_len(pdev, 1);
-       xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
-       XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
+                            &xgifb_info->revision_id);
+       hw_info->jChipRevision = xgifb_info->revision_id;
+
+       xgifb_info->pcibus = pdev->bus->number;
+       xgifb_info->pcislot = PCI_SLOT(pdev->devfn);
+       xgifb_info->pcifunc = PCI_FUNC(pdev->devfn);
+       xgifb_info->subsysvendor = pdev->subsystem_vendor;
+       xgifb_info->subsysdevice = pdev->subsystem_device;
+
+       xgifb_info->video_base = pci_resource_start(pdev, 0);
+       xgifb_info->mmio_base = pci_resource_start(pdev, 1);
+       xgifb_info->mmio_size = pci_resource_len(pdev, 1);
+       xgifb_info->vga_base = pci_resource_start(pdev, 2) + 0x30;
+       hw_info->pjIOAddress = (unsigned char *)xgifb_info->vga_base;
        /* XGI_Pr.RelIO  = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
        printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
-              (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
+              (unsigned long)pci_resource_start(pdev, 2),
+              xgifb_info->dev_info.RelIO);
 
        if (pci_enable_device(pdev)) {
                ret = -EIO;
                goto error;
        }
 
-       XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
+       XGIRegInit(&xgifb_info->dev_info, (unsigned long)hw_info->pjIOAddress);
 
        xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
        reg1 = xgifb_reg_get(XGISR, IND_XGI_PASSWORD);
@@ -2094,417 +2012,413 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
                goto error;
        }
 
-       switch (xgi_video_info.chip_id) {
+       switch (xgifb_info->chip_id) {
        case PCI_DEVICE_ID_XG_20:
                xgifb_reg_or(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
                CR48 = xgifb_reg_get(XGICR, Index_CR_GPIO_Reg1);
                if (CR48&GPIOG_READ)
-                       xgi_video_info.chip = XG21;
+                       xgifb_info->chip = XG21;
                else
-                       xgi_video_info.chip = XG20;
-               XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+                       xgifb_info->chip = XG20;
                break;
        case PCI_DEVICE_ID_XG_40:
-               xgi_video_info.chip = XG40;
-               XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+               xgifb_info->chip = XG40;
                break;
        case PCI_DEVICE_ID_XG_41:
-               xgi_video_info.chip = XG41;
-               XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+               xgifb_info->chip = XG41;
                break;
        case PCI_DEVICE_ID_XG_42:
-               xgi_video_info.chip = XG42;
-               XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+               xgifb_info->chip = XG42;
                break;
        case PCI_DEVICE_ID_XG_27:
-               xgi_video_info.chip = XG27;
-               XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+               xgifb_info->chip = XG27;
                break;
        default:
                ret = -ENODEV;
                goto error;
        }
 
-       printk("XGIfb:chipid = %x\n", xgi_video_info.chip);
-       XGIhw_ext.jChipType = xgi_video_info.chip;
+       printk("XGIfb:chipid = %x\n", xgifb_info->chip);
+       hw_info->jChipType = xgifb_info->chip;
 
-       if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
-               XGIhw_ext.pjVirtualRomBase = xgifb_copy_rom(pdev);
-               if (XGIhw_ext.pjVirtualRomBase)
+       if ((xgifb_info->chip == XG21) || (XGIfb_userom)) {
+               hw_info->pjVirtualRomBase = xgifb_copy_rom(pdev);
+               if (hw_info->pjVirtualRomBase)
                        printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",
-                              XGIhw_ext.pjVirtualRomBase);
+                              hw_info->pjVirtualRomBase);
                else
                        printk(KERN_INFO "XGIfb: Video ROM not found\n");
        } else {
-               XGIhw_ext.pjVirtualRomBase = NULL;
+               hw_info->pjVirtualRomBase = NULL;
                printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
        }
-       XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
 
-       if (XGIfb_get_dram_size()) {
+       if (XGIfb_get_dram_size(xgifb_info)) {
                printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
                ret = -ENODEV;
                goto error;
        }
 
-       if ((xgifb_mode_idx < 0) ||
-           ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
-               /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
-               xgifb_reg_or(XGISR,
-                            IND_XGI_PCI_ADDRESS_SET,
-                            (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
-               /* Enable 2D accelerator engine */
-               xgifb_reg_or(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
-       }
+       /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
+       xgifb_reg_or(XGISR,
+                    IND_XGI_PCI_ADDRESS_SET,
+                    (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
+       /* Enable 2D accelerator engine */
+       xgifb_reg_or(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
 
-       XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
+       hw_info->ulVideoMemorySize = xgifb_info->video_size;
 
-       if (!request_mem_region(xgi_video_info.video_base,
-                               xgi_video_info.video_size,
+       if (!request_mem_region(xgifb_info->video_base,
+                               xgifb_info->video_size,
                                "XGIfb FB")) {
                printk("unable request memory size %x",
-                      xgi_video_info.video_size);
+                      xgifb_info->video_size);
                printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
                printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
                ret = -ENODEV;
                goto error;
        }
 
-       if (!request_mem_region(xgi_video_info.mmio_base,
-                               xgi_video_info.mmio_size,
+       if (!request_mem_region(xgifb_info->mmio_base,
+                               xgifb_info->mmio_size,
                                "XGIfb MMIO")) {
                printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
                ret = -ENODEV;
                goto error_0;
        }
 
-       xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
-       ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
-       xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base,
-                                           xgi_video_info.mmio_size);
+       xgifb_info->video_vbase = hw_info->pjVideoMemoryAddress =
+       ioremap(xgifb_info->video_base, xgifb_info->video_size);
+       xgifb_info->mmio_vbase = ioremap(xgifb_info->mmio_base,
+                                           xgifb_info->mmio_size);
 
        printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
-              xgi_video_info.video_base,
-              xgi_video_info.video_vbase,
-              xgi_video_info.video_size / 1024);
+              xgifb_info->video_base,
+              xgifb_info->video_vbase,
+              xgifb_info->video_size / 1024);
 
        printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
-              xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,
-              xgi_video_info.mmio_size / 1024);
+              xgifb_info->mmio_base, xgifb_info->mmio_vbase,
+              xgifb_info->mmio_size / 1024);
        printk("XGIfb: XGIInitNew() ...");
-       if (XGIInitNew(&XGIhw_ext))
+       pci_set_drvdata(pdev, xgifb_info);
+       if (XGIInitNew(pdev))
                printk("OK\n");
        else
                printk("Fail\n");
 
-       xgi_video_info.mtrr = (unsigned int) 0;
-
-       if ((xgifb_mode_idx < 0) ||
-           ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
-               xgi_video_info.hasVB = HASVB_NONE;
-               if ((xgi_video_info.chip == XG20) ||
-                   (xgi_video_info.chip == XG27)) {
-                       xgi_video_info.hasVB = HASVB_NONE;
-               } else if (xgi_video_info.chip == XG21) {
-                       CR38 = xgifb_reg_get(XGICR, 0x38);
-                       if ((CR38&0xE0) == 0xC0) {
-                               xgi_video_info.disp_state = DISPTYPE_LCD;
-                               if (!XGIfb_GetXG21LVDSData()) {
-                                       int m;
-                                       for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
-                                               if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
-                                                   (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
-                                                       xgifb_reg_set(XGI_Pr.P3d4, 0x36, m);
-                                               }
-                                       }
-                               }
-                       } else if ((CR38&0xE0) == 0x60) {
-                               xgi_video_info.hasVB = HASVB_CHRONTEL;
-                       } else {
-                               xgi_video_info.hasVB = HASVB_NONE;
-                       }
+       xgifb_info->mtrr = (unsigned int) 0;
+
+       xgifb_info->hasVB = HASVB_NONE;
+       if ((xgifb_info->chip == XG20) ||
+           (xgifb_info->chip == XG27)) {
+               xgifb_info->hasVB = HASVB_NONE;
+       } else if (xgifb_info->chip == XG21) {
+               CR38 = xgifb_reg_get(XGICR, 0x38);
+               if ((CR38&0xE0) == 0xC0) {
+                       xgifb_info->display2 = XGIFB_DISP_LCD;
+                       if (!XGIfb_GetXG21LVDSData(xgifb_info))
+                               xgi21_drvlcdcaplist = true;
+               } else if ((CR38&0xE0) == 0x60) {
+                       xgifb_info->hasVB = HASVB_CHRONTEL;
                } else {
-                       XGIfb_get_VB_type();
+                       xgifb_info->hasVB = HASVB_NONE;
                }
+       } else {
+               XGIfb_get_VB_type(xgifb_info);
+       }
 
-               XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
-
-               XGIhw_ext.ulExternalChip = 0;
+       hw_info->ujVBChipID = VB_CHIP_UNKNOWN;
 
-               switch (xgi_video_info.hasVB) {
-               case HASVB_301:
-                       reg = xgifb_reg_get(XGIPART4, 0x01);
-                       if (reg >= 0xE0) {
-                               XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
-                               printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
-                       } else if (reg >= 0xD0) {
-                               XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
-                               printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
-                       }
-                       /* else if (reg >= 0xB0) {
-                               XGIhw_ext.ujVBChipID = VB_CHIP_301B;
-                               reg1 = xgifb_reg_get(XGIPART4, 0x23);
-                               printk("XGIfb: XGI301B bridge detected\n");
-                       } */
-                       else {
-                               XGIhw_ext.ujVBChipID = VB_CHIP_301;
-                               printk("XGIfb: XGI301 bridge detected\n");
-                       }
-                       break;
-               case HASVB_302:
-                       reg = xgifb_reg_get(XGIPART4, 0x01);
-                       if (reg >= 0xE0) {
-                               XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
-                               printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
-                       } else if (reg >= 0xD0) {
-                               XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
-                               printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
-                       } else if (reg >= 0xB0) {
-                               reg1 = xgifb_reg_get(XGIPART4, 0x23);
-
-                               XGIhw_ext.ujVBChipID = VB_CHIP_302B;
+       hw_info->ulExternalChip = 0;
 
-                       } else {
-                               XGIhw_ext.ujVBChipID = VB_CHIP_302;
-                               printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
-                       }
-                       break;
-               case HASVB_LVDS:
-                       XGIhw_ext.ulExternalChip = 0x1;
-                       printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
-                       break;
-               case HASVB_TRUMPION:
-                       XGIhw_ext.ulExternalChip = 0x2;
-                       printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
-                       break;
-               case HASVB_CHRONTEL:
-                       XGIhw_ext.ulExternalChip = 0x4;
-                       printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
-                       break;
-               case HASVB_LVDS_CHRONTEL:
-                       XGIhw_ext.ulExternalChip = 0x5;
-                       printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
-                       break;
-               default:
-                       printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
-                       break;
+       switch (xgifb_info->hasVB) {
+       case HASVB_301:
+               reg = xgifb_reg_get(XGIPART4, 0x01);
+               if (reg >= 0xE0) {
+                       hw_info->ujVBChipID = VB_CHIP_302LV;
+                       printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
+               } else if (reg >= 0xD0) {
+                       hw_info->ujVBChipID = VB_CHIP_301LV;
+                       printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
                }
-
-               if (xgi_video_info.hasVB != HASVB_NONE)
-                       XGIfb_detect_VB();
-
-               if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
-                       if (XGIfb_crt1off)
-                               xgi_video_info.disp_state |= DISPMODE_SINGLE;
-                       else
-                               xgi_video_info.disp_state |= (DISPMODE_MIRROR |
-                                                             DISPTYPE_CRT1);
-               } else {
-                       xgi_video_info.disp_state = DISPMODE_SINGLE |
-                                                   DISPTYPE_CRT1;
+               /* else if (reg >= 0xB0) {
+                       hw_info->ujVBChipID = VB_CHIP_301B;
+                       reg1 = xgifb_reg_get(XGIPART4, 0x23);
+                       printk("XGIfb: XGI301B bridge detected\n");
+               } */
+               else {
+                       hw_info->ujVBChipID = VB_CHIP_301;
+                       printk("XGIfb: XGI301 bridge detected\n");
                }
+               break;
+       case HASVB_302:
+               reg = xgifb_reg_get(XGIPART4, 0x01);
+               if (reg >= 0xE0) {
+                       hw_info->ujVBChipID = VB_CHIP_302LV;
+                       printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
+               } else if (reg >= 0xD0) {
+                       hw_info->ujVBChipID = VB_CHIP_301LV;
+                       printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
+               } else if (reg >= 0xB0) {
+                       reg1 = xgifb_reg_get(XGIPART4, 0x23);
 
-               if (xgi_video_info.disp_state & DISPTYPE_LCD) {
-                       if (!enable_dstn) {
-                               reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL);
-                               reg &= 0x0f;
-                               XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
+                       hw_info->ujVBChipID = VB_CHIP_302B;
 
-                       } else {
-                               /* TW: FSTN/DSTN */
-                               XGIhw_ext.ulCRT2LCDType = LCD_320x480;
-                       }
+               } else {
+                       hw_info->ujVBChipID = VB_CHIP_302;
+                       printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
                }
+               break;
+       case HASVB_LVDS:
+               hw_info->ulExternalChip = 0x1;
+               printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
+               break;
+       case HASVB_TRUMPION:
+               hw_info->ulExternalChip = 0x2;
+               printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
+               break;
+       case HASVB_CHRONTEL:
+               hw_info->ulExternalChip = 0x4;
+               printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
+               break;
+       case HASVB_LVDS_CHRONTEL:
+               hw_info->ulExternalChip = 0x5;
+               printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
+               break;
+       default:
+               printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
+               break;
+       }
 
-               XGIfb_detectedpdc = 0;
+       if (xgifb_info->hasVB != HASVB_NONE)
+               XGIfb_detect_VB(xgifb_info);
 
-               XGIfb_detectedlcda = 0xff;
+       if (xgifb_info->display2 == XGIFB_DISP_LCD) {
+               if (!enable_dstn) {
+                       reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL);
+                       reg &= 0x0f;
+                       hw_info->ulCRT2LCDType = XGI310paneltype[reg];
 
-               /* TW: Try to find about LCDA */
+               } else {
+                       /* TW: FSTN/DSTN */
+                       hw_info->ulCRT2LCDType = LCD_320x480;
+               }
+       }
 
-               if ((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
-                               (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
-                               (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) {
-                       int tmp;
-                       tmp = xgifb_reg_get(XGICR, 0x34);
-                       if (tmp <= 0x13) {
+       if ((hw_info->ujVBChipID == VB_CHIP_302B) ||
+                       (hw_info->ujVBChipID == VB_CHIP_301LV) ||
+                       (hw_info->ujVBChipID == VB_CHIP_302LV)) {
+               int tmp;
+               tmp = xgifb_reg_get(XGICR, 0x34);
+               if (tmp <= 0x13) {
+                       /* Currently on LCDA?
+                        *(Some BIOSes leave CR38) */
+                       tmp = xgifb_reg_get(XGICR, 0x38);
+                       if ((tmp & 0x03) == 0x03) {
+                               /* XGI_Pr.XGI_UseLCDA = 1; */
+                       } else {
                                /* Currently on LCDA?
-                                *(Some BIOSes leave CR38) */
-                               tmp = xgifb_reg_get(XGICR, 0x38);
-                               if ((tmp & 0x03) == 0x03) {
+                                *(Some newer BIOSes set D0 in CR35) */
+                               tmp = xgifb_reg_get(XGICR, 0x35);
+                               if (tmp & 0x01) {
                                        /* XGI_Pr.XGI_UseLCDA = 1; */
                                } else {
-                                       /* Currently on LCDA?
-                                        *(Some newer BIOSes set D0 in CR35) */
-                                       tmp = xgifb_reg_get(XGICR, 0x35);
-                                       if (tmp & 0x01) {
-                                               /* XGI_Pr.XGI_UseLCDA = 1; */
-                                       } else {
-                                               tmp = xgifb_reg_get(XGICR,
-                                                                   0x30);
-                                               if (tmp & 0x20) {
-                                                       tmp = xgifb_reg_get(
-                                                               XGIPART1, 0x13);
-                                                       if (tmp & 0x04) {
-                                                               /* XGI_Pr.XGI_UseLCDA = 1; */
-                                                       }
+                                       tmp = xgifb_reg_get(XGICR,
+                                                           0x30);
+                                       if (tmp & 0x20) {
+                                               tmp = xgifb_reg_get(
+                                                       XGIPART1, 0x13);
+                                               if (tmp & 0x04) {
+                                                       /* XGI_Pr.XGI_UseLCDA = 1; */
                                                }
                                        }
                                }
                        }
-
                }
 
-               if (xgifb_mode_idx >= 0)
-                       xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
+       }
 
-               if (xgifb_mode_idx < 0) {
-                       switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
-                       case DISPTYPE_LCD:
-                               xgifb_mode_idx = DEFAULT_LCDMODE;
-                               if (xgi_video_info.chip == XG21)
-                                       xgifb_mode_idx =
-                                           XGIfb_GetXG21DefaultLVDSModeIdx();
-                               break;
-                       case DISPTYPE_TV:
-                               xgifb_mode_idx = DEFAULT_TVMODE;
-                               break;
-                       default:
-                               xgifb_mode_idx = DEFAULT_MODE;
+       xgifb_info->mode_idx = -1;
+
+       if (mode)
+               XGIfb_search_mode(xgifb_info, mode);
+       else if (vesa != -1)
+               XGIfb_search_vesamode(xgifb_info, vesa);
+
+       if (xgifb_info->mode_idx >= 0)
+               xgifb_info->mode_idx =
+                       XGIfb_validate_mode(xgifb_info, xgifb_info->mode_idx);
+
+       if (xgifb_info->mode_idx < 0) {
+               if (xgifb_info->display2 == XGIFB_DISP_LCD &&
+                   xgifb_info->chip == XG21)
+                       xgifb_info->mode_idx =
+                               XGIfb_GetXG21DefaultLVDSModeIdx();
+               else
+                       xgifb_info->mode_idx = DEFAULT_MODE;
+       }
+
+       if (xgifb_info->mode_idx < 0) {
+               dev_err(&pdev->dev, "no supported video mode found\n");
+               goto error_1;
+       }
+
+       if (xgi21_drvlcdcaplist) {
+               int m;
+
+               for (m = 0; m < ARRAY_SIZE(XGI21_LCDCapList); m++)
+                       if ((XGI21_LCDCapList[m].LVDSHDE ==
+                               XGIbios_mode[xgifb_info->mode_idx].xres) &&
+                           (XGI21_LCDCapList[m].LVDSVDE ==
+                               XGIbios_mode[xgifb_info->mode_idx].yres)) {
+                               xgifb_reg_set(xgifb_info->dev_info.P3d4,
+                                             0x36,
+                                             m);
                                break;
                        }
-               }
+       }
 
-               XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
+       /* yilin set default refresh rate */
+       xgifb_info->refresh_rate = refresh_rate;
+       if (xgifb_info->refresh_rate == 0)
+               xgifb_info->refresh_rate = 60;
+       if (XGIfb_search_refresh_rate(xgifb_info,
+                       xgifb_info->refresh_rate) == 0) {
+               xgifb_info->rate_idx =
+                       XGIbios_mode[xgifb_info->mode_idx].rate_idx;
+               xgifb_info->refresh_rate = 60;
+       }
 
-               /* yilin set default refresh rate */
-               if (xgi_video_info.refresh_rate == 0)
-                       xgi_video_info.refresh_rate = 60;
-               if (XGIfb_search_refresh_rate(
-                               xgi_video_info.refresh_rate) == 0) {
-                       XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
-                       xgi_video_info.refresh_rate = 60;
-               }
+       xgifb_info->video_bpp = XGIbios_mode[xgifb_info->mode_idx].bpp;
+       xgifb_info->video_vwidth =
+               xgifb_info->video_width =
+                       XGIbios_mode[xgifb_info->mode_idx].xres;
+       xgifb_info->video_vheight =
+               xgifb_info->video_height =
+                       XGIbios_mode[xgifb_info->mode_idx].yres;
+       xgifb_info->org_x = xgifb_info->org_y = 0;
+       xgifb_info->video_linelength =
+               xgifb_info->video_width *
+               (xgifb_info->video_bpp >> 3);
+       switch (xgifb_info->video_bpp) {
+       case 8:
+               xgifb_info->DstColor = 0x0000;
+               xgifb_info->XGI310_AccelDepth = 0x00000000;
+               xgifb_info->video_cmap_len = 256;
+               break;
+       case 16:
+               xgifb_info->DstColor = 0x8000;
+               xgifb_info->XGI310_AccelDepth = 0x00010000;
+               xgifb_info->video_cmap_len = 16;
+               break;
+       case 32:
+               xgifb_info->DstColor = 0xC000;
+               xgifb_info->XGI310_AccelDepth = 0x00020000;
+               xgifb_info->video_cmap_len = 16;
+               break;
+       default:
+               xgifb_info->video_cmap_len = 16;
+               printk(KERN_INFO "XGIfb: Unsupported depth %d",
+                      xgifb_info->video_bpp);
+               break;
+       }
 
-               xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
-               xgi_video_info.video_vwidth =
-                       xgi_video_info.video_width =
-                               XGIbios_mode[xgifb_mode_idx].xres;
-               xgi_video_info.video_vheight =
-                       xgi_video_info.video_height =
-                               XGIbios_mode[xgifb_mode_idx].yres;
-               xgi_video_info.org_x = xgi_video_info.org_y = 0;
-               xgi_video_info.video_linelength =
-                       xgi_video_info.video_width *
-                       (xgi_video_info.video_bpp >> 3);
-               switch (xgi_video_info.video_bpp) {
-               case 8:
-                       xgi_video_info.DstColor = 0x0000;
-                       xgi_video_info.XGI310_AccelDepth = 0x00000000;
-                       xgi_video_info.video_cmap_len = 256;
-                       break;
-               case 16:
-                       xgi_video_info.DstColor = 0x8000;
-                       xgi_video_info.XGI310_AccelDepth = 0x00010000;
-                       xgi_video_info.video_cmap_len = 16;
-                       break;
-               case 32:
-                       xgi_video_info.DstColor = 0xC000;
-                       xgi_video_info.XGI310_AccelDepth = 0x00020000;
-                       xgi_video_info.video_cmap_len = 16;
-                       break;
-               default:
-                       xgi_video_info.video_cmap_len = 16;
-                       printk(KERN_INFO "XGIfb: Unsupported depth %d",
-                              xgi_video_info.video_bpp);
-                       break;
+       printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
+              xgifb_info->video_width,
+              xgifb_info->video_height,
+              xgifb_info->video_bpp,
+              xgifb_info->refresh_rate);
+
+       fb_info->var.red.length         = 8;
+       fb_info->var.green.length       = 8;
+       fb_info->var.blue.length        = 8;
+       fb_info->var.activate           = FB_ACTIVATE_NOW;
+       fb_info->var.height             = -1;
+       fb_info->var.width              = -1;
+       fb_info->var.vmode              = FB_VMODE_NONINTERLACED;
+       fb_info->var.xres               = xgifb_info->video_width;
+       fb_info->var.xres_virtual       = xgifb_info->video_width;
+       fb_info->var.yres               = xgifb_info->video_height;
+       fb_info->var.yres_virtual       = xgifb_info->video_height;
+       fb_info->var.bits_per_pixel     = xgifb_info->video_bpp;
+
+       XGIfb_bpp_to_var(xgifb_info, &fb_info->var);
+
+       fb_info->var.pixclock = (u32) (1000000000 /
+                       XGIfb_mode_rate_to_dclock(&xgifb_info->dev_info,
+                               hw_info,
+                               XGIbios_mode[xgifb_info->mode_idx].mode_no,
+                               xgifb_info->rate_idx));
+
+       if (XGIfb_mode_rate_to_ddata(&xgifb_info->dev_info, hw_info,
+               XGIbios_mode[xgifb_info->mode_idx].mode_no,
+               xgifb_info->rate_idx,
+               &fb_info->var.left_margin,
+               &fb_info->var.right_margin,
+               &fb_info->var.upper_margin,
+               &fb_info->var.lower_margin,
+               &fb_info->var.hsync_len,
+               &fb_info->var.vsync_len,
+               &fb_info->var.sync,
+               &fb_info->var.vmode)) {
+
+               if ((fb_info->var.vmode & FB_VMODE_MASK) ==
+                   FB_VMODE_INTERLACED) {
+                       fb_info->var.yres <<= 1;
+                       fb_info->var.yres_virtual <<= 1;
+               } else if ((fb_info->var.vmode & FB_VMODE_MASK) ==
+                          FB_VMODE_DOUBLE) {
+                       fb_info->var.pixclock >>= 1;
+                       fb_info->var.yres >>= 1;
+                       fb_info->var.yres_virtual >>= 1;
                }
 
-               printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
-                      xgi_video_info.video_width,
-                      xgi_video_info.video_height,
-                      xgi_video_info.video_bpp,
-                      xgi_video_info.refresh_rate);
-
-               default_var.xres =
-                       default_var.xres_virtual =
-                               xgi_video_info.video_width;
-               default_var.yres =
-                       default_var.yres_virtual =
-                               xgi_video_info.video_height;
-               default_var.bits_per_pixel = xgi_video_info.video_bpp;
-
-               XGIfb_bpp_to_var(&default_var);
-
-               default_var.pixclock = (u32) (1000000000 /
-                               XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
-                                               XGIfb_mode_no, XGIfb_rate_idx));
-
-               if (XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
-                       XGIfb_mode_no, XGIfb_rate_idx,
-                       &default_var.left_margin, &default_var.right_margin,
-                       &default_var.upper_margin, &default_var.lower_margin,
-                       &default_var.hsync_len, &default_var.vsync_len,
-                       &default_var.sync, &default_var.vmode)) {
-
-                       if ((default_var.vmode & FB_VMODE_MASK) ==
-                           FB_VMODE_INTERLACED) {
-                               default_var.yres <<= 1;
-                               default_var.yres_virtual <<= 1;
-                       } else if ((default_var.vmode & FB_VMODE_MASK) ==
-                                  FB_VMODE_DOUBLE) {
-                               default_var.pixclock >>= 1;
-                               default_var.yres >>= 1;
-                               default_var.yres_virtual >>= 1;
-                       }
+       }
 
-               }
+       strncpy(fb_info->fix.id, "XGI", sizeof(fb_info->fix.id) - 1);
+       fb_info->fix.type       = FB_TYPE_PACKED_PIXELS;
+       fb_info->fix.xpanstep   = 1;
+       fb_info->fix.ypanstep   = 1;
 
-               fb_info->flags = FBINFO_FLAG_DEFAULT;
-               fb_info->var = default_var;
-               fb_info->fix = XGIfb_fix;
-               fb_info->par = &xgi_video_info;
-               fb_info->screen_base = xgi_video_info.video_vbase;
-               fb_info->fbops = &XGIfb_ops;
-               XGIfb_get_fix(&fb_info->fix, -1, fb_info);
-               fb_info->pseudo_palette = pseudo_palette;
+       fb_info->flags = FBINFO_FLAG_DEFAULT;
+       fb_info->screen_base = xgifb_info->video_vbase;
+       fb_info->fbops = &XGIfb_ops;
+       XGIfb_get_fix(&fb_info->fix, -1, fb_info);
+       fb_info->pseudo_palette = xgifb_info->pseudo_palette;
 
-               fb_alloc_cmap(&fb_info->cmap, 256 , 0);
+       fb_alloc_cmap(&fb_info->cmap, 256 , 0);
 
 #ifdef CONFIG_MTRR
-               xgi_video_info.mtrr = mtrr_add(
-                       (unsigned int) xgi_video_info.video_base,
-                       (unsigned int) xgi_video_info.video_size,
-                       MTRR_TYPE_WRCOMB, 1);
-               if (xgi_video_info.mtrr)
-                       printk(KERN_INFO "XGIfb: Added MTRRs\n");
+       xgifb_info->mtrr = mtrr_add(xgifb_info->video_base,
+               xgifb_info->video_size, MTRR_TYPE_WRCOMB, 1);
+       if (xgifb_info->mtrr >= 0)
+               dev_info(&pdev->dev, "added MTRR\n");
 #endif
 
-               if (register_framebuffer(fb_info) < 0) {
-                       ret = -EINVAL;
-                       goto error_1;
-               }
-
-               XGIfb_registered = 1;
-
-               printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
-                      fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
-
+       if (register_framebuffer(fb_info) < 0) {
+               ret = -EINVAL;
+               goto error_mtrr;
        }
 
        dumpVGAReg();
 
        return 0;
 
+error_mtrr:
+#ifdef CONFIG_MTRR
+       if (xgifb_info->mtrr >= 0)
+               mtrr_del(xgifb_info->mtrr, xgifb_info->video_base,
+                       xgifb_info->video_size);
+#endif /* CONFIG_MTRR */
 error_1:
-       iounmap(xgi_video_info.mmio_vbase);
-       iounmap(xgi_video_info.video_vbase);
-       release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
+       iounmap(xgifb_info->mmio_vbase);
+       iounmap(xgifb_info->video_vbase);
+       release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
 error_0:
-       release_mem_region(xgi_video_info.video_base,
-                          xgi_video_info.video_size);
+       release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
 error:
-       vfree(XGIhw_ext.pjVirtualRomBase);
+       vfree(hw_info->pjVirtualRomBase);
        framebuffer_release(fb_info);
        return ret;
 }
@@ -2515,13 +2429,20 @@ error:
 
 static void __devexit xgifb_remove(struct pci_dev *pdev)
 {
+       struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
+       struct fb_info *fb_info = xgifb_info->fb_info;
+
        unregister_framebuffer(fb_info);
-       iounmap(xgi_video_info.mmio_vbase);
-       iounmap(xgi_video_info.video_vbase);
-       release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
-       release_mem_region(xgi_video_info.video_base,
-                          xgi_video_info.video_size);
-       vfree(XGIhw_ext.pjVirtualRomBase);
+#ifdef CONFIG_MTRR
+       if (xgifb_info->mtrr >= 0)
+               mtrr_del(xgifb_info->mtrr, xgifb_info->video_base,
+                       xgifb_info->video_size);
+#endif /* CONFIG_MTRR */
+       iounmap(xgifb_info->mmio_vbase);
+       iounmap(xgifb_info->video_vbase);
+       release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
+       release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
+       vfree(xgifb_info->hw_info.pjVirtualRomBase);
        framebuffer_release(fb_info);
        pci_set_drvdata(pdev, NULL);
 }
@@ -2533,7 +2454,7 @@ static struct pci_driver xgifb_driver = {
        .remove = __devexit_p(xgifb_remove)
 };
 
-XGIINITSTATIC int __init xgifb_init(void)
+static int __init xgifb_init(void)
 {
        char *option = NULL;
 
@@ -2544,9 +2465,7 @@ XGIINITSTATIC int __init xgifb_init(void)
        return pci_register_driver(&xgifb_driver);
 }
 
-#ifndef MODULE
 module_init(xgifb_init);
-#endif
 
 /*****************************************************/
 /*                      MODULE                       */
@@ -2554,154 +2473,32 @@ module_init(xgifb_init);
 
 #ifdef MODULE
 
-static char *mode = NULL;
-static int vesa = 0;
-static unsigned int rate = 0;
-static unsigned int mem = 0;
-static char *forcecrt2type = NULL;
-static int forcecrt1 = -1;
-static int pdc = -1;
-static int pdc1 = -1;
-static int noypan = -1;
-static int userom = -1;
-static int useoem = -1;
-static char *tvstandard = NULL;
-static int nocrt2rate = 0;
-static int scalelcd = -1;
-static char *specialtiming = NULL;
-static int lvdshl = -1;
-static int tvxposoffset = 0, tvyposoffset = 0;
-#if !defined(__i386__) && !defined(__x86_64__)
-static int resetcard = 0;
-static int videoram = 0;
-#endif
-
 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("XGITECH , Others");
 
-module_param(mem, int, 0);
-module_param(noypan, int, 0);
-module_param(userom, int, 0);
-module_param(useoem, int, 0);
 module_param(mode, charp, 0);
 module_param(vesa, int, 0);
-module_param(rate, int, 0);
-module_param(forcecrt1, int, 0);
-module_param(forcecrt2type, charp, 0);
-module_param(scalelcd, int, 0);
-module_param(pdc, int, 0);
-module_param(pdc1, int, 0);
-module_param(specialtiming, charp, 0);
-module_param(lvdshl, int, 0);
-module_param(tvstandard, charp, 0);
-module_param(tvxposoffset, int, 0);
-module_param(tvyposoffset, int, 0);
 module_param(filter, int, 0);
-module_param(nocrt2rate, int, 0);
-#if !defined(__i386__) && !defined(__x86_64__)
-module_param(resetcard, int, 0);
-module_param(videoram, int, 0);
-#endif
-
-MODULE_PARM_DESC(noypan,
-               "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
-               "will be performed by redrawing the screen. (default: 0)\n");
 
 MODULE_PARM_DESC(mode,
-               "\nSelects the desired default display mode in the format XxYxDepth,\n"
-               "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
-               "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
-               "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
+       "\nSelects the desired default display mode in the format XxYxDepth,\n"
+       "eg. 1024x768x16.\n");
 
 MODULE_PARM_DESC(vesa,
-               "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
-               "0x117 (default: 0x0103)\n");
-
-MODULE_PARM_DESC(rate,
-               "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
-               "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
-               "will be ignored (default: 60)\n");
-
-MODULE_PARM_DESC(forcecrt1,
-               "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is\n"
-               "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
-               "0=CRT1 OFF) (default: [autodetected])\n");
-
-MODULE_PARM_DESC(forcecrt2type,
-               "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
-               "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
-               "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
-               "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
-               "be used instead of TV to override the TV detection. Furthermore, on systems\n"
-               "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
-               "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
-               "depends on the very hardware in use. (default: [autodetected])\n");
-
-MODULE_PARM_DESC(scalelcd,
-               "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
-               "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
-               "show black bars around the image, TMDS panels will probably do the scaling\n"
-               "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
-
-MODULE_PARM_DESC(pdc,
-               "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
-               "should detect this correctly in most cases; however, sometimes this is not\n"
-               "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
-               "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
-               "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
-               "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
-
-MODULE_PARM_DESC(pdc1,
-               "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
-               "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
-               "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
-               "implemented yet.\n");
-
-MODULE_PARM_DESC(specialtiming,
-               "\nPlease refer to documentation for more information on this option.\n");
-
-MODULE_PARM_DESC(lvdshl,
-               "\nPlease refer to documentation for more information on this option.\n");
-
-MODULE_PARM_DESC(tvstandard,
-               "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
-               "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
-
-MODULE_PARM_DESC(tvxposoffset,
-               "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
-               "Default: 0\n");
-
-MODULE_PARM_DESC(tvyposoffset,
-               "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
-               "Default: 0\n");
+       "\nSelects the desired default display mode by VESA mode number, eg.\n"
+       "0x117.\n");
 
 MODULE_PARM_DESC(filter,
                "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
                "(Possible values 0-7, default: [no filter])\n");
 
-MODULE_PARM_DESC(nocrt2rate,
-               "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
-               "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
-
-static int __init xgifb_init_module(void)
-{
-       printk("\nXGIfb_init_module");
-       if (mode)
-               XGIfb_search_mode(mode);
-       else if (vesa != -1)
-               XGIfb_search_vesamode(vesa);
-
-       return xgifb_init();
-}
-
 static void __exit xgifb_remove_module(void)
 {
        pci_unregister_driver(&xgifb_driver);
        printk(KERN_DEBUG "xgifb: Module unloaded\n");
 }
 
-module_init(xgifb_init_module);
 module_exit(xgifb_remove_module);
 
 #endif /*  /MODULE  */