linux/drivers/staging/xgifb/XGI_main_26.c
<<
>>
Prefs
   1/*
   2 * XG20, XG21, XG40, XG42 frame buffer device
   3 * for Linux kernels  2.5.x, 2.6.x
   4 * Base on TW's sis fbdev code.
   5 */
   6
   7/* #include <linux/config.h> */
   8#include <linux/version.h>
   9#include <linux/module.h>
  10#include <linux/moduleparam.h>
  11#include <linux/kernel.h>
  12#include <linux/spinlock.h>
  13#include <linux/errno.h>
  14#include <linux/string.h>
  15#include <linux/mm.h>
  16#include <linux/tty.h>
  17#include <linux/slab.h>
  18#include <linux/delay.h>
  19#include <linux/fb.h>
  20#include <linux/console.h>
  21#include <linux/selection.h>
  22#include <linux/ioport.h>
  23#include <linux/init.h>
  24#include <linux/pci.h>
  25#include <linux/vmalloc.h>
  26#include <linux/vt_kern.h>
  27#include <linux/capability.h>
  28#include <linux/fs.h>
  29#include <linux/types.h>
  30#include <linux/proc_fs.h>
  31
  32#ifndef XGIFB_PAN
  33#define XGIFB_PAN
  34#endif
  35
  36#include <asm/io.h>
  37#ifdef CONFIG_MTRR
  38#include <asm/mtrr.h>
  39#endif
  40
  41#include "XGIfb.h"
  42#include "vgatypes.h"
  43#include "XGI_main.h"
  44#include "vb_util.h"
  45
  46int XGIfb_accel = 0;
  47
  48#define Index_CR_GPIO_Reg1 0x48
  49#define Index_CR_GPIO_Reg2 0x49
  50#define Index_CR_GPIO_Reg3 0x4a
  51
  52#define GPIOG_EN    (1<<6)
  53#define GPIOG_WRITE (1<<6)
  54#define GPIOG_READ  (1<<1)
  55int XGIfb_GetXG21DefaultLVDSModeIdx(void);
  56
  57/* -------------------- Macro definitions ---------------------------- */
  58
  59#undef XGIFBDEBUG
  60
  61#ifdef XGIFBDEBUG
  62#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
  63#else
  64#define DPRINTK(fmt, args...)
  65#endif
  66
  67#ifdef XGIFBDEBUG
  68static void dumpVGAReg(void)
  69{
  70        u8 i, reg;
  71
  72        outXGIIDXREG(XGISR, 0x05, 0x86);
  73        /*
  74        outXGIIDXREG(XGISR, 0x08, 0x4f);
  75        outXGIIDXREG(XGISR, 0x0f, 0x20);
  76        outXGIIDXREG(XGISR, 0x11, 0x4f);
  77        outXGIIDXREG(XGISR, 0x13, 0x45);
  78        outXGIIDXREG(XGISR, 0x14, 0x51);
  79        outXGIIDXREG(XGISR, 0x1e, 0x41);
  80        outXGIIDXREG(XGISR, 0x1f, 0x0);
  81        outXGIIDXREG(XGISR, 0x20, 0xa1);
  82        outXGIIDXREG(XGISR, 0x22, 0xfb);
  83        outXGIIDXREG(XGISR, 0x26, 0x22);
  84        outXGIIDXREG(XGISR, 0x3e, 0x07);
  85        */
  86
  87        /* outXGIIDXREG(XGICR, 0x19, 0x00); */
  88        /* outXGIIDXREG(XGICR, 0x1a, 0x3C); */
  89        /* outXGIIDXREG(XGICR, 0x22, 0xff); */
  90        /* outXGIIDXREG(XGICR, 0x3D, 0x10); */
  91
  92        /* outXGIIDXREG(XGICR, 0x4a, 0xf3); */
  93
  94        /* outXGIIDXREG(XGICR, 0x57, 0x0); */
  95        /* outXGIIDXREG(XGICR, 0x7a, 0x2c); */
  96
  97        /* outXGIIDXREG(XGICR, 0x82, 0xcc); */
  98        /* outXGIIDXREG(XGICR, 0x8c, 0x0); */
  99        /*
 100        outXGIIDXREG(XGICR, 0x99, 0x1);
 101        outXGIIDXREG(XGICR, 0x41, 0x40);
 102        */
 103
 104        for (i = 0; i < 0x4f; i++) {
 105                inXGIIDXREG(XGISR, i, reg);
 106                printk("\no 3c4 %x", i);
 107                printk("\ni 3c5 => %x", reg);
 108        }
 109
 110        for (i = 0; i < 0xF0; i++) {
 111                inXGIIDXREG(XGICR, i, reg);
 112                printk("\no 3d4 %x", i);
 113                printk("\ni 3d5 => %x", reg);
 114        }
 115        /*
 116        outXGIIDXREG(XGIPART1,0x2F,1);
 117        for (i=1; i < 0x50; i++) {
 118                inXGIIDXREG(XGIPART1, i, reg);
 119                printk("\no d004 %x", i);
 120                printk("\ni d005 => %x", reg);
 121        }
 122
 123        for (i=0; i < 0x50; i++) {
 124                 inXGIIDXREG(XGIPART2, i, reg);
 125                 printk("\no d010 %x", i);
 126                 printk("\ni d011 => %x", reg);
 127        }
 128        for (i=0; i < 0x50; i++) {
 129                inXGIIDXREG(XGIPART3, i, reg);
 130                printk("\no d012 %x",i);
 131                printk("\ni d013 => %x",reg);
 132        }
 133        for (i=0; i < 0x50; i++) {
 134                inXGIIDXREG(XGIPART4, i, reg);
 135                printk("\no d014 %x",i);
 136                printk("\ni d015 => %x",reg);
 137        }
 138        */
 139}
 140#else
 141static inline void dumpVGAReg(void)
 142{
 143}
 144#endif
 145
 146/* data for XGI components */
 147struct video_info xgi_video_info;
 148
 149#if 1
 150#define DEBUGPRN(x)
 151#else
 152#define DEBUGPRN(x) printk(KERN_INFO x "\n");
 153#endif
 154
 155/* --------------- Hardware Access Routines -------------------------- */
 156
 157static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
 158                struct xgi_hw_device_info *HwDeviceExtension,
 159                unsigned char modeno, unsigned char rateindex)
 160{
 161        unsigned short ModeNo = modeno;
 162        unsigned short ModeIdIndex = 0, ClockIndex = 0;
 163        unsigned short RefreshRateTableIndex = 0;
 164
 165        /* unsigned long  temp = 0; */
 166        int Clock;
 167        XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
 168        InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
 169
 170        RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
 171                        ModeIdIndex, XGI_Pr);
 172
 173        /*
 174        temp = XGI_SearchModeID(ModeNo , &ModeIdIndex,  XGI_Pr) ;
 175        if (!temp) {
 176                printk(KERN_ERR "Could not find mode %x\n", ModeNo);
 177                return 65000;
 178        }
 179
 180        RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
 181        RefreshRateTableIndex += (rateindex - 1);
 182
 183        */
 184        ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
 185        if (HwDeviceExtension->jChipType < XGI_315H)
 186                ClockIndex &= 0x3F;
 187
 188        Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
 189
 190        return Clock;
 191}
 192
 193static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
 194                struct xgi_hw_device_info *HwDeviceExtension,
 195                unsigned char modeno, unsigned char rateindex,
 196                u32 *left_margin, u32 *right_margin, u32 *upper_margin,
 197                u32 *lower_margin, u32 *hsync_len, u32 *vsync_len, u32 *sync,
 198                u32 *vmode)
 199{
 200        unsigned short ModeNo = modeno;
 201        unsigned short ModeIdIndex = 0, index = 0;
 202        unsigned short RefreshRateTableIndex = 0;
 203
 204        unsigned short VRE, VBE, VRS, VBS, VDE, VT;
 205        unsigned short HRE, HBE, HRS, HBS, HDE, HT;
 206        unsigned char sr_data, cr_data, cr_data2;
 207        unsigned long cr_data3;
 208        int A, B, C, D, E, F, temp, j;
 209        XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
 210        InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
 211        RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
 212                        ModeIdIndex, XGI_Pr);
 213        /*
 214        temp = XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
 215        if (!temp)
 216                return 0;
 217
 218        RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
 219        RefreshRateTableIndex += (rateindex - 1);
 220        */
 221        index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 222
 223        sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
 224
 225        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
 226
 227        /* Horizontal total */
 228        HT = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8);
 229        A = HT + 5;
 230
 231        /*
 232        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
 233
 234        Horizontal display enable end
 235        HDE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x0C) << 6);
 236        */
 237        HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) - 1;
 238        E = HDE + 1;
 239
 240        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
 241
 242        /* Horizontal retrace (=sync) start */
 243        HRS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0xC0) << 2);
 244        F = HRS - E - 3;
 245
 246        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
 247
 248        /* Horizontal blank start */
 249        HBS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x30) << 4);
 250
 251        sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
 252
 253        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
 254
 255        cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
 256
 257        /* Horizontal blank end */
 258        HBE = (cr_data & 0x1f) | ((unsigned short) (cr_data2 & 0x80) >> 2)
 259                        | ((unsigned short) (sr_data & 0x03) << 6);
 260
 261        /* Horizontal retrace (=sync) end */
 262        HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
 263
 264        temp = HBE - ((E - 1) & 255);
 265        B = (temp > 0) ? temp : (temp + 256);
 266
 267        temp = HRE - ((E + F + 3) & 63);
 268        C = (temp > 0) ? temp : (temp + 64);
 269
 270        D = B - F - C;
 271
 272        *left_margin = D * 8;
 273        *right_margin = F * 8;
 274        *hsync_len = C * 8;
 275
 276        sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
 277
 278        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
 279
 280        cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
 281
 282        /* Vertical total */
 283        VT = (cr_data & 0xFF) | ((unsigned short) (cr_data2 & 0x01) << 8)
 284                        | ((unsigned short) (cr_data2 & 0x20) << 4)
 285                        | ((unsigned short) (sr_data & 0x01) << 10);
 286        A = VT + 2;
 287
 288        /* cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; */
 289
 290        /* Vertical display enable end */
 291        /*
 292        VDE = (cr_data & 0xff) |
 293                ((unsigned short) (cr_data2 & 0x02) << 7) |
 294                ((unsigned short) (cr_data2 & 0x40) << 3) |
 295                ((unsigned short) (sr_data & 0x02) << 9);
 296        */
 297        VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes - 1;
 298        E = VDE + 1;
 299
 300        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
 301
 302        /* Vertical retrace (=sync) start */
 303        VRS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x04) << 6)
 304                        | ((unsigned short) (cr_data2 & 0x80) << 2)
 305                        | ((unsigned short) (sr_data & 0x08) << 7);
 306        F = VRS + 1 - E;
 307
 308        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
 309
 310        cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
 311
 312        /* Vertical blank start */
 313        VBS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x08) << 5)
 314                        | ((unsigned short) (cr_data3 & 0x20) << 4)
 315                        | ((unsigned short) (sr_data & 0x04) << 8);
 316
 317        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
 318
 319        /* Vertical blank end */
 320        VBE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x10) << 4);
 321        temp = VBE - ((E - 1) & 511);
 322        B = (temp > 0) ? temp : (temp + 512);
 323
 324        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
 325
 326        /* Vertical retrace (=sync) end */
 327        VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
 328        temp = VRE - ((E + F - 1) & 31);
 329        C = (temp > 0) ? temp : (temp + 32);
 330
 331        D = B - F - C;
 332
 333        *upper_margin = D;
 334        *lower_margin = F;
 335        *vsync_len = C;
 336
 337        if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
 338                *sync &= ~FB_SYNC_VERT_HIGH_ACT;
 339        else
 340                *sync |= FB_SYNC_VERT_HIGH_ACT;
 341
 342        if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
 343                *sync &= ~FB_SYNC_HOR_HIGH_ACT;
 344        else
 345                *sync |= FB_SYNC_HOR_HIGH_ACT;
 346
 347        *vmode = FB_VMODE_NONINTERLACED;
 348        if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
 349                *vmode = FB_VMODE_INTERLACED;
 350        else {
 351                j = 0;
 352                while (XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
 353                        if (XGI_Pr->EModeIDTable[j].Ext_ModeID
 354                                        == XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
 355                                if (XGI_Pr->EModeIDTable[j].Ext_ModeFlag
 356                                                & DoubleScanMode) {
 357                                        *vmode = FB_VMODE_DOUBLE;
 358                                }
 359                                break;
 360                        }
 361                        j++;
 362                }
 363        }
 364
 365        return 1;
 366}
 367
 368static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
 369{
 370        XGI_Pr->RelIO = BaseAddr;
 371        XGI_Pr->P3c4 = BaseAddr + 0x14;
 372        XGI_Pr->P3d4 = BaseAddr + 0x24;
 373        XGI_Pr->P3c0 = BaseAddr + 0x10;
 374        XGI_Pr->P3ce = BaseAddr + 0x1e;
 375        XGI_Pr->P3c2 = BaseAddr + 0x12;
 376        XGI_Pr->P3ca = BaseAddr + 0x1a;
 377        XGI_Pr->P3c6 = BaseAddr + 0x16;
 378        XGI_Pr->P3c7 = BaseAddr + 0x17;
 379        XGI_Pr->P3c8 = BaseAddr + 0x18;
 380        XGI_Pr->P3c9 = BaseAddr + 0x19;
 381        XGI_Pr->P3da = BaseAddr + 0x2A;
 382        XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04; /* Digital video interface registers (LCD) */
 383        XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10; /* 301 TV Encoder registers */
 384        XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12; /* 301 Macrovision registers */
 385        XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
 386        XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14 + 2; /* 301 palette address port registers */
 387
 388}
 389
 390void XGIfb_set_reg4(u16 port, unsigned long data)
 391{
 392        outl((u32)(data & 0xffffffff), port);
 393}
 394
 395u32 XGIfb_get_reg3(u16 port)
 396{
 397        u32 data;
 398
 399        data = inl(port);
 400        return data;
 401}
 402
 403/* ------------ Interface for init & mode switching code ------------- */
 404
 405unsigned char XGIfb_query_VGA_config_space(
 406                struct xgi_hw_device_info *pXGIhw_ext, unsigned long offset,
 407                unsigned long set, unsigned long *value)
 408{
 409        static struct pci_dev *pdev = NULL;
 410        static unsigned char init = 0, valid_pdev = 0;
 411
 412        if (!set)
 413                DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
 414        else
 415                DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
 416
 417        if (!init) {
 418                init = 1;
 419                pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id,
 420                                pdev);
 421                if (pdev) {
 422                        valid_pdev = 1;
 423                        pci_dev_put(pdev);
 424                }
 425        }
 426
 427        if (!valid_pdev) {
 428                printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
 429                                xgi_video_info.chip_id);
 430                return 0;
 431        }
 432
 433        if (set == 0)
 434                pci_read_config_dword(pdev, offset, (u32 *) value);
 435        else
 436                pci_write_config_dword(pdev, offset, (u32)(*value));
 437
 438        return 1;
 439}
 440
 441/*
 442unsigned char XGIfb_query_north_bridge_space(struct xgi_hw_device_info *pXGIhw_ext,
 443        unsigned long offset, unsigned long set, unsigned long *value)
 444{
 445        static struct pci_dev *pdev = NULL;
 446        static unsigned char init = 0, valid_pdev = 0;
 447        u16 nbridge_id = 0;
 448
 449        if (!init) {
 450                init = 1;
 451                switch (xgi_video_info.chip) {
 452                case XGI_540:
 453                        nbridge_id = PCI_DEVICE_ID_XG_540;
 454                        break;
 455                case XGI_630:
 456                        nbridge_id = PCI_DEVICE_ID_XG_630;
 457                        break;
 458                case XGI_730:
 459                        nbridge_id = PCI_DEVICE_ID_XG_730;
 460                        break;
 461                case XGI_550:
 462                        nbridge_id = PCI_DEVICE_ID_XG_550;
 463                        break;
 464                case XGI_650:
 465                        nbridge_id = PCI_DEVICE_ID_XG_650;
 466                        break;
 467                case XGI_740:
 468                        nbridge_id = PCI_DEVICE_ID_XG_740;
 469                        break;
 470                default:
 471                        nbridge_id = 0;
 472                        break;
 473                }
 474
 475                pdev = pci_get_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
 476                if (pdev) {
 477                        valid_pdev = 1;
 478                        pci_dev_put(pdev);
 479                }
 480        }
 481
 482        if (!valid_pdev) {
 483                printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
 484                        nbridge_id);
 485                return 0;
 486        }
 487
 488        if (set == 0)
 489                pci_read_config_dword(pdev, offset, (u32 *)value);
 490        else
 491                pci_write_config_dword(pdev, offset, (u32)(*value));
 492
 493        return 1;
 494}
 495*/
 496/* ------------------ Internal helper routines ----------------- */
 497
 498static void XGIfb_search_mode(const char *name)
 499{
 500        int i = 0, j = 0, l;
 501
 502        if (name == NULL) {
 503                printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
 504                xgifb_mode_idx = DEFAULT_MODE;
 505                if ((xgi_video_info.chip == XG21)
 506                                && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
 507                                                == DISPTYPE_LCD)) {
 508                        xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
 509                }
 510                return;
 511        }
 512
 513        if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
 514                printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
 515                xgifb_mode_idx = DEFAULT_MODE;
 516                if ((xgi_video_info.chip == XG21)
 517                                && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
 518                                                == DISPTYPE_LCD)) {
 519                        xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
 520                }
 521                return;
 522        }
 523
 524        while (XGIbios_mode[i].mode_no != 0) {
 525                l = min(strlen(name), strlen(XGIbios_mode[i].name));
 526                if (!strncmp(name, XGIbios_mode[i].name, l)) {
 527                        xgifb_mode_idx = i;
 528                        j = 1;
 529                        break;
 530                }
 531                i++;
 532        }
 533        if (!j)
 534                printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
 535}
 536
 537static void XGIfb_search_vesamode(unsigned int vesamode)
 538{
 539        int i = 0, j = 0;
 540
 541        if (vesamode == 0) {
 542
 543                printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
 544                xgifb_mode_idx = DEFAULT_MODE;
 545                if ((xgi_video_info.chip == XG21)
 546                                && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
 547                                                == DISPTYPE_LCD)) {
 548                        xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
 549                }
 550                return;
 551        }
 552
 553        vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
 554
 555        while (XGIbios_mode[i].mode_no != 0) {
 556                if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode)
 557                                || (XGIbios_mode[i].vesa_mode_no_2 == vesamode)) {
 558                        xgifb_mode_idx = i;
 559                        j = 1;
 560                        break;
 561                }
 562                i++;
 563        }
 564        if (!j)
 565                printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
 566}
 567
 568static int XGIfb_GetXG21LVDSData(void)
 569{
 570        u8 tmp;
 571        unsigned char *pData;
 572        int i, j, k;
 573
 574        inXGIIDXREG(XGISR, 0x1e, tmp);
 575        outXGIIDXREG(XGISR, 0x1e, tmp | 4);
 576
 577        pData = xgi_video_info.mmio_vbase + 0x20000;
 578        if ((pData[0x0] == 0x55) && (pData[0x1] == 0xAA) && (pData[0x65] & 0x1)) {
 579                i = pData[0x316] | (pData[0x317] << 8);
 580                j = pData[i - 1];
 581                if (j == 0xff)
 582                        j = 1;
 583
 584                k = 0;
 585                do {
 586                        XGI21_LCDCapList[k].LVDS_Capability = pData[i]
 587                                        | (pData[i + 1] << 8);
 588                        XGI21_LCDCapList[k].LVDSHT = pData[i + 2] | (pData[i
 589                                        + 3] << 8);
 590                        XGI21_LCDCapList[k].LVDSVT = pData[i + 4] | (pData[i
 591                                        + 5] << 8);
 592                        XGI21_LCDCapList[k].LVDSHDE = pData[i + 6] | (pData[i
 593                                        + 7] << 8);
 594                        XGI21_LCDCapList[k].LVDSVDE = pData[i + 8] | (pData[i
 595                                        + 9] << 8);
 596                        XGI21_LCDCapList[k].LVDSHFP = pData[i + 10] | (pData[i
 597                                        + 11] << 8);
 598                        XGI21_LCDCapList[k].LVDSVFP = pData[i + 12] | (pData[i
 599                                        + 13] << 8);
 600                        XGI21_LCDCapList[k].LVDSHSYNC = pData[i + 14]
 601                                        | (pData[i + 15] << 8);
 602                        XGI21_LCDCapList[k].LVDSVSYNC = pData[i + 16]
 603                                        | (pData[i + 17] << 8);
 604                        XGI21_LCDCapList[k].VCLKData1 = pData[i + 18];
 605                        XGI21_LCDCapList[k].VCLKData2 = pData[i + 19];
 606                        XGI21_LCDCapList[k].PSC_S1 = pData[i + 20];
 607                        XGI21_LCDCapList[k].PSC_S2 = pData[i + 21];
 608                        XGI21_LCDCapList[k].PSC_S3 = pData[i + 22];
 609                        XGI21_LCDCapList[k].PSC_S4 = pData[i + 23];
 610                        XGI21_LCDCapList[k].PSC_S5 = pData[i + 24];
 611                        i += 25;
 612                        j--;
 613                        k++;
 614                } while ((j > 0) && (k < (sizeof(XGI21_LCDCapList)
 615                                / sizeof(struct XGI21_LVDSCapStruct))));
 616                return 1;
 617        }
 618        return 0;
 619}
 620
 621int XGIfb_GetXG21DefaultLVDSModeIdx(void)
 622{
 623
 624        int found_mode = 0;
 625        int XGIfb_mode_idx = 0;
 626
 627        found_mode = 0;
 628        while ((XGIbios_mode[XGIfb_mode_idx].mode_no != 0)
 629                        && (XGIbios_mode[XGIfb_mode_idx].xres
 630                                        <= XGI21_LCDCapList[0].LVDSHDE)) {
 631                if ((XGIbios_mode[XGIfb_mode_idx].xres
 632                                == XGI21_LCDCapList[0].LVDSHDE)
 633                                && (XGIbios_mode[XGIfb_mode_idx].yres
 634                                                == XGI21_LCDCapList[0].LVDSVDE)
 635                                && (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) {
 636                        XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
 637                        found_mode = 1;
 638                        break;
 639                }
 640                XGIfb_mode_idx++;
 641        }
 642        if (!found_mode)
 643                XGIfb_mode_idx = 0;
 644
 645        return XGIfb_mode_idx;
 646}
 647
 648static int XGIfb_validate_mode(int myindex)
 649{
 650        u16 xres, yres;
 651
 652        if (xgi_video_info.chip == XG21) {
 653                if ((xgi_video_info.disp_state & DISPTYPE_DISP2)
 654                                == DISPTYPE_LCD) {
 655                        xres = XGI21_LCDCapList[0].LVDSHDE;
 656                        yres = XGI21_LCDCapList[0].LVDSVDE;
 657                        if (XGIbios_mode[myindex].xres > xres)
 658                                return -1;
 659                        if (XGIbios_mode[myindex].yres > yres)
 660                                return -1;
 661                        if ((XGIbios_mode[myindex].xres < xres)
 662                                        && (XGIbios_mode[myindex].yres < yres)) {
 663                                if (XGIbios_mode[myindex].bpp > 8)
 664                                        return -1;
 665                        }
 666
 667                }
 668                return myindex;
 669
 670        }
 671
 672        /* FIXME: for now, all is valid on XG27 */
 673        if (xgi_video_info.chip == XG27)
 674                return myindex;
 675
 676        if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
 677                return -1;
 678
 679        switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
 680        case DISPTYPE_LCD:
 681                switch (XGIhw_ext.ulCRT2LCDType) {
 682                case LCD_640x480:
 683                        xres = 640;
 684                        yres = 480;
 685                        break;
 686                case LCD_800x600:
 687                        xres = 800;
 688                        yres = 600;
 689                        break;
 690                case LCD_1024x600:
 691                        xres = 1024;
 692                        yres = 600;
 693                        break;
 694                case LCD_1024x768:
 695                        xres = 1024;
 696                        yres = 768;
 697                        break;
 698                case LCD_1152x768:
 699                        xres = 1152;
 700                        yres = 768;
 701                        break;
 702                case LCD_1280x960:
 703                        xres = 1280;
 704                        yres = 960;
 705                        break;
 706                case LCD_1280x768:
 707                        xres = 1280;
 708                        yres = 768;
 709                        break;
 710                case LCD_1280x1024:
 711                        xres = 1280;
 712                        yres = 1024;
 713                        break;
 714                case LCD_1400x1050:
 715                        xres = 1400;
 716                        yres = 1050;
 717                        break;
 718                case LCD_1600x1200:
 719                        xres = 1600;
 720                        yres = 1200;
 721                        break;
 722                /* case LCD_320x480: */ /* TW: FSTN */
 723                        /*
 724                        xres =  320;
 725                        yres =  480;
 726                        break;
 727                        */
 728                default:
 729                        xres = 0;
 730                        yres = 0;
 731                        break;
 732                }
 733                if (XGIbios_mode[myindex].xres > xres)
 734                        return -1;
 735                if (XGIbios_mode[myindex].yres > yres)
 736                        return -1;
 737                if ((XGIhw_ext.ulExternalChip == 0x01) || /* LVDS */
 738                                (XGIhw_ext.ulExternalChip == 0x05)) { /* LVDS+Chrontel */
 739                        switch (XGIbios_mode[myindex].xres) {
 740                        case 512:
 741                                if (XGIbios_mode[myindex].yres != 512)
 742                                        return -1;
 743                                if (XGIhw_ext.ulCRT2LCDType == LCD_1024x600)
 744                                        return -1;
 745                                break;
 746                        case 640:
 747                                if ((XGIbios_mode[myindex].yres != 400)
 748                                                && (XGIbios_mode[myindex].yres
 749                                                                != 480))
 750                                        return -1;
 751                                break;
 752                        case 800:
 753                                if (XGIbios_mode[myindex].yres != 600)
 754                                        return -1;
 755                                break;
 756                        case 1024:
 757                                if ((XGIbios_mode[myindex].yres != 600)
 758                                                && (XGIbios_mode[myindex].yres
 759                                                                != 768))
 760                                        return -1;
 761                                if ((XGIbios_mode[myindex].yres == 600)
 762                                                && (XGIhw_ext.ulCRT2LCDType
 763                                                                != LCD_1024x600))
 764                                        return -1;
 765                                break;
 766                        case 1152:
 767                                if ((XGIbios_mode[myindex].yres) != 768)
 768                                        return -1;
 769                                if (XGIhw_ext.ulCRT2LCDType != LCD_1152x768)
 770                                        return -1;
 771                                break;
 772                        case 1280:
 773                                if ((XGIbios_mode[myindex].yres != 768)
 774                                                && (XGIbios_mode[myindex].yres
 775                                                                != 1024))
 776                                        return -1;
 777                                if ((XGIbios_mode[myindex].yres == 768)
 778                                                && (XGIhw_ext.ulCRT2LCDType
 779                                                                != LCD_1280x768))
 780                                        return -1;
 781                                break;
 782                        case 1400:
 783                                if (XGIbios_mode[myindex].yres != 1050)
 784                                        return -1;
 785                                break;
 786                        case 1600:
 787                                if (XGIbios_mode[myindex].yres != 1200)
 788                                        return -1;
 789                                break;
 790                        default:
 791                                return -1;
 792                        }
 793                } else {
 794                        switch (XGIbios_mode[myindex].xres) {
 795                        case 512:
 796                                if (XGIbios_mode[myindex].yres != 512)
 797                                        return -1;
 798                                break;
 799                        case 640:
 800                                if ((XGIbios_mode[myindex].yres != 400)
 801                                                && (XGIbios_mode[myindex].yres
 802                                                                != 480))
 803                                        return -1;
 804                                break;
 805                        case 800:
 806                                if (XGIbios_mode[myindex].yres != 600)
 807                                        return -1;
 808                                break;
 809                        case 1024:
 810                                if (XGIbios_mode[myindex].yres != 768)
 811                                        return -1;
 812                                break;
 813                        case 1280:
 814                                if ((XGIbios_mode[myindex].yres != 960)
 815                                                && (XGIbios_mode[myindex].yres
 816                                                                != 1024))
 817                                        return -1;
 818                                if (XGIbios_mode[myindex].yres == 960) {
 819                                        if (XGIhw_ext.ulCRT2LCDType
 820                                                        == LCD_1400x1050)
 821                                                return -1;
 822                                }
 823                                break;
 824                        case 1400:
 825                                if (XGIbios_mode[myindex].yres != 1050)
 826                                        return -1;
 827                                break;
 828                        case 1600:
 829                                if (XGIbios_mode[myindex].yres != 1200)
 830                                        return -1;
 831                                break;
 832                        default:
 833                                return -1;
 834                        }
 835                }
 836                break;
 837        case DISPTYPE_TV:
 838                switch (XGIbios_mode[myindex].xres) {
 839                case 512:
 840                case 640:
 841                case 800:
 842                        break;
 843                case 720:
 844                        if (xgi_video_info.TV_type == TVMODE_NTSC) {
 845                                if (XGIbios_mode[myindex].yres != 480)
 846                                        return -1;
 847                        } else if (xgi_video_info.TV_type == TVMODE_PAL) {
 848                                if (XGIbios_mode[myindex].yres != 576)
 849                                        return -1;
 850                        }
 851                        /*  TW: LVDS/CHRONTEL does not support 720 */
 852                        if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL
 853                                        || xgi_video_info.hasVB == HASVB_CHRONTEL) {
 854                                return -1;
 855                        }
 856                        break;
 857                case 1024:
 858                        if (xgi_video_info.TV_type == TVMODE_NTSC) {
 859                                if (XGIbios_mode[myindex].bpp == 32)
 860                                        return -1;
 861                        }
 862                        /* TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019) */
 863                        if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL
 864                                        || xgi_video_info.hasVB == HASVB_CHRONTEL) {
 865                                if (xgi_video_info.chip < XGI_315H)
 866                                        return -1;
 867                        }
 868                        break;
 869                default:
 870                        return -1;
 871                }
 872                break;
 873        case DISPTYPE_CRT2:
 874                if (XGIbios_mode[myindex].xres > 1280)
 875                        return -1;
 876                break;
 877        }
 878        return myindex;
 879
 880}
 881
 882static void XGIfb_search_crt2type(const char *name)
 883{
 884        int i = 0;
 885
 886        if (name == NULL)
 887                return;
 888
 889        while (XGI_crt2type[i].type_no != -1) {
 890                if (!strcmp(name, XGI_crt2type[i].name)) {
 891                        XGIfb_crt2type = XGI_crt2type[i].type_no;
 892                        XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
 893                        break;
 894                }
 895                i++;
 896        }
 897        if (XGIfb_crt2type < 0)
 898                printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
 899}
 900
 901static void XGIfb_search_queuemode(const char *name)
 902{
 903        int i = 0;
 904
 905        if (name == NULL)
 906                return;
 907
 908        while (XGI_queuemode[i].type_no != -1) {
 909                if (!strcmp(name, XGI_queuemode[i].name)) {
 910                        XGIfb_queuemode = XGI_queuemode[i].type_no;
 911                        break;
 912                }
 913                i++;
 914        }
 915        if (XGIfb_queuemode < 0)
 916                printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
 917}
 918
 919static u8 XGIfb_search_refresh_rate(unsigned int rate)
 920{
 921        u16 xres, yres;
 922        int i = 0;
 923
 924        xres = XGIbios_mode[xgifb_mode_idx].xres;
 925        yres = XGIbios_mode[xgifb_mode_idx].yres;
 926
 927        XGIfb_rate_idx = 0;
 928        while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
 929                if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres
 930                                == yres)) {
 931                        if (XGIfb_vrate[i].refresh == rate) {
 932                                XGIfb_rate_idx = XGIfb_vrate[i].idx;
 933                                break;
 934                        } else if (XGIfb_vrate[i].refresh > rate) {
 935                                if ((XGIfb_vrate[i].refresh - rate) <= 3) {
 936                                        DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
 937                                                        rate, XGIfb_vrate[i].refresh);
 938                                        XGIfb_rate_idx = XGIfb_vrate[i].idx;
 939                                        xgi_video_info.refresh_rate
 940                                                        = XGIfb_vrate[i].refresh;
 941                                } else if (((rate - XGIfb_vrate[i - 1].refresh)
 942                                                <= 2) && (XGIfb_vrate[i].idx
 943                                                != 1)) {
 944                                        DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
 945                                                        rate, XGIfb_vrate[i-1].refresh);
 946                                        XGIfb_rate_idx = XGIfb_vrate[i - 1].idx;
 947                                        xgi_video_info.refresh_rate
 948                                                        = XGIfb_vrate[i - 1].refresh;
 949                                }
 950                                break;
 951                        } else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
 952                                DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
 953                                                rate, XGIfb_vrate[i].refresh);
 954                                XGIfb_rate_idx = XGIfb_vrate[i].idx;
 955                                break;
 956                        }
 957                }
 958                i++;
 959        }
 960        if (XGIfb_rate_idx > 0) {
 961                return XGIfb_rate_idx;
 962        } else {
 963                printk(KERN_INFO
 964                                "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
 965                return 0;
 966        }
 967}
 968
 969static void XGIfb_search_tvstd(const char *name)
 970{
 971        int i = 0;
 972
 973        if (name == NULL)
 974                return;
 975
 976        while (XGI_tvtype[i].type_no != -1) {
 977                if (!strcmp(name, XGI_tvtype[i].name)) {
 978                        XGIfb_tvmode = XGI_tvtype[i].type_no;
 979                        break;
 980                }
 981                i++;
 982        }
 983}
 984
 985static unsigned char XGIfb_bridgeisslave(void)
 986{
 987        unsigned char usScratchP1_00;
 988
 989        if (xgi_video_info.hasVB == HASVB_NONE)
 990                return 0;
 991
 992        inXGIIDXREG(XGIPART1, 0x00, usScratchP1_00);
 993        if ((usScratchP1_00 & 0x50) == 0x10)
 994                return 1;
 995        else
 996                return 0;
 997}
 998
 999static unsigned char XGIfbcheckvretracecrt1(void)
1000{
1001        unsigned char temp;
1002
1003        inXGIIDXREG(XGICR, 0x17, temp);
1004        if (!(temp & 0x80))
1005                return 0;
1006
1007        inXGIIDXREG(XGISR, 0x1f, temp);
1008        if (temp & 0xc0)
1009                return 0;
1010
1011        if (inXGIREG(XGIINPSTAT) & 0x08)
1012                return 1;
1013        else
1014                return 0;
1015}
1016
1017static unsigned char XGIfbcheckvretracecrt2(void)
1018{
1019        unsigned char temp;
1020        if (xgi_video_info.hasVB == HASVB_NONE)
1021                return 0;
1022        inXGIIDXREG(XGIPART1, 0x30, temp);
1023        if (temp & 0x02)
1024                return 0;
1025        else
1026                return 1;
1027}
1028
1029static unsigned char XGIfb_CheckVBRetrace(void)
1030{
1031        if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1032                if (XGIfb_bridgeisslave())
1033                        return XGIfbcheckvretracecrt1();
1034                else
1035                        return XGIfbcheckvretracecrt2();
1036        }
1037        return XGIfbcheckvretracecrt1();
1038}
1039
1040/* ----------- FBDev related routines for all series ----------- */
1041
1042static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
1043{
1044        switch (var->bits_per_pixel) {
1045        case 8:
1046                var->red.offset = var->green.offset = var->blue.offset = 0;
1047                var->red.length = var->green.length = var->blue.length = 6;
1048                xgi_video_info.video_cmap_len = 256;
1049                break;
1050        case 16:
1051                var->red.offset = 11;
1052                var->red.length = 5;
1053                var->green.offset = 5;
1054                var->green.length = 6;
1055                var->blue.offset = 0;
1056                var->blue.length = 5;
1057                var->transp.offset = 0;
1058                var->transp.length = 0;
1059                xgi_video_info.video_cmap_len = 16;
1060                break;
1061        case 32:
1062                var->red.offset = 16;
1063                var->red.length = 8;
1064                var->green.offset = 8;
1065                var->green.length = 8;
1066                var->blue.offset = 0;
1067                var->blue.length = 8;
1068                var->transp.offset = 24;
1069                var->transp.length = 8;
1070                xgi_video_info.video_cmap_len = 16;
1071                break;
1072        }
1073}
1074
1075static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1076                struct fb_info *info)
1077{
1078
1079        unsigned int htotal = var->left_margin + var->xres + var->right_margin
1080                        + var->hsync_len;
1081        unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
1082                        + var->vsync_len;
1083#if defined(__powerpc__)
1084        u8 sr_data, cr_data;
1085#endif
1086        unsigned int drate = 0, hrate = 0;
1087        int found_mode = 0;
1088        int old_mode;
1089        /* unsigned char reg, reg1; */
1090
1091        DEBUGPRN("Inside do_set_var");
1092        /* printk(KERN_DEBUG "XGIfb:var->yres=%d, var->upper_margin=%d, var->lower_margin=%d, var->vsync_len=%d\n", var->yres, var->upper_margin, var->lower_margin, var->vsync_len); */
1093
1094        info->var.xres_virtual = var->xres_virtual;
1095        info->var.yres_virtual = var->yres_virtual;
1096        info->var.bits_per_pixel = var->bits_per_pixel;
1097
1098        if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1099                vtotal <<= 1;
1100        else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1101                vtotal <<= 2;
1102        else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1103                /* vtotal <<= 1; */
1104                /* var->yres <<= 1; */
1105        }
1106
1107        if (!htotal || !vtotal) {
1108                DPRINTK("XGIfb: Invalid 'var' information\n");
1109                return -EINVAL;
1110        } printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1111                        var->pixclock, htotal, vtotal);
1112
1113        if (var->pixclock && htotal && vtotal) {
1114                drate = 1000000000 / var->pixclock;
1115                hrate = (drate * 1000) / htotal;
1116                xgi_video_info.refresh_rate = (unsigned int) (hrate * 2
1117                                / vtotal);
1118        } else {
1119                xgi_video_info.refresh_rate = 60;
1120        }
1121
1122        printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1123                        var->xres, var->yres, var->bits_per_pixel, xgi_video_info.refresh_rate);
1124
1125        old_mode = xgifb_mode_idx;
1126        xgifb_mode_idx = 0;
1127
1128        while ((XGIbios_mode[xgifb_mode_idx].mode_no != 0)
1129                        && (XGIbios_mode[xgifb_mode_idx].xres <= var->xres)) {
1130                if ((XGIbios_mode[xgifb_mode_idx].xres == var->xres)
1131                                && (XGIbios_mode[xgifb_mode_idx].yres
1132                                                == var->yres)
1133                                && (XGIbios_mode[xgifb_mode_idx].bpp
1134                                                == var->bits_per_pixel)) {
1135                        XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1136                        found_mode = 1;
1137                        break;
1138                }
1139                xgifb_mode_idx++;
1140        }
1141
1142        if (found_mode)
1143                xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1144        else
1145                xgifb_mode_idx = -1;
1146
1147        if (xgifb_mode_idx < 0) {
1148                printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
1149                                var->yres, var->bits_per_pixel);
1150                xgifb_mode_idx = old_mode;
1151                return -EINVAL;
1152        }
1153
1154        if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1155                XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1156                xgi_video_info.refresh_rate = 60;
1157        }
1158
1159        if (isactive) {
1160
1161                XGIfb_pre_setmode();
1162                if (XGISetModeNew(&XGIhw_ext, XGIfb_mode_no) == 0) {
1163                        printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
1164                        return -EINVAL;
1165                }
1166                info->fix.line_length = ((info->var.xres_virtual
1167                                * info->var.bits_per_pixel) >> 6);
1168
1169                outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1170
1171                outXGIIDXREG(XGICR, 0x13, (info->fix.line_length & 0x00ff));
1172                outXGIIDXREG(XGISR, 0x0E, (info->fix.line_length & 0xff00) >> 8);
1173
1174                XGIfb_post_setmode();
1175
1176                DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
1177                                XGIbios_mode[xgifb_mode_idx].xres,
1178                                XGIbios_mode[xgifb_mode_idx].yres,
1179                                XGIbios_mode[xgifb_mode_idx].bpp,
1180                                xgi_video_info.refresh_rate);
1181
1182                xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1183                xgi_video_info.video_vwidth = info->var.xres_virtual;
1184                xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1185                xgi_video_info.video_vheight = info->var.yres_virtual;
1186                xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1187                xgi_video_info.org_x = xgi_video_info.org_y = 0;
1188                xgi_video_info.video_linelength = info->var.xres_virtual
1189                                * (xgi_video_info.video_bpp >> 3);
1190                xgi_video_info.accel = 0;
1191                if (XGIfb_accel) {
1192                        xgi_video_info.accel = (var->accel_flags
1193                                        & FB_ACCELF_TEXT) ? -1 : 0;
1194                }
1195                switch (xgi_video_info.video_bpp) {
1196                case 8:
1197                        xgi_video_info.DstColor = 0x0000;
1198                        xgi_video_info.XGI310_AccelDepth = 0x00000000;
1199                        xgi_video_info.video_cmap_len = 256;
1200#if defined(__powerpc__)
1201                        inXGIIDXREG(XGICR, 0x4D, cr_data);
1202                        outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
1203#endif
1204                        break;
1205                case 16:
1206                        xgi_video_info.DstColor = 0x8000;
1207                        xgi_video_info.XGI310_AccelDepth = 0x00010000;
1208#if defined(__powerpc__)
1209                        inXGIIDXREG(XGICR, 0x4D, cr_data);
1210                        outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1211#endif
1212                        xgi_video_info.video_cmap_len = 16;
1213                        break;
1214                case 32:
1215                        xgi_video_info.DstColor = 0xC000;
1216                        xgi_video_info.XGI310_AccelDepth = 0x00020000;
1217                        xgi_video_info.video_cmap_len = 16;
1218#if defined(__powerpc__)
1219                        inXGIIDXREG(XGICR, 0x4D, cr_data);
1220                        outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1221#endif
1222                        break;
1223                default:
1224                        xgi_video_info.video_cmap_len = 16;
1225                        printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1226                        xgi_video_info.accel = 0;
1227                        break;
1228                }
1229        }
1230        XGIfb_bpp_to_var(var); /*update ARGB info*/
1231        DEBUGPRN("End of do_set_var");
1232
1233        dumpVGAReg();
1234        return 0;
1235}
1236
1237#ifdef XGIFB_PAN
1238static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1239{
1240        unsigned int base;
1241
1242        /* printk("Inside pan_var"); */
1243
1244        if (var->xoffset > (var->xres_virtual - var->xres)) {
1245                /* printk("Pan: xo: %d xv %d xr %d\n",
1246                        var->xoffset, var->xres_virtual, var->xres); */
1247                return -EINVAL;
1248        }
1249        if (var->yoffset > (var->yres_virtual - var->yres)) {
1250                /* printk("Pan: yo: %d yv %d yr %d\n",
1251                        var->yoffset, var->yres_virtual, var->yres); */
1252                return -EINVAL;
1253        }
1254        base = var->yoffset * var->xres_virtual + var->xoffset;
1255
1256        /* calculate base bpp dep. */
1257        switch (var->bits_per_pixel) {
1258        case 16:
1259                base >>= 1;
1260                break;
1261        case 32:
1262                break;
1263        case 8:
1264        default:
1265                base >>= 2;
1266                break;
1267        }
1268
1269        outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1270
1271        outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
1272        outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
1273        outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
1274        outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
1275        setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1276
1277        if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1278                orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1279                outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
1280                outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1281                outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1282                setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1283        }
1284        /* printk("End of pan_var"); */
1285        return 0;
1286}
1287#endif
1288
1289void XGI_dispinfo(struct ap_data *rec)
1290{
1291        rec->minfo.bpp = xgi_video_info.video_bpp;
1292        rec->minfo.xres = xgi_video_info.video_width;
1293        rec->minfo.yres = xgi_video_info.video_height;
1294        rec->minfo.v_xres = xgi_video_info.video_vwidth;
1295        rec->minfo.v_yres = xgi_video_info.video_vheight;
1296        rec->minfo.org_x = xgi_video_info.org_x;
1297        rec->minfo.org_y = xgi_video_info.org_y;
1298        rec->minfo.vrate = xgi_video_info.refresh_rate;
1299        rec->iobase = xgi_video_info.vga_base - 0x30;
1300        rec->mem_size = xgi_video_info.video_size;
1301        rec->disp_state = xgi_video_info.disp_state;
1302        rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
1303        rec->hasVB = xgi_video_info.hasVB;
1304        rec->TV_type = xgi_video_info.TV_type;
1305        rec->TV_plug = xgi_video_info.TV_plug;
1306        rec->chip = xgi_video_info.chip;
1307}
1308
1309static int XGIfb_open(struct fb_info *info, int user)
1310{
1311        return 0;
1312}
1313
1314static int XGIfb_release(struct fb_info *info, int user)
1315{
1316        return 0;
1317}
1318
1319static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1320{
1321        int rc = 16;
1322
1323        switch (var->bits_per_pixel) {
1324        case 8:
1325                rc = 256;
1326                break;
1327        case 16:
1328                rc = 16;
1329                break;
1330        case 32:
1331                rc = 16;
1332                break;
1333        }
1334        return rc;
1335}
1336
1337static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1338                unsigned blue, unsigned transp, struct fb_info *info)
1339{
1340        if (regno >= XGIfb_get_cmap_len(&info->var))
1341                return 1;
1342
1343        switch (info->var.bits_per_pixel) {
1344        case 8:
1345                outXGIREG(XGIDACA, regno);
1346                outXGIREG(XGIDACD, (red >> 10));
1347                outXGIREG(XGIDACD, (green >> 10));
1348                outXGIREG(XGIDACD, (blue >> 10));
1349                if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1350                        outXGIREG(XGIDAC2A, regno);
1351                        outXGIREG(XGIDAC2D, (red >> 8));
1352                        outXGIREG(XGIDAC2D, (green >> 8));
1353                        outXGIREG(XGIDAC2D, (blue >> 8));
1354                }
1355                break;
1356        case 16:
1357                ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800))
1358                                | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
1359                                >> 11);
1360                break;
1361        case 32:
1362                red >>= 8;
1363                green >>= 8;
1364                blue >>= 8;
1365                ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green
1366                                << 8) | (blue);
1367                break;
1368        }
1369        return 0;
1370}
1371
1372static int XGIfb_set_par(struct fb_info *info)
1373{
1374        int err;
1375
1376        /* printk("XGIfb: inside set_par\n"); */
1377        err = XGIfb_do_set_var(&info->var, 1, info);
1378        if (err)
1379                return err;
1380        XGIfb_get_fix(&info->fix, -1, info);
1381        /* printk("XGIfb: end of set_par\n"); */
1382        return 0;
1383}
1384
1385static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1386{
1387        unsigned int htotal = var->left_margin + var->xres + var->right_margin
1388                        + var->hsync_len;
1389        unsigned int vtotal = 0;
1390        unsigned int drate = 0, hrate = 0;
1391        int found_mode = 0;
1392        int refresh_rate, search_idx;
1393
1394        DEBUGPRN("Inside check_var");
1395
1396        if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1397                vtotal = var->upper_margin + var->yres + var->lower_margin
1398                                + var->vsync_len;
1399                vtotal <<= 1;
1400        } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1401                vtotal = var->upper_margin + var->yres + var->lower_margin
1402                                + var->vsync_len;
1403                vtotal <<= 2;
1404        } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1405                vtotal = var->upper_margin + (var->yres / 2)
1406                                + var->lower_margin + var->vsync_len;
1407        } else
1408                vtotal = var->upper_margin + var->yres + var->lower_margin
1409                                + var->vsync_len;
1410
1411        if (!(htotal) || !(vtotal))
1412                XGIFAIL("XGIfb: no valid timing data");
1413
1414        if (var->pixclock && htotal && vtotal) {
1415                drate = 1000000000 / var->pixclock;
1416                hrate = (drate * 1000) / htotal;
1417                xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1418                printk(KERN_DEBUG
1419                        "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1420                        "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1421                        __func__, var->pixclock, htotal, vtotal,
1422                        __func__, drate, hrate, xgi_video_info.refresh_rate);
1423        } else {
1424                xgi_video_info.refresh_rate = 60;
1425        }
1426
1427        /*
1428        if ((var->pixclock) && (htotal)) {
1429                drate = 1E12 / var->pixclock;
1430                hrate = drate / htotal;
1431                refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1432        } else {
1433                refresh_rate = 60;
1434        }
1435        */
1436        /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1437        if ((var->xres == 1024) && (var->yres == 600))
1438                refresh_rate = 60;
1439
1440        search_idx = 0;
1441        while ((XGIbios_mode[search_idx].mode_no != 0) &&
1442                (XGIbios_mode[search_idx].xres <= var->xres)) {
1443                if ((XGIbios_mode[search_idx].xres == var->xres) &&
1444                        (XGIbios_mode[search_idx].yres == var->yres) &&
1445                        (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1446                        if (XGIfb_validate_mode(search_idx) > 0) {
1447                                found_mode = 1;
1448                                break;
1449                        }
1450                }
1451                search_idx++;
1452        }
1453
1454        if (!found_mode) {
1455
1456                printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1457                        var->xres, var->yres, var->bits_per_pixel);
1458                search_idx = 0;
1459                while (XGIbios_mode[search_idx].mode_no != 0) {
1460
1461                        if ((var->xres <= XGIbios_mode[search_idx].xres) &&
1462                                (var->yres <= XGIbios_mode[search_idx].yres) &&
1463                                (var->bits_per_pixel == XGIbios_mode[search_idx].bpp)) {
1464                                if (XGIfb_validate_mode(search_idx) > 0) {
1465                                        found_mode = 1;
1466                                        break;
1467                                }
1468                        }
1469                        search_idx++;
1470                }
1471                if (found_mode) {
1472                        var->xres = XGIbios_mode[search_idx].xres;
1473                        var->yres = XGIbios_mode[search_idx].yres;
1474                        printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1475                                var->xres, var->yres, var->bits_per_pixel);
1476
1477                } else {
1478                        printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1479                                var->xres, var->yres, var->bits_per_pixel);
1480                        return -EINVAL;
1481                }
1482        }
1483
1484        /* TW: TODO: Check the refresh rate */
1485
1486        /* Adapt RGB settings */
1487        XGIfb_bpp_to_var(var);
1488
1489        /* Sanity check for offsets */
1490        if (var->xoffset < 0)
1491                var->xoffset = 0;
1492        if (var->yoffset < 0)
1493                var->yoffset = 0;
1494
1495        if (!XGIfb_ypan) {
1496                if (var->xres != var->xres_virtual)
1497                        var->xres_virtual = var->xres;
1498                if (var->yres != var->yres_virtual)
1499                        var->yres_virtual = var->yres;
1500        } /* else { */
1501                /* TW: Now patch yres_virtual if we use panning */
1502                /* May I do this? */
1503                /* var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3)); */
1504                /* if (var->yres_virtual <= var->yres) { */
1505                /* TW: Paranoia check */
1506                /* var->yres_virtual = var->yres; */
1507                /* } */
1508        /* } */
1509
1510        /* Truncate offsets to maximum if too high */
1511        if (var->xoffset > var->xres_virtual - var->xres)
1512                var->xoffset = var->xres_virtual - var->xres - 1;
1513
1514        if (var->yoffset > var->yres_virtual - var->yres)
1515                var->yoffset = var->yres_virtual - var->yres - 1;
1516
1517        /* Set everything else to 0 */
1518        var->red.msb_right =
1519        var->green.msb_right =
1520        var->blue.msb_right =
1521        var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1522
1523        DEBUGPRN("end of check_var");
1524        return 0;
1525}
1526
1527#ifdef XGIFB_PAN
1528static int XGIfb_pan_display(struct fb_var_screeninfo *var,
1529                struct fb_info *info)
1530{
1531        int err;
1532
1533        /* printk("\nInside pan_display:\n"); */
1534
1535        if (var->xoffset > (var->xres_virtual - var->xres))
1536                return -EINVAL;
1537        if (var->yoffset > (var->yres_virtual - var->yres))
1538                return -EINVAL;
1539
1540        if (var->vmode & FB_VMODE_YWRAP) {
1541                if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual
1542                                || var->xoffset)
1543                        return -EINVAL;
1544        } else {
1545                if (var->xoffset + info->var.xres > info->var.xres_virtual
1546                                || var->yoffset + info->var.yres
1547                                                > info->var.yres_virtual)
1548                        return -EINVAL;
1549        }
1550        err = XGIfb_pan_var(var);
1551        if (err < 0)
1552                return err;
1553
1554        info->var.xoffset = var->xoffset;
1555        info->var.yoffset = var->yoffset;
1556        if (var->vmode & FB_VMODE_YWRAP)
1557                info->var.vmode |= FB_VMODE_YWRAP;
1558        else
1559                info->var.vmode &= ~FB_VMODE_YWRAP;
1560
1561        /* printk("End of pan_display\n"); */
1562        return 0;
1563}
1564#endif
1565
1566static int XGIfb_blank(int blank, struct fb_info *info)
1567{
1568        u8 reg;
1569
1570        inXGIIDXREG(XGICR, 0x17, reg);
1571
1572        if (blank > 0)
1573                reg &= 0x7f;
1574        else
1575                reg |= 0x80;
1576
1577        outXGIIDXREG(XGICR, 0x17, reg);
1578        outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
1579        outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
1580        return 0;
1581}
1582
1583static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
1584                unsigned long arg)
1585{
1586        DEBUGPRN("inside ioctl");
1587        switch (cmd) {
1588        case FBIO_ALLOC:
1589                if (!capable(CAP_SYS_RAWIO))
1590                        return -EPERM;
1591                XGI_malloc((struct XGI_memreq *) arg);
1592                break;
1593        case FBIO_FREE:
1594                if (!capable(CAP_SYS_RAWIO))
1595                        return -EPERM;
1596                XGI_free(*(unsigned long *) arg);
1597                break;
1598        case FBIOGET_HWCINFO: {
1599                unsigned long *hwc_offset = (unsigned long *) arg;
1600
1601                if (XGIfb_caps & HW_CURSOR_CAP)
1602                        *hwc_offset
1603                                        = XGIfb_hwcursor_vbase
1604                                                        - (unsigned long) xgi_video_info.video_vbase;
1605                else
1606                        *hwc_offset = 0;
1607
1608                break;
1609        }
1610        case FBIOPUT_MODEINFO: {
1611                struct mode_info *x = (struct mode_info *) arg;
1612
1613                xgi_video_info.video_bpp = x->bpp;
1614                xgi_video_info.video_width = x->xres;
1615                xgi_video_info.video_height = x->yres;
1616                xgi_video_info.video_vwidth = x->v_xres;
1617                xgi_video_info.video_vheight = x->v_yres;
1618                xgi_video_info.org_x = x->org_x;
1619                xgi_video_info.org_y = x->org_y;
1620                xgi_video_info.refresh_rate = x->vrate;
1621                xgi_video_info.video_linelength = xgi_video_info.video_vwidth
1622                                * (xgi_video_info.video_bpp >> 3);
1623                switch (xgi_video_info.video_bpp) {
1624                case 8:
1625                        xgi_video_info.DstColor = 0x0000;
1626                        xgi_video_info.XGI310_AccelDepth = 0x00000000;
1627                        xgi_video_info.video_cmap_len = 256;
1628                        break;
1629                case 16:
1630                        xgi_video_info.DstColor = 0x8000;
1631                        xgi_video_info.XGI310_AccelDepth = 0x00010000;
1632                        xgi_video_info.video_cmap_len = 16;
1633                        break;
1634                case 32:
1635                        xgi_video_info.DstColor = 0xC000;
1636                        xgi_video_info.XGI310_AccelDepth = 0x00020000;
1637                        xgi_video_info.video_cmap_len = 16;
1638                        break;
1639                default:
1640                        xgi_video_info.video_cmap_len = 16;
1641                        printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
1642                        xgi_video_info.accel = 0;
1643                        break;
1644                }
1645
1646                break;
1647        }
1648        case FBIOGET_DISPINFO:
1649                XGI_dispinfo((struct ap_data *) arg);
1650                break;
1651        case XGIFB_GET_INFO: /* TW: New for communication with X driver */
1652        {
1653                struct XGIfb_info *x = (struct XGIfb_info *) arg;
1654
1655                /* x->XGIfb_id = XGIFB_ID; */
1656                x->XGIfb_version = VER_MAJOR;
1657                x->XGIfb_revision = VER_MINOR;
1658                x->XGIfb_patchlevel = VER_LEVEL;
1659                x->chip_id = xgi_video_info.chip_id;
1660                x->memory = xgi_video_info.video_size / 1024;
1661                x->heapstart = xgi_video_info.heapstart / 1024;
1662                x->fbvidmode = XGIfb_mode_no;
1663                x->XGIfb_caps = XGIfb_caps;
1664                x->XGIfb_tqlen = 512; /* yet unused */
1665                x->XGIfb_pcibus = xgi_video_info.pcibus;
1666                x->XGIfb_pcislot = xgi_video_info.pcislot;
1667                x->XGIfb_pcifunc = xgi_video_info.pcifunc;
1668                x->XGIfb_lcdpdc = XGIfb_detectedpdc;
1669                x->XGIfb_lcda = XGIfb_detectedlcda;
1670                break;
1671        }
1672        case XGIFB_GET_VBRSTATUS: {
1673                unsigned long *vbrstatus = (unsigned long *) arg;
1674                if (XGIfb_CheckVBRetrace())
1675                        *vbrstatus = 1;
1676                else
1677                        *vbrstatus = 0;
1678        }
1679        default:
1680                return -EINVAL;
1681        } DEBUGPRN("end of ioctl");
1682        return 0;
1683
1684}
1685
1686/* ----------- FBDev related routines for all series ---------- */
1687
1688static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1689                struct fb_info *info)
1690{
1691        DEBUGPRN("inside get_fix");
1692        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1693
1694        strcpy(fix->id, myid);
1695
1696        fix->smem_start = xgi_video_info.video_base;
1697
1698        fix->smem_len = xgi_video_info.video_size;
1699
1700        /*        if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1701         if (xgi_video_info.video_size > 0x1000000) {
1702         fix->smem_len = 0xD00000;
1703         } else if (xgi_video_info.video_size > 0x800000)
1704         fix->smem_len = 0x800000;
1705         else
1706         fix->smem_len = 0x400000;
1707         } else
1708         fix->smem_len = XGIfb_mem * 1024;
1709         */
1710        fix->type = video_type;
1711        fix->type_aux = 0;
1712        if (xgi_video_info.video_bpp == 8)
1713                fix->visual = FB_VISUAL_PSEUDOCOLOR;
1714        else
1715                fix->visual = FB_VISUAL_DIRECTCOLOR;
1716        fix->xpanstep = 0;
1717#ifdef XGIFB_PAN
1718        if (XGIfb_ypan)
1719                fix->ypanstep = 1;
1720#endif
1721        fix->ywrapstep = 0;
1722        fix->line_length = xgi_video_info.video_linelength;
1723        fix->mmio_start = xgi_video_info.mmio_base;
1724        fix->mmio_len = XGIfb_mmio_size;
1725        if (xgi_video_info.chip >= XG40)
1726                fix->accel = FB_ACCEL_XGI_XABRE;
1727        else
1728                fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
1729
1730        DEBUGPRN("end of get_fix");
1731        return 0;
1732}
1733
1734static struct fb_ops XGIfb_ops = {
1735        .owner = THIS_MODULE,
1736        .fb_open = XGIfb_open,
1737        .fb_release = XGIfb_release,
1738        .fb_check_var = XGIfb_check_var,
1739        .fb_set_par = XGIfb_set_par,
1740        .fb_setcolreg = XGIfb_setcolreg,
1741#ifdef XGIFB_PAN
1742        .fb_pan_display = XGIfb_pan_display,
1743#endif
1744        .fb_blank = XGIfb_blank,
1745        .fb_fillrect = fbcon_XGI_fillrect,
1746        .fb_copyarea = fbcon_XGI_copyarea,
1747        .fb_imageblit = cfb_imageblit,
1748        .fb_sync = fbcon_XGI_sync,
1749        .fb_ioctl = XGIfb_ioctl,
1750        /* .fb_mmap = XGIfb_mmap, */
1751};
1752
1753/* ---------------- Chip generation dependent routines ---------------- */
1754
1755/* for XGI 315/550/650/740/330 */
1756
1757static int XGIfb_get_dram_size(void)
1758{
1759
1760        u8 ChannelNum, tmp;
1761        u8 reg = 0;
1762
1763        /* xorg driver sets 32MB * 1 channel */
1764        if (xgi_video_info.chip == XG27)
1765                outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1766
1767        inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
1768        switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1769        case XGI_DRAM_SIZE_1MB:
1770                xgi_video_info.video_size = 0x100000;
1771                break;
1772        case XGI_DRAM_SIZE_2MB:
1773                xgi_video_info.video_size = 0x200000;
1774                break;
1775        case XGI_DRAM_SIZE_4MB:
1776                xgi_video_info.video_size = 0x400000;
1777                break;
1778        case XGI_DRAM_SIZE_8MB:
1779                xgi_video_info.video_size = 0x800000;
1780                break;
1781        case XGI_DRAM_SIZE_16MB:
1782                xgi_video_info.video_size = 0x1000000;
1783                break;
1784        case XGI_DRAM_SIZE_32MB:
1785                xgi_video_info.video_size = 0x2000000;
1786                break;
1787        case XGI_DRAM_SIZE_64MB:
1788                xgi_video_info.video_size = 0x4000000;
1789                break;
1790        case XGI_DRAM_SIZE_128MB:
1791                xgi_video_info.video_size = 0x8000000;
1792                break;
1793        case XGI_DRAM_SIZE_256MB:
1794                xgi_video_info.video_size = 0x10000000;
1795                break;
1796        default:
1797                return -1;
1798        }
1799
1800        tmp = (reg & 0x0c) >> 2;
1801        switch (xgi_video_info.chip) {
1802        case XG20:
1803        case XG21:
1804        case XG27:
1805                ChannelNum = 1;
1806                break;
1807
1808        case XG42:
1809                if (reg & 0x04)
1810                        ChannelNum = 2;
1811                else
1812                        ChannelNum = 1;
1813                break;
1814
1815        case XG45:
1816                if (tmp == 1)
1817                        ChannelNum = 2;
1818                else if (tmp == 2)
1819                        ChannelNum = 3;
1820                else if (tmp == 3)
1821                        ChannelNum = 4;
1822                else
1823                        ChannelNum = 1;
1824                break;
1825
1826        case XG40:
1827        default:
1828                if (tmp == 2)
1829                        ChannelNum = 2;
1830                else if (tmp == 3)
1831                        ChannelNum = 3;
1832                else
1833                        ChannelNum = 1;
1834                break;
1835        }
1836
1837        xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1838        /* PLiad fixed for benchmarking and fb set */
1839        /* xgi_video_info.video_size = 0x200000; */ /* 1024x768x16 */
1840        /* xgi_video_info.video_size = 0x1000000; */ /* benchmark */
1841
1842        printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n", reg,
1843                        xgi_video_info.video_size, ChannelNum);
1844        return 0;
1845
1846}
1847
1848static void XGIfb_detect_VB(void)
1849{
1850        u8 cr32, temp = 0;
1851
1852        xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1853
1854        switch (xgi_video_info.hasVB) {
1855        case HASVB_LVDS_CHRONTEL:
1856        case HASVB_CHRONTEL:
1857                break;
1858        case HASVB_301:
1859        case HASVB_302:
1860                /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1861                break;
1862        }
1863
1864        inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
1865
1866        if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1867                XGIfb_crt1off = 0;
1868        else {
1869                if (cr32 & 0x5F)
1870                        XGIfb_crt1off = 1;
1871                else
1872                        XGIfb_crt1off = 0;
1873        }
1874
1875        if (XGIfb_crt2type != -1)
1876                /* TW: Override with option */
1877                xgi_video_info.disp_state = XGIfb_crt2type;
1878        else if (cr32 & XGI_VB_TV)
1879                xgi_video_info.disp_state = DISPTYPE_TV;
1880        else if (cr32 & XGI_VB_LCD)
1881                xgi_video_info.disp_state = DISPTYPE_LCD;
1882        else if (cr32 & XGI_VB_CRT2)
1883                xgi_video_info.disp_state = DISPTYPE_CRT2;
1884        else
1885                xgi_video_info.disp_state = 0;
1886
1887        if (XGIfb_tvplug != -1)
1888                /* PR/TW: Override with option */
1889                xgi_video_info.TV_plug = XGIfb_tvplug;
1890        else if (cr32 & XGI_VB_HIVISION) {
1891                xgi_video_info.TV_type = TVMODE_HIVISION;
1892                xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1893        } else if (cr32 & XGI_VB_SVIDEO)
1894                xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1895        else if (cr32 & XGI_VB_COMPOSITE)
1896                xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1897        else if (cr32 & XGI_VB_SCART)
1898                xgi_video_info.TV_plug = TVPLUG_SCART;
1899
1900        if (xgi_video_info.TV_type == 0) {
1901                /* TW: PAL/NTSC changed for 650 */
1902                if ((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip
1903                                >= XGI_330)) {
1904
1905                        inXGIIDXREG(XGICR, 0x38, temp);
1906                        if (temp & 0x10)
1907                                xgi_video_info.TV_type = TVMODE_PAL;
1908                        else
1909                                xgi_video_info.TV_type = TVMODE_NTSC;
1910
1911                } else {
1912
1913                        inXGIIDXREG(XGICR, 0x79, temp);
1914                        if (temp & 0x20)
1915                                xgi_video_info.TV_type = TVMODE_PAL;
1916                        else
1917                                xgi_video_info.TV_type = TVMODE_NTSC;
1918                }
1919        }
1920
1921        /* TW: Copy forceCRT1 option to CRT1off if option is given */
1922        if (XGIfb_forcecrt1 != -1) {
1923                if (XGIfb_forcecrt1)
1924                        XGIfb_crt1off = 0;
1925                else
1926                        XGIfb_crt1off = 1;
1927        }
1928}
1929
1930static void XGIfb_get_VB_type(void)
1931{
1932        u8 reg;
1933
1934        if (!XGIfb_has_VB()) {
1935                inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
1936                switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1937                case XGI310_EXTERNAL_CHIP_LVDS:
1938                        xgi_video_info.hasVB = HASVB_LVDS;
1939                        break;
1940                case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1941                        xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1942                        break;
1943                default:
1944                        break;
1945                }
1946        }
1947}
1948
1949static int XGIfb_has_VB(void)
1950{
1951        u8 vb_chipid;
1952
1953        inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
1954        switch (vb_chipid) {
1955        case 0x01:
1956                xgi_video_info.hasVB = HASVB_301;
1957                break;
1958        case 0x02:
1959                xgi_video_info.hasVB = HASVB_302;
1960                break;
1961        default:
1962                xgi_video_info.hasVB = HASVB_NONE;
1963                return 0;
1964        }
1965        return 1;
1966}
1967
1968/* ------------------ Sensing routines ------------------ */
1969
1970/* TW: Determine and detect attached devices on XGI30x */
1971int XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
1972{
1973        int temp, i;
1974
1975        outXGIIDXREG(XGIPART4, 0x11, tempbl);
1976        temp = tempbh | tempcl;
1977        setXGIIDXREG(XGIPART4, 0x10, 0xe0, temp);
1978        for (i = 0; i < 10; i++)
1979                XGI_LongWait(&XGI_Pr);
1980        tempch &= 0x7f;
1981        inXGIIDXREG(XGIPART4, 0x03, temp);
1982        temp ^= 0x0e;
1983        temp &= tempch;
1984        return temp;
1985}
1986
1987void XGI_Sense30x(void)
1988{
1989        u8 backupP4_0d;
1990        u8 testsvhs_tempbl, testsvhs_tempbh;
1991        u8 testsvhs_tempcl, testsvhs_tempch;
1992        u8 testcvbs_tempbl, testcvbs_tempbh;
1993        u8 testcvbs_tempcl, testcvbs_tempch;
1994        u8 testvga2_tempbl, testvga2_tempbh;
1995        u8 testvga2_tempcl, testvga2_tempch;
1996        int myflag, result;
1997
1998        inXGIIDXREG(XGIPART4, 0x0d, backupP4_0d);
1999        outXGIIDXREG(XGIPART4, 0x0d, (backupP4_0d | 0x04));
2000
2001        testvga2_tempbh = 0x00;
2002        testvga2_tempbl = 0xd1;
2003        testsvhs_tempbh = 0x00;
2004        testsvhs_tempbl = 0xb9;
2005        testcvbs_tempbh = 0x00;
2006        testcvbs_tempbl = 0xb3;
2007        if ((XGIhw_ext.ujVBChipID != VB_CHIP_301) && (XGIhw_ext.ujVBChipID
2008                        != VB_CHIP_302)) {
2009                testvga2_tempbh = 0x01;
2010                testvga2_tempbl = 0x90;
2011                testsvhs_tempbh = 0x01;
2012                testsvhs_tempbl = 0x6b;
2013                testcvbs_tempbh = 0x01;
2014                testcvbs_tempbl = 0x74;
2015                if (XGIhw_ext.ujVBChipID == VB_CHIP_301LV
2016                                || XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
2017                        testvga2_tempbh = 0x00;
2018                        testvga2_tempbl = 0x00;
2019                        testsvhs_tempbh = 0x02;
2020                        testsvhs_tempbl = 0x00;
2021                        testcvbs_tempbh = 0x01;
2022                        testcvbs_tempbl = 0x00;
2023                }
2024        }
2025        if (XGIhw_ext.ujVBChipID != VB_CHIP_301LV && XGIhw_ext.ujVBChipID
2026                        != VB_CHIP_302LV) {
2027                inXGIIDXREG(XGIPART4, 0x01, myflag);
2028                if (myflag & 0x04) {
2029                        testvga2_tempbh = 0x00;
2030                        testvga2_tempbl = 0xfd;
2031                        testsvhs_tempbh = 0x00;
2032                        testsvhs_tempbl = 0xdd;
2033                        testcvbs_tempbh = 0x00;
2034                        testcvbs_tempbl = 0xee;
2035                }
2036        }
2037        if ((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) || (XGIhw_ext.ujVBChipID
2038                        == VB_CHIP_302LV)) {
2039                testvga2_tempbh = 0x00;
2040                testvga2_tempbl = 0x00;
2041                testvga2_tempch = 0x00;
2042                testvga2_tempcl = 0x00;
2043                testsvhs_tempch = 0x04;
2044                testsvhs_tempcl = 0x08;
2045                testcvbs_tempch = 0x08;
2046                testcvbs_tempcl = 0x08;
2047        } else {
2048                testvga2_tempch = 0x0e;
2049                testvga2_tempcl = 0x08;
2050                testsvhs_tempch = 0x06;
2051                testsvhs_tempcl = 0x04;
2052                testcvbs_tempch = 0x08;
2053                testcvbs_tempcl = 0x04;
2054        }
2055
2056        if (testvga2_tempch || testvga2_tempcl || testvga2_tempbh
2057                        || testvga2_tempbl) {
2058                result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
2059                                testvga2_tempcl, testvga2_tempch);
2060                if (result) {
2061                        printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
2062                        orXGIIDXREG(XGICR, 0x32, 0x10);
2063                }
2064        }
2065
2066        result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh, testsvhs_tempcl,
2067                        testsvhs_tempch);
2068        if (result) {
2069                printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
2070                /* TW: So we can be sure that there IS a SVHS output */
2071                xgi_video_info.TV_plug = TVPLUG_SVIDEO;
2072                orXGIIDXREG(XGICR, 0x32, 0x02);
2073        }
2074
2075        if (!result) {
2076                result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
2077                                testcvbs_tempcl, testcvbs_tempch);
2078                if (result) {
2079                        printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
2080                        /* TW: So we can be sure that there IS a CVBS output */
2081                        xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
2082                        orXGIIDXREG(XGICR, 0x32, 0x01);
2083                }
2084        }
2085        XGIDoSense(0, 0, 0, 0);
2086
2087        outXGIIDXREG(XGIPART4, 0x0d, backupP4_0d);
2088}
2089
2090/* ------------------------ Heap routines -------------------------- */
2091
2092static int XGIfb_heap_init(void)
2093{
2094        XGI_OH *poh;
2095        u8 temp = 0;
2096
2097        int agp_enabled = 1;
2098        u32 agp_size;
2099        unsigned long *cmdq_baseport = NULL;
2100        unsigned long *read_port = NULL;
2101        unsigned long *write_port = NULL;
2102        XGI_CMDTYPE cmd_type;
2103#ifndef AGPOFF
2104        struct agp_kern_info *agp_info;
2105        struct agp_memory *agp;
2106        u32 agp_phys;
2107#endif
2108
2109        /* TW: The heap start is either set manually using the "mem" parameter, or
2110         *     defaults as follows:
2111         *     -) If more than 16MB videoRAM available, let our heap start at 12MB.
2112         *     -) If more than  8MB videoRAM available, let our heap start at  8MB.
2113         *     -) If 4MB or less is available, let it start at 4MB.
2114         *     This is for avoiding a clash with X driver which uses the beginning
2115         *     of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2116         *     in XF86Config-4.
2117         *     The heap start can also be specified by parameter "mem" when starting the XGIfb
2118         *     driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2119         */
2120        if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size / 1024))) {
2121                if (xgi_video_info.video_size > 0x1000000)
2122                        xgi_video_info.heapstart = 0xD00000;
2123                else if (xgi_video_info.video_size > 0x800000)
2124                        xgi_video_info.heapstart = 0x800000;
2125                else
2126                        xgi_video_info.heapstart = 0x400000;
2127        } else {
2128                xgi_video_info.heapstart = XGIfb_mem * 1024;
2129        }
2130        XGIfb_heap_start = (unsigned long) (xgi_video_info.video_vbase
2131                        + xgi_video_info.heapstart);
2132        printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
2133                        (int)(xgi_video_info.heapstart / 1024));
2134
2135        XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase
2136                        + xgi_video_info.video_size;
2137        XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
2138
2139        /* TW: Now initialize the 310 series' command queue mode.
2140         * On 310/325, there are three queue modes available which
2141         * are chosen by setting bits 7:5 in SR26:
2142         * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2143         *    track of the queue, the FIFO, command parsing and so
2144         *    on. This is the one comparable to the 300 series.
2145         * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2146         *    have to do queue management himself. Register 0x85c4 will
2147         *    hold the location of the next free queue slot, 0x85c8
2148         *    is the "queue read pointer" whose way of working is
2149         *    unknown to me. Anyway, this mode would require a
2150         *    translation of the MMIO commands to some kind of
2151         *    accelerator assembly and writing these commands
2152         *    to the memory location pointed to by 0x85c4.
2153         *    We will not use this, as nobody knows how this
2154         *    "assembly" works, and as it would require a complete
2155         *    re-write of the accelerator code.
2156         * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2157         *    queue in AGP memory space.
2158         *
2159         * SR26 bit 4 is called "Bypass H/W queue".
2160         * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2161         * SR26 bit 0 resets the queue
2162         * Size of queue memory is encoded in bits 3:2 like this:
2163         *    00  (0x00)  512K
2164         *    01  (0x04)  1M
2165         *    10  (0x08)  2M
2166         *    11  (0x0C)  4M
2167         * The queue location is to be written to 0x85C0.
2168         *
2169         */
2170        cmdq_baseport = (unsigned long *) (xgi_video_info.mmio_vbase
2171                        + MMIO_QUEUE_PHYBASE);
2172        write_port = (unsigned long *) (xgi_video_info.mmio_vbase
2173                        + MMIO_QUEUE_WRITEPORT);
2174        read_port = (unsigned long *) (xgi_video_info.mmio_vbase
2175                        + MMIO_QUEUE_READPORT);
2176
2177        DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
2178
2179        agp_size = COMMAND_QUEUE_AREA_SIZE;
2180
2181#ifndef AGPOFF
2182        if (XGIfb_queuemode == AGP_CMD_QUEUE) {
2183                agp_info = vzalloc(sizeof(*agp_info));
2184                agp_copy_info(agp_info);
2185
2186                agp_backend_acquire();
2187
2188                agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE / PAGE_SIZE,
2189                                AGP_NORMAL_MEMORY);
2190                if (agp == NULL) {
2191                        DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2192                        agp_enabled = 0;
2193                } else {
2194                        if (agp_bind_memory(agp, agp->pg_start) != 0) {
2195                                DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2196                                /* TODO: Free AGP memory here */
2197                                agp_enabled = 0;
2198                        } else {
2199                                agp_enable(0);
2200                        }
2201                }
2202        }
2203#else
2204        agp_enabled = 0;
2205#endif
2206
2207        /* TW: Now select the queue mode */
2208
2209        if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
2210                cmd_type = AGP_CMD_QUEUE;
2211                printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
2212        /* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE)  */
2213        } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
2214                cmd_type = VM_CMD_QUEUE;
2215                printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
2216        } else {
2217                printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
2218                cmd_type = MMIO_CMD;
2219        }
2220
2221        switch (agp_size) {
2222        case 0x80000:
2223                temp = XGI_CMD_QUEUE_SIZE_512k;
2224                break;
2225        case 0x100000:
2226                temp = XGI_CMD_QUEUE_SIZE_1M;
2227                break;
2228        case 0x200000:
2229                temp = XGI_CMD_QUEUE_SIZE_2M;
2230                break;
2231        case 0x400000:
2232                temp = XGI_CMD_QUEUE_SIZE_4M;
2233                break;
2234        }
2235
2236        switch (cmd_type) {
2237        case AGP_CMD_QUEUE:
2238#ifndef AGPOFF
2239                DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2240                        agp_info->aper_base, agp->physical, agp_size/1024);
2241
2242                agp_phys = agp_info->aper_base + agp->physical;
2243
2244                outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0);
2245                outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
2246
2247                outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2248
2249                outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2250
2251                *write_port = *read_port;
2252
2253                temp |= XGI_AGP_CMDQUEUE_ENABLE;
2254                outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2255
2256                *cmdq_baseport = agp_phys;
2257
2258                XGIfb_caps |= AGP_CMD_QUEUE_CAP;
2259#endif
2260                break;
2261
2262        case VM_CMD_QUEUE:
2263                XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2264                XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2265
2266                outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2267
2268                outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2269
2270                *write_port = *read_port;
2271
2272                temp |= XGI_VRAM_CMDQUEUE_ENABLE;
2273                outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2274
2275                *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2276
2277                XGIfb_caps |= VM_CMD_QUEUE_CAP;
2278
2279                DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2280                        *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2281                break;
2282
2283        default: /* MMIO */
2284
2285                /* printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__); */
2286                /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2287                 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2288                 * enough. Reserve memory in any way.
2289                 */
2290                /* FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE; */
2291                /* FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE; */
2292                /* FIXME */
2293                /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); */
2294                /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET); */
2295                /* FIXME */
2296                /* FIXME *write_port = *read_port; */
2297                /* FIXME */
2298                /* FIXME *//* TW: Set Auto_Correction bit */
2299                /* FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR); */
2300                /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp); */
2301                /* FIXME */
2302                /* FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE; */
2303                /* FIXME */
2304                /* FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP; */
2305                /* FIXME */
2306                /* FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n", */
2307                /* FIXME        *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024); */
2308        break;
2309}
2310
2311        /* TW: Now reserve memory for the HWCursor. It is always located at the very
2312        top of the videoRAM, right below the TB memory area (if used). */
2313        if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
2314                XGIfb_heap_end -= XGIfb_hwcursor_size;
2315                XGIfb_heap_size -= XGIfb_hwcursor_size;
2316                XGIfb_hwcursor_vbase = XGIfb_heap_end;
2317
2318                XGIfb_caps |= HW_CURSOR_CAP;
2319
2320                DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2321                                XGIfb_heap_end, XGIfb_hwcursor_size/1024);
2322        }
2323
2324        XGIfb_heap.poha_chain = NULL;
2325        XGIfb_heap.poh_freelist = NULL;
2326
2327        poh = XGIfb_poh_new_node();
2328
2329        if (poh == NULL)
2330                return 1;
2331
2332        poh->poh_next = &XGIfb_heap.oh_free;
2333        poh->poh_prev = &XGIfb_heap.oh_free;
2334        poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
2335        poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
2336
2337        DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2338                (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
2339                (unsigned int) poh->size / 1024);
2340
2341        DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2342                (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
2343
2344        XGIfb_heap.oh_free.poh_next = poh;
2345        XGIfb_heap.oh_free.poh_prev = poh;
2346        XGIfb_heap.oh_free.size = 0;
2347        XGIfb_heap.max_freesize = poh->size;
2348
2349        XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
2350        XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
2351        XGIfb_heap.oh_used.size = SENTINEL;
2352
2353        return 0;
2354}
2355
2356static XGI_OH *XGIfb_poh_new_node(void)
2357{
2358        int i;
2359        unsigned long cOhs;
2360        XGI_OHALLOC *poha;
2361        XGI_OH *poh;
2362
2363        if (XGIfb_heap.poh_freelist == NULL) {
2364                poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
2365                if (!poha)
2366                        return NULL;
2367
2368                poha->poha_next = XGIfb_heap.poha_chain;
2369                XGIfb_heap.poha_chain = poha;
2370
2371                cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH)
2372                                + 1;
2373
2374                poh = &poha->aoh[0];
2375                for (i = cOhs - 1; i != 0; i--) {
2376                        poh->poh_next = poh + 1;
2377                        poh = poh + 1;
2378                }
2379
2380                poh->poh_next = NULL;
2381                XGIfb_heap.poh_freelist = &poha->aoh[0];
2382        }
2383
2384        poh = XGIfb_heap.poh_freelist;
2385        XGIfb_heap.poh_freelist = poh->poh_next;
2386
2387        return poh;
2388}
2389
2390static XGI_OH *XGIfb_poh_allocate(unsigned long size)
2391{
2392        XGI_OH *pohThis;
2393        XGI_OH *pohRoot;
2394        int bAllocated = 0;
2395
2396        if (size > XGIfb_heap.max_freesize) {
2397                DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2398                                (unsigned int) size / 1024);
2399                return NULL;
2400        }
2401
2402        pohThis = XGIfb_heap.oh_free.poh_next;
2403
2404        while (pohThis != &XGIfb_heap.oh_free) {
2405                if (size <= pohThis->size) {
2406                        bAllocated = 1;
2407                        break;
2408                }
2409                pohThis = pohThis->poh_next;
2410        }
2411
2412        if (!bAllocated) {
2413                DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2414                                (unsigned int) size / 1024);
2415                return NULL;
2416        }
2417
2418        if (size == pohThis->size) {
2419                pohRoot = pohThis;
2420                XGIfb_delete_node(pohThis);
2421        } else {
2422                pohRoot = XGIfb_poh_new_node();
2423
2424                if (pohRoot == NULL)
2425                        return NULL;
2426
2427                pohRoot->offset = pohThis->offset;
2428                pohRoot->size = size;
2429
2430                pohThis->offset += size;
2431                pohThis->size -= size;
2432        }
2433
2434        XGIfb_heap.max_freesize -= size;
2435
2436        pohThis = &XGIfb_heap.oh_used;
2437        XGIfb_insert_node(pohThis, pohRoot);
2438
2439        return pohRoot;
2440}
2441
2442static void XGIfb_delete_node(XGI_OH *poh)
2443{
2444        XGI_OH *poh_prev;
2445        XGI_OH *poh_next;
2446
2447        poh_prev = poh->poh_prev;
2448        poh_next = poh->poh_next;
2449
2450        poh_prev->poh_next = poh_next;
2451        poh_next->poh_prev = poh_prev;
2452
2453}
2454
2455static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
2456{
2457        XGI_OH *pohTemp;
2458
2459        pohTemp = pohList->poh_next;
2460
2461        pohList->poh_next = poh;
2462        pohTemp->poh_prev = poh;
2463
2464        poh->poh_prev = pohList;
2465        poh->poh_next = pohTemp;
2466}
2467
2468static XGI_OH *XGIfb_poh_free(unsigned long base)
2469{
2470        XGI_OH *pohThis;
2471        XGI_OH *poh_freed;
2472        XGI_OH *poh_prev;
2473        XGI_OH *poh_next;
2474        unsigned long ulUpper;
2475        unsigned long ulLower;
2476        int foundNode = 0;
2477
2478        poh_freed = XGIfb_heap.oh_used.poh_next;
2479
2480        while (poh_freed != &XGIfb_heap.oh_used) {
2481                if (poh_freed->offset == base) {
2482                        foundNode = 1;
2483                        break;
2484                }
2485
2486                poh_freed = poh_freed->poh_next;
2487        }
2488
2489        if (!foundNode)
2490                return NULL;
2491
2492        XGIfb_heap.max_freesize += poh_freed->size;
2493
2494        poh_prev = poh_next = NULL;
2495        ulUpper = poh_freed->offset + poh_freed->size;
2496        ulLower = poh_freed->offset;
2497
2498        pohThis = XGIfb_heap.oh_free.poh_next;
2499
2500        while (pohThis != &XGIfb_heap.oh_free) {
2501                if (pohThis->offset == ulUpper)
2502                        poh_next = pohThis;
2503                else if ((pohThis->offset + pohThis->size) == ulLower)
2504                        poh_prev = pohThis;
2505
2506                pohThis = pohThis->poh_next;
2507        }
2508
2509        XGIfb_delete_node(poh_freed);
2510
2511        if (poh_prev && poh_next) {
2512                poh_prev->size += (poh_freed->size + poh_next->size);
2513                XGIfb_delete_node(poh_next);
2514                XGIfb_free_node(poh_freed);
2515                XGIfb_free_node(poh_next);
2516                return poh_prev;
2517        }
2518
2519        if (poh_prev) {
2520                poh_prev->size += poh_freed->size;
2521                XGIfb_free_node(poh_freed);
2522                return poh_prev;
2523        }
2524
2525        if (poh_next) {
2526                poh_next->size += poh_freed->size;
2527                poh_next->offset = poh_freed->offset;
2528                XGIfb_free_node(poh_freed);
2529                return poh_next;
2530        }
2531
2532        XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
2533
2534        return poh_freed;
2535}
2536
2537static void XGIfb_free_node(XGI_OH *poh)
2538{
2539        if (poh == NULL)
2540                return;
2541
2542        poh->poh_next = XGIfb_heap.poh_freelist;
2543        XGIfb_heap.poh_freelist = poh;
2544
2545}
2546
2547void XGI_malloc(struct XGI_memreq *req)
2548{
2549        XGI_OH *poh;
2550
2551        poh = XGIfb_poh_allocate(req->size);
2552
2553        if (poh == NULL) {
2554                req->offset = 0;
2555                req->size = 0;
2556                DPRINTK("XGIfb: Video RAM allocation failed\n");
2557        } else {
2558                DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2559                                (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
2560
2561                req->offset = poh->offset;
2562                req->size = poh->size;
2563        }
2564
2565}
2566
2567void XGI_free(unsigned long base)
2568{
2569        XGI_OH *poh;
2570
2571        poh = XGIfb_poh_free(base);
2572
2573        if (poh == NULL) {
2574                DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2575                                (unsigned int) base);
2576        }
2577}
2578
2579/* --------------------- SetMode routines ------------------------- */
2580
2581static void XGIfb_pre_setmode(void)
2582{
2583        u8 cr30 = 0, cr31 = 0;
2584
2585        inXGIIDXREG(XGICR, 0x31, cr31);
2586        cr31 &= ~0x60;
2587
2588        switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2589        case DISPTYPE_CRT2:
2590                cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2591                cr31 |= XGI_DRIVER_MODE;
2592                break;
2593        case DISPTYPE_LCD:
2594                cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
2595                cr31 |= XGI_DRIVER_MODE;
2596                break;
2597        case DISPTYPE_TV:
2598                if (xgi_video_info.TV_type == TVMODE_HIVISION)
2599                        cr30 = (XGI_VB_OUTPUT_HIVISION
2600                                        | XGI_SIMULTANEOUS_VIEW_ENABLE);
2601                else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
2602                        cr30 = (XGI_VB_OUTPUT_SVIDEO
2603                                        | XGI_SIMULTANEOUS_VIEW_ENABLE);
2604                else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
2605                        cr30 = (XGI_VB_OUTPUT_COMPOSITE
2606                                        | XGI_SIMULTANEOUS_VIEW_ENABLE);
2607                else if (xgi_video_info.TV_plug == TVPLUG_SCART)
2608                        cr30 = (XGI_VB_OUTPUT_SCART
2609                                        | XGI_SIMULTANEOUS_VIEW_ENABLE);
2610                cr31 |= XGI_DRIVER_MODE;
2611
2612                if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
2613                        cr31 |= 0x01;
2614                else
2615                        cr31 &= ~0x01;
2616                break;
2617        default: /* disable CRT2 */
2618                cr30 = 0x00;
2619                cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
2620        }
2621
2622        outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
2623        outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
2624        outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
2625
2626        if (xgi_video_info.accel)
2627                XGIfb_syncaccel();
2628
2629}
2630
2631static void XGIfb_post_setmode(void)
2632{
2633        u8 reg;
2634        unsigned char doit = 1;
2635        /*
2636        outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2637        outXGIIDXREG(XGICR, 0x13, 0x00);
2638        setXGIIDXREG(XGISR,0x0E, 0xF0, 0x01);
2639        *test*
2640        */
2641        if (xgi_video_info.video_bpp == 8) {
2642                /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2643                if ((xgi_video_info.hasVB == HASVB_LVDS)
2644                                || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
2645                        doit = 0;
2646                }
2647                /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2648                if (xgi_video_info.disp_state & DISPTYPE_LCD)
2649                        doit = 0;
2650        }
2651
2652        /* TW: We can't switch off CRT1 if bridge is in slave mode */
2653        if (xgi_video_info.hasVB != HASVB_NONE) {
2654                inXGIIDXREG(XGIPART1, 0x00, reg);
2655
2656                if ((reg & 0x50) == 0x10)
2657                        doit = 0;
2658
2659        } else {
2660                XGIfb_crt1off = 0;
2661        }
2662
2663        inXGIIDXREG(XGICR, 0x17, reg);
2664        if ((XGIfb_crt1off) && (doit))
2665                reg &= ~0x80;
2666        else
2667                reg |= 0x80;
2668        outXGIIDXREG(XGICR, 0x17, reg);
2669
2670        andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
2671
2672        if ((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB
2673                        == HASVB_301)) {
2674
2675                inXGIIDXREG(XGIPART4, 0x01, reg);
2676
2677                if (reg < 0xB0) { /* Set filter for XGI301 */
2678
2679                        switch (xgi_video_info.video_width) {
2680                        case 320:
2681                                filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
2682                                break;
2683                        case 640:
2684                                filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
2685                                break;
2686                        case 720:
2687                                filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
2688                                break;
2689                        case 800:
2690                                filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
2691                                break;
2692                        default:
2693                                filter = -1;
2694                                break;
2695                        }
2696
2697                        orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
2698
2699                        if (xgi_video_info.TV_type == TVMODE_NTSC) {
2700
2701                                andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
2702
2703                                if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2704
2705                                        andXGIIDXREG(XGIPART2, 0x30, 0xdf);
2706
2707                                } else if (xgi_video_info.TV_plug
2708                                                == TVPLUG_COMPOSITE) {
2709
2710                                        orXGIIDXREG(XGIPART2, 0x30, 0x20);
2711
2712                                        switch (xgi_video_info.video_width) {
2713                                        case 640:
2714                                                outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2715                                                outXGIIDXREG(XGIPART2, 0x36, 0x04);
2716                                                outXGIIDXREG(XGIPART2, 0x37, 0x25);
2717                                                outXGIIDXREG(XGIPART2, 0x38, 0x18);
2718                                                break;
2719                                        case 720:
2720                                                outXGIIDXREG(XGIPART2, 0x35, 0xEE);
2721                                                outXGIIDXREG(XGIPART2, 0x36, 0x0C);
2722                                                outXGIIDXREG(XGIPART2, 0x37, 0x22);
2723                                                outXGIIDXREG(XGIPART2, 0x38, 0x08);
2724                                                break;
2725                                        case 800:
2726                                                outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2727                                                outXGIIDXREG(XGIPART2, 0x36, 0x15);
2728                                                outXGIIDXREG(XGIPART2, 0x37, 0x25);
2729                                                outXGIIDXREG(XGIPART2, 0x38, 0xF6);
2730                                                break;
2731                                        }
2732                                }
2733
2734                        } else if (xgi_video_info.TV_type == TVMODE_PAL) {
2735
2736                                andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2737
2738                                if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2739
2740                                        andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2741
2742                                } else if (xgi_video_info.TV_plug
2743                                                == TVPLUG_COMPOSITE) {
2744
2745                                        orXGIIDXREG(XGIPART2, 0x30, 0x20);
2746
2747                                        switch (xgi_video_info.video_width) {
2748                                        case 640:
2749                                                outXGIIDXREG(XGIPART2, 0x35, 0xF1);
2750                                                outXGIIDXREG(XGIPART2, 0x36, 0xF7);
2751                                                outXGIIDXREG(XGIPART2, 0x37, 0x1F);
2752                                                outXGIIDXREG(XGIPART2, 0x38, 0x32);
2753                                                break;
2754                                        case 720:
2755                                                outXGIIDXREG(XGIPART2, 0x35, 0xF3);
2756                                                outXGIIDXREG(XGIPART2, 0x36, 0x00);
2757                                                outXGIIDXREG(XGIPART2, 0x37, 0x1D);
2758                                                outXGIIDXREG(XGIPART2, 0x38, 0x20);
2759                                                break;
2760                                        case 800:
2761                                                outXGIIDXREG(XGIPART2, 0x35, 0xFC);
2762                                                outXGIIDXREG(XGIPART2, 0x36, 0xFB);
2763                                                outXGIIDXREG(XGIPART2, 0x37, 0x14);
2764                                                outXGIIDXREG(XGIPART2, 0x38, 0x2A);
2765                                                break;
2766                                        }
2767                                }
2768                        }
2769
2770                        if ((filter >= 0) && (filter <= 7)) {
2771                                DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2772                                                XGI_TV_filter[filter_tb].filter[filter][0],
2773                                                XGI_TV_filter[filter_tb].filter[filter][1],
2774                                                XGI_TV_filter[filter_tb].filter[filter][2],
2775                                                XGI_TV_filter[filter_tb].filter[filter][3]
2776                                );
2777                                outXGIIDXREG(
2778                                                XGIPART2,
2779                                                0x35,
2780                                                (XGI_TV_filter[filter_tb].filter[filter][0]));
2781                                outXGIIDXREG(
2782                                                XGIPART2,
2783                                                0x36,
2784                                                (XGI_TV_filter[filter_tb].filter[filter][1]));
2785                                outXGIIDXREG(
2786                                                XGIPART2,
2787                                                0x37,
2788                                                (XGI_TV_filter[filter_tb].filter[filter][2]));
2789                                outXGIIDXREG(
2790                                                XGIPART2,
2791                                                0x38,
2792                                                (XGI_TV_filter[filter_tb].filter[filter][3]));
2793                        }
2794
2795                }
2796
2797        }
2798
2799}
2800
2801XGIINITSTATIC int __init XGIfb_setup(char *options)
2802{
2803        char *this_opt;
2804
2805        xgi_video_info.refresh_rate = 0;
2806
2807        printk(KERN_INFO "XGIfb: Options %s\n", options);
2808
2809        if (!options || !*options)
2810                return 0;
2811
2812        while ((this_opt = strsep(&options, ",")) != NULL) {
2813
2814                if (!*this_opt)
2815                        continue;
2816
2817                if (!strncmp(this_opt, "mode:", 5)) {
2818                        XGIfb_search_mode(this_opt + 5);
2819                } else if (!strncmp(this_opt, "vesa:", 5)) {
2820                        XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2821                } else if (!strncmp(this_opt, "mode:", 5)) {
2822                        XGIfb_search_mode(this_opt + 5);
2823                } else if (!strncmp(this_opt, "vesa:", 5)) {
2824                        XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2825                } else if (!strncmp(this_opt, "vrate:", 6)) {
2826                        xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2827                } else if (!strncmp(this_opt, "rate:", 5)) {
2828                        xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2829                } else if (!strncmp(this_opt, "off", 3)) {
2830                        XGIfb_off = 1;
2831                } else if (!strncmp(this_opt, "crt1off", 7)) {
2832                        XGIfb_crt1off = 1;
2833                } else if (!strncmp(this_opt, "filter:", 7)) {
2834                        filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2835                } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2836                        XGIfb_search_crt2type(this_opt + 14);
2837                } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2838                        XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2839                } else if (!strncmp(this_opt, "tvmode:", 7)) {
2840                        XGIfb_search_tvstd(this_opt + 7);
2841                } else if (!strncmp(this_opt, "tvstandard:", 11)) {
2842                        XGIfb_search_tvstd(this_opt + 7);
2843                } else if (!strncmp(this_opt, "mem:", 4)) {
2844                        XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
2845                } else if (!strncmp(this_opt, "dstn", 4)) {
2846                        enable_dstn = 1;
2847                        /* TW: DSTN overrules forcecrt2type */
2848                        XGIfb_crt2type = DISPTYPE_LCD;
2849                } else if (!strncmp(this_opt, "queuemode:", 10)) {
2850                        XGIfb_search_queuemode(this_opt + 10);
2851                } else if (!strncmp(this_opt, "pdc:", 4)) {
2852                        XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2853                        if (XGIfb_pdc & ~0x3c) {
2854                                printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2855                                XGIfb_pdc = 0;
2856                        }
2857                } else if (!strncmp(this_opt, "noaccel", 7)) {
2858                        XGIfb_accel = 0;
2859                } else if (!strncmp(this_opt, "noypan", 6)) {
2860                        XGIfb_ypan = 0;
2861                } else if (!strncmp(this_opt, "userom:", 7)) {
2862                        XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2863                        /* } else if (!strncmp(this_opt, "useoem:", 7)) { */
2864                        /* XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); */
2865                } else {
2866                        XGIfb_search_mode(this_opt);
2867                        /* printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt); */
2868                }
2869
2870                /* TW: Acceleration only with MMIO mode */
2871                if ((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
2872                        XGIfb_ypan = 0;
2873                        XGIfb_accel = 0;
2874                }
2875                /* TW: Panning only with acceleration */
2876                if (XGIfb_accel == 0)
2877                        XGIfb_ypan = 0;
2878
2879        }
2880        printk("\nxgifb: outa xgifb_setup 3450");
2881        return 0;
2882}
2883
2884static unsigned char VBIOS_BUF[65535];
2885
2886static unsigned char *attempt_map_rom(struct pci_dev *dev, void *copy_address)
2887{
2888        u32 rom_size = 0;
2889        u32 rom_address = 0;
2890        int j;
2891
2892        /*  Get the size of the expansion rom */
2893        pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
2894        pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
2895        if ((rom_size & 0x01) == 0) {
2896                printk("No ROM\n");
2897                return NULL;
2898        }
2899
2900        rom_size &= 0xFFFFF800;
2901        rom_size = (~rom_size) + 1;
2902
2903        rom_address = pci_resource_start(dev, 0);
2904        if (rom_address == 0 || rom_address == 0xFFFFFFF0) {
2905                printk("No suitable rom address found\n");
2906                return NULL;
2907        }
2908
2909        printk("ROM Size is %dK, Address is %x\n", rom_size / 1024, rom_address);
2910
2911        /*  Map ROM */
2912        pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address
2913                        | PCI_ROM_ADDRESS_ENABLE);
2914
2915        /* memcpy(copy_address, rom_address, rom_size); */
2916        {
2917                unsigned char *virt_addr = ioremap(rom_address, 0x8000000);
2918
2919                unsigned char *from = (unsigned char *) virt_addr;
2920                unsigned char *to = (unsigned char *) copy_address;
2921                for (j = 0; j < 65536 /*rom_size*/; j++)
2922                        *to++ = *from++;
2923        }
2924
2925        pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
2926
2927        printk("Copy is done\n");
2928
2929        return copy_address;
2930}
2931
2932static int __devinit xgifb_probe(struct pci_dev *pdev,
2933                const struct pci_device_id *ent)
2934{
2935        u16 reg16;
2936        u8 reg, reg1;
2937        u8 CR48, CR38;
2938        if (XGIfb_off)
2939                return -ENXIO;
2940
2941        XGIfb_registered = 0;
2942
2943        memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
2944        fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2945        if (!fb_info)
2946                return -ENOMEM;
2947
2948        xgi_video_info.chip_id = pdev->device;
2949        pci_read_config_byte(pdev, PCI_REVISION_ID, &xgi_video_info.revision_id);
2950        pci_read_config_word(pdev, PCI_COMMAND, &reg16);
2951        XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2952        XGIvga_enabled = reg16 & 0x01;
2953
2954        xgi_video_info.pcibus = pdev->bus->number;
2955        xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2956        xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2957        xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2958        xgi_video_info.subsysdevice = pdev->subsystem_device;
2959
2960        xgi_video_info.video_base = pci_resource_start(pdev, 0);
2961        xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2962        XGIfb_mmio_size = pci_resource_len(pdev, 1);
2963        xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2964        XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
2965        /* XGI_Pr.RelIO  = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
2966        printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2967                        (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2968
2969        if (pci_enable_device(pdev))
2970                return -EIO;
2971
2972        XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
2973
2974        outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2975        inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
2976
2977        if (reg1 != 0xa1) { /*I/O error */
2978                printk("\nXGIfb: I/O error!!!");
2979                return -EIO;
2980        }
2981
2982        switch (xgi_video_info.chip_id) {
2983        case PCI_DEVICE_ID_XG_20:
2984                orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2985                inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
2986                if (CR48&GPIOG_READ)
2987                        xgi_video_info.chip = XG21;
2988                else
2989                        xgi_video_info.chip = XG20;
2990                XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2991                XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2992                break;
2993        case PCI_DEVICE_ID_XG_40:
2994                xgi_video_info.chip = XG40;
2995                XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2996                XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2997                break;
2998        case PCI_DEVICE_ID_XG_41:
2999                xgi_video_info.chip = XG41;
3000                XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3001                XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3002                break;
3003        case PCI_DEVICE_ID_XG_42:
3004                xgi_video_info.chip = XG42;
3005                XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3006                XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3007                break;
3008        case PCI_DEVICE_ID_XG_27:
3009                xgi_video_info.chip = XG27;
3010                XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3011                XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3012                break;
3013        default:
3014                return -ENODEV;
3015        }
3016
3017        printk("XGIfb:chipid = %x\n", xgi_video_info.chip);
3018        XGIhw_ext.jChipType = xgi_video_info.chip;
3019
3020        switch (xgi_video_info.chip) {
3021        case XG40:
3022        case XG41:
3023        case XG42:
3024        case XG45:
3025        case XG20:
3026        case XG21:
3027        case XG27:
3028                XGIhw_ext.bIntegratedMMEnabled = 1;
3029                break;
3030        default:
3031                break;
3032        }
3033
3034        XGIhw_ext.pDevice = NULL;
3035        if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
3036                XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF);
3037
3038                if (XGIhw_ext.pjVirtualRomBase)
3039                        printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n", XGIhw_ext.pjVirtualRomBase);
3040                else
3041                        printk(KERN_INFO "XGIfb: Video ROM not found\n");
3042        } else {
3043                XGIhw_ext.pjVirtualRomBase = NULL;
3044                printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
3045        }
3046        XGIhw_ext.pjCustomizedROMImage = NULL;
3047        XGIhw_ext.bSkipDramSizing = 0;
3048        XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
3049        /* XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space; */
3050        strcpy(XGIhw_ext.szVBIOSVer, "0.84");
3051
3052        XGIhw_ext.pSR = vmalloc(sizeof(struct XGI_DSReg) * SR_BUFFER_SIZE);
3053        if (XGIhw_ext.pSR == NULL) {
3054                printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
3055                return -ENODEV;
3056        }
3057        XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
3058
3059        XGIhw_ext.pCR = vmalloc(sizeof(struct XGI_DSReg) * CR_BUFFER_SIZE);
3060        if (XGIhw_ext.pCR == NULL) {
3061                vfree(XGIhw_ext.pSR);
3062                printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n");
3063                return -ENODEV;
3064        }
3065        XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF;
3066
3067        if (!XGIvga_enabled) {
3068                /* Mapping Max FB Size for 315 Init */
3069                XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3070                if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3071#ifdef LINUXBIOS
3072                        printk("XGIfb: XGIInit() ...");
3073                        /* XGIInitNewt for LINUXBIOS only */
3074                        if (XGIInitNew(&XGIhw_ext))
3075                                printk("OK\n");
3076                        else
3077                                printk("Fail\n");
3078#endif
3079
3080                        outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3081
3082                }
3083        }
3084#ifdef LINUXBIOS
3085        else {
3086                XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3087                if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3088
3089                        outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3090
3091                        /* yilin Because no VBIOS DRAM Sizing, Dram size will error. */
3092                        /* Set SR13 ,14 temporarily for UDtech */
3093                        outXGIIDXREG(XGISR, 0x13, 0x45);
3094                        outXGIIDXREG(XGISR, 0x14, 0x51);
3095
3096                }
3097        }
3098#endif
3099        if (XGIfb_get_dram_size()) {
3100                vfree(XGIhw_ext.pSR);
3101                vfree(XGIhw_ext.pCR);
3102                printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
3103                return -ENODEV;
3104        }
3105
3106        if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3107                /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
3108                orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
3109                /* Enable 2D accelerator engine */
3110                orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
3111        }
3112
3113        XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
3114
3115        if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB")) {
3116                printk("unable request memory size %x", xgi_video_info.video_size);
3117                printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3118                printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
3119                vfree(XGIhw_ext.pSR);
3120                vfree(XGIhw_ext.pCR);
3121                return -ENODEV;
3122        }
3123
3124        if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO")) {
3125                printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
3126                release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size);
3127                vfree(XGIhw_ext.pSR);
3128                vfree(XGIhw_ext.pCR);
3129                return -ENODEV;
3130        }
3131
3132        xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
3133        ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
3134        xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size);
3135
3136        printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3137                        xgi_video_info.video_base, xgi_video_info.video_vbase, xgi_video_info.video_size / 1024);
3138
3139        printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3140                        xgi_video_info.mmio_base, xgi_video_info.mmio_vbase, XGIfb_mmio_size / 1024);
3141        printk("XGIfb: XGIInitNew() ...");
3142        if (XGIInitNew(&XGIhw_ext))
3143                printk("OK\n");
3144        else
3145                printk("Fail\n");
3146
3147        if (XGIfb_heap_init())
3148                printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
3149
3150        xgi_video_info.mtrr = (unsigned int) 0;
3151
3152        if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3153                xgi_video_info.hasVB = HASVB_NONE;
3154                if ((xgi_video_info.chip == XG20) || (xgi_video_info.chip == XG27)) {
3155                        xgi_video_info.hasVB = HASVB_NONE;
3156                } else if (xgi_video_info.chip == XG21) {
3157                        inXGIIDXREG(XGICR, 0x38, CR38);
3158                        if ((CR38&0xE0) == 0xC0) {
3159                                xgi_video_info.disp_state = DISPTYPE_LCD;
3160                                if (!XGIfb_GetXG21LVDSData()) {
3161                                        int m;
3162                                        for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
3163                                                if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
3164                                                                (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
3165                                                        XGINew_SetReg1(XGI_Pr.P3d4, 0x36, m);
3166                                                }
3167                                        }
3168                                }
3169                        } else if ((CR38&0xE0) == 0x60) {
3170                                xgi_video_info.hasVB = HASVB_CHRONTEL;
3171                        } else {
3172                                xgi_video_info.hasVB = HASVB_NONE;
3173                        }
3174                } else {
3175                        XGIfb_get_VB_type();
3176                }
3177
3178                XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
3179
3180                XGIhw_ext.ulExternalChip = 0;
3181
3182                switch (xgi_video_info.hasVB) {
3183                case HASVB_301:
3184                        inXGIIDXREG(XGIPART4, 0x01, reg);
3185                        if (reg >= 0xE0) {
3186                                XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3187                                printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3188                        } else if (reg >= 0xD0) {
3189                                XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3190                                printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
3191                        }
3192                        /* else if (reg >= 0xB0) {
3193                                XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3194                                inXGIIDXREG(XGIPART4, 0x23, reg1);
3195                                printk("XGIfb: XGI301B bridge detected\n");
3196                        } */
3197                        else {
3198                                XGIhw_ext.ujVBChipID = VB_CHIP_301;
3199                                printk("XGIfb: XGI301 bridge detected\n");
3200                        }
3201                        break;
3202                case HASVB_302:
3203                        inXGIIDXREG(XGIPART4, 0x01, reg);
3204                        if (reg >= 0xE0) {
3205                                XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3206                                printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3207                        } else if (reg >= 0xD0) {
3208                                XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3209                                printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3210                        } else if (reg >= 0xB0) {
3211                                inXGIIDXREG(XGIPART4, 0x23, reg1);
3212
3213                                XGIhw_ext.ujVBChipID = VB_CHIP_302B;
3214
3215                        } else {
3216                                XGIhw_ext.ujVBChipID = VB_CHIP_302;
3217                                printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
3218                        }
3219                        break;
3220                case HASVB_LVDS:
3221                        XGIhw_ext.ulExternalChip = 0x1;
3222                        printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
3223                        break;
3224                case HASVB_TRUMPION:
3225                        XGIhw_ext.ulExternalChip = 0x2;
3226                        printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
3227                        break;
3228                case HASVB_CHRONTEL:
3229                        XGIhw_ext.ulExternalChip = 0x4;
3230                        printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
3231                        break;
3232                case HASVB_LVDS_CHRONTEL:
3233                        XGIhw_ext.ulExternalChip = 0x5;
3234                        printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3235                        break;
3236                default:
3237                        printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
3238                        break;
3239                }
3240
3241                if (xgi_video_info.hasVB != HASVB_NONE)
3242                        XGIfb_detect_VB();
3243
3244                if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3245                        if (XGIfb_crt1off)
3246                                xgi_video_info.disp_state |= DISPMODE_SINGLE;
3247                        else
3248                                xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
3249                } else {
3250                        xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
3251                }
3252
3253                if (xgi_video_info.disp_state & DISPTYPE_LCD) {
3254                        if (!enable_dstn) {
3255                                inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
3256                                reg &= 0x0f;
3257                                XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
3258
3259                        } else {
3260                                /* TW: FSTN/DSTN */
3261                                XGIhw_ext.ulCRT2LCDType = LCD_320x480;
3262                        }
3263                }
3264
3265                XGIfb_detectedpdc = 0;
3266
3267                XGIfb_detectedlcda = 0xff;
3268#ifndef LINUXBIOS
3269
3270                /* TW: Try to find about LCDA */
3271
3272                if ((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
3273                                (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
3274                                (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) {
3275                        int tmp;
3276                        inXGIIDXREG(XGICR, 0x34, tmp);
3277                        if (tmp <= 0x13) {
3278                                /* Currently on LCDA? (Some BIOSes leave CR38) */
3279                                inXGIIDXREG(XGICR, 0x38, tmp);
3280                                if ((tmp & 0x03) == 0x03) {
3281                                        /* XGI_Pr.XGI_UseLCDA = 1; */
3282                                } else {
3283                                        /* Currently on LCDA? (Some newer BIOSes set D0 in CR35) */
3284                                        inXGIIDXREG(XGICR, 0x35, tmp);
3285                                        if (tmp & 0x01) {
3286                                                /* XGI_Pr.XGI_UseLCDA = 1; */
3287                                        } else {
3288                                                inXGIIDXREG(XGICR, 0x30, tmp);
3289                                                if (tmp & 0x20) {
3290                                                        inXGIIDXREG(XGIPART1, 0x13, tmp);
3291                                                        if (tmp & 0x04) {
3292                                                                /* XGI_Pr.XGI_UseLCDA = 1; */
3293                                                        }
3294                                                }
3295                                        }
3296                                }
3297                        }
3298
3299                }
3300
3301#endif
3302
3303                if (xgifb_mode_idx >= 0)
3304                        xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
3305
3306                if (xgifb_mode_idx < 0) {
3307                        switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3308                        case DISPTYPE_LCD:
3309                                xgifb_mode_idx = DEFAULT_LCDMODE;
3310                                if (xgi_video_info.chip == XG21)
3311                                        xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
3312                                break;
3313                        case DISPTYPE_TV:
3314                                xgifb_mode_idx = DEFAULT_TVMODE;
3315                                break;
3316                        default:
3317                                xgifb_mode_idx = DEFAULT_MODE;
3318                                break;
3319                        }
3320                }
3321
3322                XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
3323
3324                if (xgi_video_info.refresh_rate == 0)
3325                        xgi_video_info.refresh_rate = 60; /* yilin set default refresh rate */
3326                if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
3327                        XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
3328                        xgi_video_info.refresh_rate = 60;
3329                }
3330
3331                xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
3332                xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
3333                xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
3334                xgi_video_info.org_x = xgi_video_info.org_y = 0;
3335                xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
3336                switch (xgi_video_info.video_bpp) {
3337                case 8:
3338                        xgi_video_info.DstColor = 0x0000;
3339                        xgi_video_info.XGI310_AccelDepth = 0x00000000;
3340                        xgi_video_info.video_cmap_len = 256;
3341                        break;
3342                case 16:
3343                        xgi_video_info.DstColor = 0x8000;
3344                        xgi_video_info.XGI310_AccelDepth = 0x00010000;
3345                        xgi_video_info.video_cmap_len = 16;
3346                        break;
3347                case 32:
3348                        xgi_video_info.DstColor = 0xC000;
3349                        xgi_video_info.XGI310_AccelDepth = 0x00020000;
3350                        xgi_video_info.video_cmap_len = 16;
3351                        break;
3352                default:
3353                        xgi_video_info.video_cmap_len = 16;
3354                        printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
3355                        break;
3356                }
3357
3358                printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3359                                xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
3360                                xgi_video_info.refresh_rate);
3361
3362                default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
3363                default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
3364                default_var.bits_per_pixel = xgi_video_info.video_bpp;
3365
3366                XGIfb_bpp_to_var(&default_var);
3367
3368                default_var.pixclock = (u32) (1000000000 /
3369                                XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
3370                                                XGIfb_mode_no, XGIfb_rate_idx));
3371
3372                if (XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
3373                        XGIfb_mode_no, XGIfb_rate_idx,
3374                        &default_var.left_margin, &default_var.right_margin,
3375                        &default_var.upper_margin, &default_var.lower_margin,
3376                        &default_var.hsync_len, &default_var.vsync_len,
3377                        &default_var.sync, &default_var.vmode)) {
3378
3379                        if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3380                                default_var.yres <<= 1;
3381                                default_var.yres_virtual <<= 1;
3382                        } else if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
3383                                default_var.pixclock >>= 1;
3384                                default_var.yres >>= 1;
3385                                default_var.yres_virtual >>= 1;
3386                        }
3387
3388                }
3389
3390                xgi_video_info.accel = 0;
3391                if (XGIfb_accel) {
3392                        xgi_video_info.accel = -1;
3393                        default_var.accel_flags |= FB_ACCELF_TEXT;
3394                        XGIfb_initaccel();
3395                }
3396
3397                fb_info->flags = FBINFO_FLAG_DEFAULT;
3398                fb_info->var = default_var;
3399                fb_info->fix = XGIfb_fix;
3400                fb_info->par = &xgi_video_info;
3401                fb_info->screen_base = xgi_video_info.video_vbase;
3402                fb_info->fbops = &XGIfb_ops;
3403                XGIfb_get_fix(&fb_info->fix, -1, fb_info);
3404                fb_info->pseudo_palette = pseudo_palette;
3405
3406                fb_alloc_cmap(&fb_info->cmap, 256 , 0);
3407
3408#ifdef CONFIG_MTRR
3409                xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
3410                                (unsigned int) xgi_video_info.video_size,
3411                                MTRR_TYPE_WRCOMB, 1);
3412                if (xgi_video_info.mtrr)
3413                        printk(KERN_INFO "XGIfb: Added MTRRs\n");
3414#endif
3415
3416                if (register_framebuffer(fb_info) < 0)
3417                        return -EINVAL;
3418
3419                XGIfb_registered = 1;
3420
3421                printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3422                                fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
3423
3424        }
3425
3426        dumpVGAReg();
3427
3428        return 0;
3429}
3430
3431/*****************************************************/
3432/*                PCI DEVICE HANDLING                */
3433/*****************************************************/
3434
3435static void __devexit xgifb_remove(struct pci_dev *pdev)
3436{
3437        /* Unregister the framebuffer */
3438        /* if (xgi_video_info.registered) { */
3439        unregister_framebuffer(fb_info);
3440        framebuffer_release(fb_info);
3441        /* } */
3442
3443        pci_set_drvdata(pdev, NULL);
3444
3445};
3446
3447static struct pci_driver xgifb_driver = {
3448        .name = "xgifb",
3449        .id_table = xgifb_pci_table,
3450        .probe = xgifb_probe,
3451        .remove = __devexit_p(xgifb_remove)
3452};
3453
3454XGIINITSTATIC int __init xgifb_init(void)
3455{
3456        char *option = NULL;
3457
3458        if (fb_get_options("xgifb", &option))
3459                return -ENODEV;
3460        XGIfb_setup(option);
3461
3462        return pci_register_driver(&xgifb_driver);
3463}
3464
3465#ifndef MODULE
3466module_init(xgifb_init);
3467#endif
3468
3469/*****************************************************/
3470/*                      MODULE                       */
3471/*****************************************************/
3472
3473#ifdef MODULE
3474
3475static char *mode = NULL;
3476static int vesa = 0;
3477static unsigned int rate = 0;
3478static unsigned int mem = 0;
3479static char *forcecrt2type = NULL;
3480static int forcecrt1 = -1;
3481static int pdc = -1;
3482static int pdc1 = -1;
3483static int noaccel = -1;
3484static int noypan = -1;
3485static int nomax = -1;
3486static int userom = -1;
3487static int useoem = -1;
3488static char *tvstandard = NULL;
3489static int nocrt2rate = 0;
3490static int scalelcd = -1;
3491static char *specialtiming = NULL;
3492static int lvdshl = -1;
3493static int tvxposoffset = 0, tvyposoffset = 0;
3494#if !defined(__i386__) && !defined(__x86_64__)
3495static int resetcard = 0;
3496static int videoram = 0;
3497#endif
3498
3499MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3500MODULE_LICENSE("GPL");
3501MODULE_AUTHOR("XGITECH , Others");
3502
3503module_param(mem, int, 0);
3504module_param(noaccel, int, 0);
3505module_param(noypan, int, 0);
3506module_param(nomax, int, 0);
3507module_param(userom, int, 0);
3508module_param(useoem, int, 0);
3509module_param(mode, charp, 0);
3510module_param(vesa, int, 0);
3511module_param(rate, int, 0);
3512module_param(forcecrt1, int, 0);
3513module_param(forcecrt2type, charp, 0);
3514module_param(scalelcd, int, 0);
3515module_param(pdc, int, 0);
3516module_param(pdc1, int, 0);
3517module_param(specialtiming, charp, 0);
3518module_param(lvdshl, int, 0);
3519module_param(tvstandard, charp, 0);
3520module_param(tvxposoffset, int, 0);
3521module_param(tvyposoffset, int, 0);
3522module_param(filter, int, 0);
3523module_param(nocrt2rate, int, 0);
3524#if !defined(__i386__) && !defined(__x86_64__)
3525module_param(resetcard, int, 0);
3526module_param(videoram, int, 0);
3527#endif
3528
3529MODULE_PARM_DESC(mem,
3530                "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3531                "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3532                "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3533                "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3534                "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3535                "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3536                "for XFree86 4.x/X.org 6.7 and later.\n");
3537
3538MODULE_PARM_DESC(noaccel,
3539                "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
3540                "(default: 0)\n");
3541
3542MODULE_PARM_DESC(noypan,
3543                "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3544                "will be performed by redrawing the screen. (default: 0)\n");
3545
3546MODULE_PARM_DESC(nomax,
3547                "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3548                "memory for the virtual screen in order to optimize scrolling performance. If\n"
3549                "this is set to anything other than 0, xgifb will not do this and thereby\n"
3550                "enable the user to positively specify a virtual Y size of the screen using\n"
3551                "fbset. (default: 0)\n");
3552
3553MODULE_PARM_DESC(mode,
3554                "\nSelects the desired default display mode in the format XxYxDepth,\n"
3555                "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3556                "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3557                "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3558
3559MODULE_PARM_DESC(vesa,
3560                "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3561                "0x117 (default: 0x0103)\n");
3562
3563MODULE_PARM_DESC(rate,
3564                "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3565                "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3566                "will be ignored (default: 60)\n");
3567
3568MODULE_PARM_DESC(forcecrt1,
3569                "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is\n"
3570                "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3571                "0=CRT1 OFF) (default: [autodetected])\n");
3572
3573MODULE_PARM_DESC(forcecrt2type,
3574                "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3575                "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3576                "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3577                "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3578                "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3579                "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3580                "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3581                "depends on the very hardware in use. (default: [autodetected])\n");
3582
3583MODULE_PARM_DESC(scalelcd,
3584                "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3585                "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3586                "show black bars around the image, TMDS panels will probably do the scaling\n"
3587                "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3588
3589MODULE_PARM_DESC(pdc,
3590                "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3591                "should detect this correctly in most cases; however, sometimes this is not\n"
3592                "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3593                "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3594                "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3595                "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3596
3597MODULE_PARM_DESC(pdc1,
3598                "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3599                "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3600                "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3601                "implemented yet.\n");
3602
3603MODULE_PARM_DESC(specialtiming,
3604                "\nPlease refer to documentation for more information on this option.\n");
3605
3606MODULE_PARM_DESC(lvdshl,
3607                "\nPlease refer to documentation for more information on this option.\n");
3608
3609MODULE_PARM_DESC(tvstandard,
3610                "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3611                "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3612
3613MODULE_PARM_DESC(tvxposoffset,
3614                "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3615                "Default: 0\n");
3616
3617MODULE_PARM_DESC(tvyposoffset,
3618                "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3619                "Default: 0\n");
3620
3621MODULE_PARM_DESC(filter,
3622                "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3623                "(Possible values 0-7, default: [no filter])\n");
3624
3625MODULE_PARM_DESC(nocrt2rate,
3626                "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3627                "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3628
3629static int __init xgifb_init_module(void)
3630{
3631        printk("\nXGIfb_init_module");
3632        if (mode)
3633                XGIfb_search_mode(mode);
3634        else if (vesa != -1)
3635                XGIfb_search_vesamode(vesa);
3636
3637        return xgifb_init();
3638}
3639
3640static void __exit xgifb_remove_module(void)
3641{
3642        pci_unregister_driver(&xgifb_driver);
3643        printk(KERN_DEBUG "xgifb: Module unloaded\n");
3644}
3645
3646module_init(xgifb_init_module);
3647module_exit(xgifb_remove_module);
3648
3649#endif  /*  /MODULE  */
3650
3651EXPORT_SYMBOL(XGI_malloc);
3652EXPORT_SYMBOL(XGI_free);
3653
3654