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#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   8
   9/* #include <linux/config.h> */
  10#include <linux/module.h>
  11#include <linux/moduleparam.h>
  12#include <linux/kernel.h>
  13#include <linux/spinlock.h>
  14#include <linux/errno.h>
  15#include <linux/string.h>
  16#include <linux/mm.h>
  17#include <linux/tty.h>
  18#include <linux/slab.h>
  19#include <linux/delay.h>
  20#include <linux/fb.h>
  21#include <linux/console.h>
  22#include <linux/selection.h>
  23#include <linux/ioport.h>
  24#include <linux/init.h>
  25#include <linux/pci.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#include <linux/io.h>
  33#ifdef CONFIG_MTRR
  34#include <asm/mtrr.h>
  35#endif
  36
  37#include "XGIfb.h"
  38#include "vgatypes.h"
  39#include "XGI_main.h"
  40#include "vb_init.h"
  41#include "vb_util.h"
  42#include "vb_setmode.h"
  43
  44#define Index_CR_GPIO_Reg1 0x48
  45#define Index_CR_GPIO_Reg3 0x4a
  46
  47#define GPIOG_EN    (1<<6)
  48#define GPIOG_READ  (1<<1)
  49
  50static char *forcecrt2type;
  51static char *mode;
  52static int vesa = -1;
  53static unsigned int refresh_rate;
  54
  55/* -------------------- Macro definitions ---------------------------- */
  56
  57#undef XGIFBDEBUG
  58
  59#ifdef XGIFBDEBUG
  60#define DPRINTK(fmt, args...) pr_debug("%s: " fmt, __func__ , ## args)
  61#else
  62#define DPRINTK(fmt, args...)
  63#endif
  64
  65#ifdef XGIFBDEBUG
  66static void dumpVGAReg(void)
  67{
  68        u8 i, reg;
  69
  70        xgifb_reg_set(XGISR, 0x05, 0x86);
  71        /*
  72        xgifb_reg_set(XGISR, 0x08, 0x4f);
  73        xgifb_reg_set(XGISR, 0x0f, 0x20);
  74        xgifb_reg_set(XGISR, 0x11, 0x4f);
  75        xgifb_reg_set(XGISR, 0x13, 0x45);
  76        xgifb_reg_set(XGISR, 0x14, 0x51);
  77        xgifb_reg_set(XGISR, 0x1e, 0x41);
  78        xgifb_reg_set(XGISR, 0x1f, 0x0);
  79        xgifb_reg_set(XGISR, 0x20, 0xa1);
  80        xgifb_reg_set(XGISR, 0x22, 0xfb);
  81        xgifb_reg_set(XGISR, 0x26, 0x22);
  82        xgifb_reg_set(XGISR, 0x3e, 0x07);
  83        */
  84
  85        /* xgifb_reg_set(XGICR, 0x19, 0x00); */
  86        /* xgifb_reg_set(XGICR, 0x1a, 0x3C); */
  87        /* xgifb_reg_set(XGICR, 0x22, 0xff); */
  88        /* xgifb_reg_set(XGICR, 0x3D, 0x10); */
  89
  90        /* xgifb_reg_set(XGICR, 0x4a, 0xf3); */
  91
  92        /* xgifb_reg_set(XGICR, 0x57, 0x0); */
  93        /* xgifb_reg_set(XGICR, 0x7a, 0x2c); */
  94
  95        /* xgifb_reg_set(XGICR, 0x82, 0xcc); */
  96        /* xgifb_reg_set(XGICR, 0x8c, 0x0); */
  97        /*
  98        xgifb_reg_set(XGICR, 0x99, 0x1);
  99        xgifb_reg_set(XGICR, 0x41, 0x40);
 100        */
 101
 102        for (i = 0; i < 0x4f; i++) {
 103                reg = xgifb_reg_get(XGISR, i);
 104                printk("\no 3c4 %x", i);
 105                printk("\ni 3c5 => %x", reg);
 106        }
 107
 108        for (i = 0; i < 0xF0; i++) {
 109                reg = xgifb_reg_get(XGICR, i);
 110                printk("\no 3d4 %x", i);
 111                printk("\ni 3d5 => %x", reg);
 112        }
 113        /*
 114        xgifb_reg_set(XGIPART1,0x2F,1);
 115        for (i=1; i < 0x50; i++) {
 116                reg = xgifb_reg_get(XGIPART1, i);
 117                printk("\no d004 %x", i);
 118                printk("\ni d005 => %x", reg);
 119        }
 120
 121        for (i=0; i < 0x50; i++) {
 122                 reg = xgifb_reg_get(XGIPART2, i);
 123                 printk("\no d010 %x", i);
 124                 printk("\ni d011 => %x", reg);
 125        }
 126        for (i=0; i < 0x50; i++) {
 127                reg = xgifb_reg_get(XGIPART3, i);
 128                printk("\no d012 %x",i);
 129                printk("\ni d013 => %x",reg);
 130        }
 131        for (i=0; i < 0x50; i++) {
 132                reg = xgifb_reg_get(XGIPART4, i);
 133                printk("\no d014 %x",i);
 134                printk("\ni d015 => %x",reg);
 135        }
 136        */
 137}
 138#else
 139static inline void dumpVGAReg(void)
 140{
 141}
 142#endif
 143
 144#if 1
 145#define DEBUGPRN(x)
 146#else
 147#define DEBUGPRN(x) pr_info(x "\n");
 148#endif
 149
 150/* --------------- Hardware Access Routines -------------------------- */
 151
 152static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
 153                struct xgi_hw_device_info *HwDeviceExtension,
 154                unsigned char modeno, unsigned char rateindex)
 155{
 156        unsigned short ModeNo = modeno;
 157        unsigned short ModeIdIndex = 0, ClockIndex = 0;
 158        unsigned short RefreshRateTableIndex = 0;
 159        int Clock;
 160        InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
 161
 162        XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
 163
 164        RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
 165                        ModeIdIndex, XGI_Pr);
 166
 167        ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
 168
 169        Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
 170
 171        return Clock;
 172}
 173
 174static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
 175                struct xgi_hw_device_info *HwDeviceExtension,
 176                unsigned char modeno, unsigned char rateindex,
 177                u32 *left_margin, u32 *right_margin, u32 *upper_margin,
 178                u32 *lower_margin, u32 *hsync_len, u32 *vsync_len, u32 *sync,
 179                u32 *vmode)
 180{
 181        unsigned short ModeNo = modeno;
 182        unsigned short ModeIdIndex, index = 0;
 183        unsigned short RefreshRateTableIndex = 0;
 184
 185        unsigned short VRE, VBE, VRS, VBS, VDE, VT;
 186        unsigned short HRE, HBE, HRS, HBS, HDE, HT;
 187        unsigned char sr_data, cr_data, cr_data2;
 188        unsigned long cr_data3;
 189        int A, B, C, D, E, F, temp, j;
 190        InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
 191        if (!XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr))
 192                return 0;
 193        RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
 194                        ModeIdIndex, XGI_Pr);
 195        index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 196
 197        sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
 198
 199        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
 200
 201        /* Horizontal total */
 202        HT = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8);
 203        A = HT + 5;
 204
 205        HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) - 1;
 206        E = HDE + 1;
 207
 208        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
 209
 210        /* Horizontal retrace (=sync) start */
 211        HRS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0xC0) << 2);
 212        F = HRS - E - 3;
 213
 214        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
 215
 216        /* Horizontal blank start */
 217        HBS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x30) << 4);
 218
 219        sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
 220
 221        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
 222
 223        cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
 224
 225        /* Horizontal blank end */
 226        HBE = (cr_data & 0x1f) | ((unsigned short) (cr_data2 & 0x80) >> 2)
 227                        | ((unsigned short) (sr_data & 0x03) << 6);
 228
 229        /* Horizontal retrace (=sync) end */
 230        HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
 231
 232        temp = HBE - ((E - 1) & 255);
 233        B = (temp > 0) ? temp : (temp + 256);
 234
 235        temp = HRE - ((E + F + 3) & 63);
 236        C = (temp > 0) ? temp : (temp + 64);
 237
 238        D = B - F - C;
 239
 240        *left_margin = D * 8;
 241        *right_margin = F * 8;
 242        *hsync_len = C * 8;
 243
 244        sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
 245
 246        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
 247
 248        cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
 249
 250        /* Vertical total */
 251        VT = (cr_data & 0xFF) | ((unsigned short) (cr_data2 & 0x01) << 8)
 252                        | ((unsigned short) (cr_data2 & 0x20) << 4)
 253                        | ((unsigned short) (sr_data & 0x01) << 10);
 254        A = VT + 2;
 255
 256        /* cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; */
 257
 258        /* Vertical display enable end */
 259        /*
 260        VDE = (cr_data & 0xff) |
 261                ((unsigned short) (cr_data2 & 0x02) << 7) |
 262                ((unsigned short) (cr_data2 & 0x40) << 3) |
 263                ((unsigned short) (sr_data & 0x02) << 9);
 264        */
 265        VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes - 1;
 266        E = VDE + 1;
 267
 268        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
 269
 270        /* Vertical retrace (=sync) start */
 271        VRS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x04) << 6)
 272                        | ((unsigned short) (cr_data2 & 0x80) << 2)
 273                        | ((unsigned short) (sr_data & 0x08) << 7);
 274        F = VRS + 1 - E;
 275
 276        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
 277
 278        cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
 279
 280        /* Vertical blank start */
 281        VBS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x08) << 5)
 282                        | ((unsigned short) (cr_data3 & 0x20) << 4)
 283                        | ((unsigned short) (sr_data & 0x04) << 8);
 284
 285        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
 286
 287        /* Vertical blank end */
 288        VBE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x10) << 4);
 289        temp = VBE - ((E - 1) & 511);
 290        B = (temp > 0) ? temp : (temp + 512);
 291
 292        cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
 293
 294        /* Vertical retrace (=sync) end */
 295        VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
 296        temp = VRE - ((E + F - 1) & 31);
 297        C = (temp > 0) ? temp : (temp + 32);
 298
 299        D = B - F - C;
 300
 301        *upper_margin = D;
 302        *lower_margin = F;
 303        *vsync_len = C;
 304
 305        if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
 306                *sync &= ~FB_SYNC_VERT_HIGH_ACT;
 307        else
 308                *sync |= FB_SYNC_VERT_HIGH_ACT;
 309
 310        if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
 311                *sync &= ~FB_SYNC_HOR_HIGH_ACT;
 312        else
 313                *sync |= FB_SYNC_HOR_HIGH_ACT;
 314
 315        *vmode = FB_VMODE_NONINTERLACED;
 316        if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
 317                *vmode = FB_VMODE_INTERLACED;
 318        else {
 319                j = 0;
 320                while (XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
 321                        if (XGI_Pr->EModeIDTable[j].Ext_ModeID ==
 322                            XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
 323                                if (XGI_Pr->EModeIDTable[j].Ext_ModeFlag &
 324                                    DoubleScanMode) {
 325                                        *vmode = FB_VMODE_DOUBLE;
 326                                }
 327                                break;
 328                        }
 329                        j++;
 330                }
 331        }
 332
 333        return 1;
 334}
 335
 336static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
 337{
 338        XGI_Pr->P3c4 = BaseAddr + 0x14;
 339        XGI_Pr->P3d4 = BaseAddr + 0x24;
 340        XGI_Pr->P3c0 = BaseAddr + 0x10;
 341        XGI_Pr->P3ce = BaseAddr + 0x1e;
 342        XGI_Pr->P3c2 = BaseAddr + 0x12;
 343        XGI_Pr->P3ca = BaseAddr + 0x1a;
 344        XGI_Pr->P3c6 = BaseAddr + 0x16;
 345        XGI_Pr->P3c7 = BaseAddr + 0x17;
 346        XGI_Pr->P3c8 = BaseAddr + 0x18;
 347        XGI_Pr->P3c9 = BaseAddr + 0x19;
 348        XGI_Pr->P3da = BaseAddr + 0x2A;
 349        /* Digital video interface registers (LCD) */
 350        XGI_Pr->Part1Port = BaseAddr + SIS_CRT2_PORT_04;
 351        /* 301 TV Encoder registers */
 352        XGI_Pr->Part2Port = BaseAddr + SIS_CRT2_PORT_10;
 353        /* 301 Macrovision registers */
 354        XGI_Pr->Part3Port = BaseAddr + SIS_CRT2_PORT_12;
 355        /* 301 VGA2 (and LCD) registers */
 356        XGI_Pr->Part4Port = BaseAddr + SIS_CRT2_PORT_14;
 357        /* 301 palette address port registers */
 358        XGI_Pr->Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
 359
 360}
 361
 362/* ------------------ Internal helper routines ----------------- */
 363
 364static int XGIfb_GetXG21DefaultLVDSModeIdx(struct xgifb_video_info *xgifb_info)
 365{
 366
 367        int found_mode = 0;
 368        int XGIfb_mode_idx = 0;
 369
 370        found_mode = 0;
 371        while ((XGIbios_mode[XGIfb_mode_idx].mode_no != 0)
 372                        && (XGIbios_mode[XGIfb_mode_idx].xres
 373                                        <= xgifb_info->lvds_data.LVDSHDE)) {
 374                if ((XGIbios_mode[XGIfb_mode_idx].xres
 375                                == xgifb_info->lvds_data.LVDSHDE)
 376                                && (XGIbios_mode[XGIfb_mode_idx].yres
 377                                        == xgifb_info->lvds_data.LVDSVDE)
 378                                && (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) {
 379                        found_mode = 1;
 380                        break;
 381                }
 382                XGIfb_mode_idx++;
 383        }
 384        if (!found_mode)
 385                XGIfb_mode_idx = -1;
 386
 387        return XGIfb_mode_idx;
 388}
 389
 390static void XGIfb_search_mode(struct xgifb_video_info *xgifb_info,
 391                              const char *name)
 392{
 393        unsigned int xres;
 394        unsigned int yres;
 395        unsigned int bpp;
 396        int i;
 397
 398        if (sscanf(name, "%ux%ux%u", &xres, &yres, &bpp) != 3)
 399                goto invalid_mode;
 400
 401        if (bpp == 24)
 402                bpp = 32; /* That's for people who mix up color and fb depth. */
 403
 404        for (i = 0; XGIbios_mode[i].mode_no != 0; i++)
 405                if (XGIbios_mode[i].xres == xres &&
 406                    XGIbios_mode[i].yres == yres &&
 407                    XGIbios_mode[i].bpp == bpp) {
 408                        xgifb_info->mode_idx = i;
 409                        return;
 410                }
 411invalid_mode:
 412        pr_info("Invalid mode '%s'\n", name);
 413}
 414
 415static void XGIfb_search_vesamode(struct xgifb_video_info *xgifb_info,
 416                                  unsigned int vesamode)
 417{
 418        int i = 0, j = 0;
 419
 420        if (vesamode == 0)
 421                goto invalid;
 422
 423        vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
 424
 425        while (XGIbios_mode[i].mode_no != 0) {
 426                if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
 427                    (XGIbios_mode[i].vesa_mode_no_2 == vesamode)) {
 428                        xgifb_info->mode_idx = i;
 429                        j = 1;
 430                        break;
 431                }
 432                i++;
 433        }
 434
 435invalid:
 436        if (!j)
 437                pr_info("Invalid VESA mode 0x%x'\n", vesamode);
 438}
 439
 440static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex)
 441{
 442        u16 xres, yres;
 443        struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info;
 444
 445        if (xgifb_info->chip == XG21) {
 446                if (xgifb_info->display2 == XGIFB_DISP_LCD) {
 447                        xres = xgifb_info->lvds_data.LVDSHDE;
 448                        yres = xgifb_info->lvds_data.LVDSVDE;
 449                        if (XGIbios_mode[myindex].xres > xres)
 450                                return -1;
 451                        if (XGIbios_mode[myindex].yres > yres)
 452                                return -1;
 453                        if ((XGIbios_mode[myindex].xres < xres) &&
 454                            (XGIbios_mode[myindex].yres < yres)) {
 455                                if (XGIbios_mode[myindex].bpp > 8)
 456                                        return -1;
 457                        }
 458
 459                }
 460                return myindex;
 461
 462        }
 463
 464        /* FIXME: for now, all is valid on XG27 */
 465        if (xgifb_info->chip == XG27)
 466                return myindex;
 467
 468        if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
 469                return -1;
 470
 471        switch (xgifb_info->display2) {
 472        case XGIFB_DISP_LCD:
 473                switch (hw_info->ulCRT2LCDType) {
 474                case LCD_640x480:
 475                        xres = 640;
 476                        yres = 480;
 477                        break;
 478                case LCD_800x600:
 479                        xres = 800;
 480                        yres = 600;
 481                        break;
 482                case LCD_1024x600:
 483                        xres = 1024;
 484                        yres = 600;
 485                        break;
 486                case LCD_1024x768:
 487                        xres = 1024;
 488                        yres = 768;
 489                        break;
 490                case LCD_1152x768:
 491                        xres = 1152;
 492                        yres = 768;
 493                        break;
 494                case LCD_1280x960:
 495                        xres = 1280;
 496                        yres = 960;
 497                        break;
 498                case LCD_1280x768:
 499                        xres = 1280;
 500                        yres = 768;
 501                        break;
 502                case LCD_1280x1024:
 503                        xres = 1280;
 504                        yres = 1024;
 505                        break;
 506                case LCD_1400x1050:
 507                        xres = 1400;
 508                        yres = 1050;
 509                        break;
 510                case LCD_1600x1200:
 511                        xres = 1600;
 512                        yres = 1200;
 513                        break;
 514                default:
 515                        xres = 0;
 516                        yres = 0;
 517                        break;
 518                }
 519                if (XGIbios_mode[myindex].xres > xres)
 520                        return -1;
 521                if (XGIbios_mode[myindex].yres > yres)
 522                        return -1;
 523                if ((hw_info->ulExternalChip == 0x01) || /* LVDS */
 524                    (hw_info->ulExternalChip == 0x05)) { /* LVDS+Chrontel */
 525                        switch (XGIbios_mode[myindex].xres) {
 526                        case 512:
 527                                if (XGIbios_mode[myindex].yres != 512)
 528                                        return -1;
 529                                if (hw_info->ulCRT2LCDType == LCD_1024x600)
 530                                        return -1;
 531                                break;
 532                        case 640:
 533                                if ((XGIbios_mode[myindex].yres != 400)
 534                                                && (XGIbios_mode[myindex].yres
 535                                                                != 480))
 536                                        return -1;
 537                                break;
 538                        case 800:
 539                                if (XGIbios_mode[myindex].yres != 600)
 540                                        return -1;
 541                                break;
 542                        case 1024:
 543                                if ((XGIbios_mode[myindex].yres != 600) &&
 544                                    (XGIbios_mode[myindex].yres != 768))
 545                                        return -1;
 546                                if ((XGIbios_mode[myindex].yres == 600) &&
 547                                    (hw_info->ulCRT2LCDType != LCD_1024x600))
 548                                        return -1;
 549                                break;
 550                        case 1152:
 551                                if ((XGIbios_mode[myindex].yres) != 768)
 552                                        return -1;
 553                                if (hw_info->ulCRT2LCDType != LCD_1152x768)
 554                                        return -1;
 555                                break;
 556                        case 1280:
 557                                if ((XGIbios_mode[myindex].yres != 768) &&
 558                                    (XGIbios_mode[myindex].yres != 1024))
 559                                        return -1;
 560                                if ((XGIbios_mode[myindex].yres == 768) &&
 561                                    (hw_info->ulCRT2LCDType != LCD_1280x768))
 562                                        return -1;
 563                                break;
 564                        case 1400:
 565                                if (XGIbios_mode[myindex].yres != 1050)
 566                                        return -1;
 567                                break;
 568                        case 1600:
 569                                if (XGIbios_mode[myindex].yres != 1200)
 570                                        return -1;
 571                                break;
 572                        default:
 573                                return -1;
 574                        }
 575                } else {
 576                        switch (XGIbios_mode[myindex].xres) {
 577                        case 512:
 578                                if (XGIbios_mode[myindex].yres != 512)
 579                                        return -1;
 580                                break;
 581                        case 640:
 582                                if ((XGIbios_mode[myindex].yres != 400) &&
 583                                    (XGIbios_mode[myindex].yres != 480))
 584                                        return -1;
 585                                break;
 586                        case 800:
 587                                if (XGIbios_mode[myindex].yres != 600)
 588                                        return -1;
 589                                break;
 590                        case 1024:
 591                                if (XGIbios_mode[myindex].yres != 768)
 592                                        return -1;
 593                                break;
 594                        case 1280:
 595                                if ((XGIbios_mode[myindex].yres != 960) &&
 596                                    (XGIbios_mode[myindex].yres != 1024))
 597                                        return -1;
 598                                if (XGIbios_mode[myindex].yres == 960) {
 599                                        if (hw_info->ulCRT2LCDType ==
 600                                            LCD_1400x1050)
 601                                                return -1;
 602                                }
 603                                break;
 604                        case 1400:
 605                                if (XGIbios_mode[myindex].yres != 1050)
 606                                        return -1;
 607                                break;
 608                        case 1600:
 609                                if (XGIbios_mode[myindex].yres != 1200)
 610                                        return -1;
 611                                break;
 612                        default:
 613                                return -1;
 614                        }
 615                }
 616                break;
 617        case XGIFB_DISP_TV:
 618                switch (XGIbios_mode[myindex].xres) {
 619                case 512:
 620                case 640:
 621                case 800:
 622                        break;
 623                case 720:
 624                        if (xgifb_info->TV_type == TVMODE_NTSC) {
 625                                if (XGIbios_mode[myindex].yres != 480)
 626                                        return -1;
 627                        } else if (xgifb_info->TV_type == TVMODE_PAL) {
 628                                if (XGIbios_mode[myindex].yres != 576)
 629                                        return -1;
 630                        }
 631                        /*  TW: LVDS/CHRONTEL does not support 720 */
 632                        if (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL ||
 633                            xgifb_info->hasVB == HASVB_CHRONTEL) {
 634                                return -1;
 635                        }
 636                        break;
 637                case 1024:
 638                        if (xgifb_info->TV_type == TVMODE_NTSC) {
 639                                if (XGIbios_mode[myindex].bpp == 32)
 640                                        return -1;
 641                        }
 642                        break;
 643                default:
 644                        return -1;
 645                }
 646                break;
 647        case XGIFB_DISP_CRT:
 648                if (XGIbios_mode[myindex].xres > 1280)
 649                        return -1;
 650                break;
 651        case XGIFB_DISP_NONE:
 652                break;
 653        }
 654        return myindex;
 655
 656}
 657
 658static void XGIfb_search_crt2type(const char *name)
 659{
 660        int i = 0;
 661
 662        if (name == NULL)
 663                return;
 664
 665        while (XGI_crt2type[i].type_no != -1) {
 666                if (!strcmp(name, XGI_crt2type[i].name)) {
 667                        XGIfb_crt2type = XGI_crt2type[i].type_no;
 668                        XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
 669                        break;
 670                }
 671                i++;
 672        }
 673        if (XGIfb_crt2type < 0)
 674                pr_info("Invalid CRT2 type: %s\n", name);
 675}
 676
 677static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info,
 678                                    unsigned int rate)
 679{
 680        u16 xres, yres;
 681        int i = 0;
 682
 683        xres = XGIbios_mode[xgifb_info->mode_idx].xres;
 684        yres = XGIbios_mode[xgifb_info->mode_idx].yres;
 685
 686        xgifb_info->rate_idx = 0;
 687        while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
 688                if ((XGIfb_vrate[i].xres == xres) &&
 689                    (XGIfb_vrate[i].yres == yres)) {
 690                        if (XGIfb_vrate[i].refresh == rate) {
 691                                xgifb_info->rate_idx = XGIfb_vrate[i].idx;
 692                                break;
 693                        } else if (XGIfb_vrate[i].refresh > rate) {
 694                                if ((XGIfb_vrate[i].refresh - rate) <= 3) {
 695                                        DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
 696                                                rate, XGIfb_vrate[i].refresh);
 697                                        xgifb_info->rate_idx =
 698                                                XGIfb_vrate[i].idx;
 699                                        xgifb_info->refresh_rate =
 700                                                XGIfb_vrate[i].refresh;
 701                                } else if (((rate - XGIfb_vrate[i - 1].refresh)
 702                                                <= 2) && (XGIfb_vrate[i].idx
 703                                                != 1)) {
 704                                        DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
 705                                                rate, XGIfb_vrate[i-1].refresh);
 706                                        xgifb_info->rate_idx =
 707                                                XGIfb_vrate[i - 1].idx;
 708                                        xgifb_info->refresh_rate =
 709                                                XGIfb_vrate[i - 1].refresh;
 710                                }
 711                                break;
 712                        } else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
 713                                DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
 714                                        rate, XGIfb_vrate[i].refresh);
 715                                xgifb_info->rate_idx = XGIfb_vrate[i].idx;
 716                                break;
 717                        }
 718                }
 719                i++;
 720        }
 721        if (xgifb_info->rate_idx > 0) {
 722                return xgifb_info->rate_idx;
 723        } else {
 724                pr_info("Unsupported rate %d for %dx%d\n",
 725                       rate, xres, yres);
 726                return 0;
 727        }
 728}
 729
 730static void XGIfb_search_tvstd(const char *name)
 731{
 732        int i = 0;
 733
 734        if (name == NULL)
 735                return;
 736
 737        while (XGI_tvtype[i].type_no != -1) {
 738                if (!strcmp(name, XGI_tvtype[i].name)) {
 739                        XGIfb_tvmode = XGI_tvtype[i].type_no;
 740                        break;
 741                }
 742                i++;
 743        }
 744}
 745
 746/* ----------- FBDev related routines for all series ----------- */
 747
 748static void XGIfb_bpp_to_var(struct xgifb_video_info *xgifb_info,
 749                             struct fb_var_screeninfo *var)
 750{
 751        switch (var->bits_per_pixel) {
 752        case 8:
 753                var->red.offset = var->green.offset = var->blue.offset = 0;
 754                var->red.length = var->green.length = var->blue.length = 6;
 755                xgifb_info->video_cmap_len = 256;
 756                break;
 757        case 16:
 758                var->red.offset = 11;
 759                var->red.length = 5;
 760                var->green.offset = 5;
 761                var->green.length = 6;
 762                var->blue.offset = 0;
 763                var->blue.length = 5;
 764                var->transp.offset = 0;
 765                var->transp.length = 0;
 766                xgifb_info->video_cmap_len = 16;
 767                break;
 768        case 32:
 769                var->red.offset = 16;
 770                var->red.length = 8;
 771                var->green.offset = 8;
 772                var->green.length = 8;
 773                var->blue.offset = 0;
 774                var->blue.length = 8;
 775                var->transp.offset = 24;
 776                var->transp.length = 8;
 777                xgifb_info->video_cmap_len = 16;
 778                break;
 779        }
 780}
 781
 782/* --------------------- SetMode routines ------------------------- */
 783
 784static void XGIfb_pre_setmode(struct xgifb_video_info *xgifb_info)
 785{
 786        u8 cr30 = 0, cr31 = 0;
 787
 788        cr31 = xgifb_reg_get(XGICR, 0x31);
 789        cr31 &= ~0x60;
 790
 791        switch (xgifb_info->display2) {
 792        case XGIFB_DISP_CRT:
 793                cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
 794                cr31 |= SIS_DRIVER_MODE;
 795                break;
 796        case XGIFB_DISP_LCD:
 797                cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
 798                cr31 |= SIS_DRIVER_MODE;
 799                break;
 800        case XGIFB_DISP_TV:
 801                if (xgifb_info->TV_type == TVMODE_HIVISION)
 802                        cr30 = (SIS_VB_OUTPUT_HIVISION
 803                                        | SIS_SIMULTANEOUS_VIEW_ENABLE);
 804                else if (xgifb_info->TV_plug == TVPLUG_SVIDEO)
 805                        cr30 = (SIS_VB_OUTPUT_SVIDEO
 806                                        | SIS_SIMULTANEOUS_VIEW_ENABLE);
 807                else if (xgifb_info->TV_plug == TVPLUG_COMPOSITE)
 808                        cr30 = (SIS_VB_OUTPUT_COMPOSITE
 809                                        | SIS_SIMULTANEOUS_VIEW_ENABLE);
 810                else if (xgifb_info->TV_plug == TVPLUG_SCART)
 811                        cr30 = (SIS_VB_OUTPUT_SCART
 812                                        | SIS_SIMULTANEOUS_VIEW_ENABLE);
 813                cr31 |= SIS_DRIVER_MODE;
 814
 815                if (XGIfb_tvmode == 1 || xgifb_info->TV_type == TVMODE_PAL)
 816                        cr31 |= 0x01;
 817                else
 818                        cr31 &= ~0x01;
 819                break;
 820        default: /* disable CRT2 */
 821                cr30 = 0x00;
 822                cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
 823        }
 824
 825        xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
 826        xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
 827        xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR33,
 828                                                (xgifb_info->rate_idx & 0x0F));
 829}
 830
 831static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info)
 832{
 833        u8 reg;
 834        unsigned char doit = 1;
 835        /*
 836        xgifb_reg_set(XGISR,IND_SIS_PASSWORD,SIS_PASSWORD);
 837        xgifb_reg_set(XGICR, 0x13, 0x00);
 838        xgifb_reg_and_or(XGISR,0x0E, 0xF0, 0x01);
 839        *test*
 840        */
 841        if (xgifb_info->video_bpp == 8) {
 842                /* TW: We can't switch off CRT1 on LVDS/Chrontel
 843                 * in 8bpp Modes */
 844                if ((xgifb_info->hasVB == HASVB_LVDS) ||
 845                    (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL)) {
 846                        doit = 0;
 847                }
 848                /* TW: We can't switch off CRT1 on 301B-DH
 849                 * in 8bpp Modes if using LCD */
 850                if (xgifb_info->display2 == XGIFB_DISP_LCD)
 851                        doit = 0;
 852        }
 853
 854        /* TW: We can't switch off CRT1 if bridge is in slave mode */
 855        if (xgifb_info->hasVB != HASVB_NONE) {
 856                reg = xgifb_reg_get(XGIPART1, 0x00);
 857
 858                if ((reg & 0x50) == 0x10)
 859                        doit = 0;
 860
 861        } else {
 862                XGIfb_crt1off = 0;
 863        }
 864
 865        reg = xgifb_reg_get(XGICR, 0x17);
 866        if ((XGIfb_crt1off) && (doit))
 867                reg &= ~0x80;
 868        else
 869                reg |= 0x80;
 870        xgifb_reg_set(XGICR, 0x17, reg);
 871
 872        xgifb_reg_and(XGISR, IND_SIS_RAMDAC_CONTROL, ~0x04);
 873
 874        if (xgifb_info->display2 == XGIFB_DISP_TV &&
 875            xgifb_info->hasVB == HASVB_301) {
 876
 877                reg = xgifb_reg_get(XGIPART4, 0x01);
 878
 879                if (reg < 0xB0) { /* Set filter for XGI301 */
 880                        int filter_tb;
 881
 882                        switch (xgifb_info->video_width) {
 883                        case 320:
 884                                filter_tb = (xgifb_info->TV_type ==
 885                                             TVMODE_NTSC) ? 4 : 12;
 886                                break;
 887                        case 640:
 888                                filter_tb = (xgifb_info->TV_type ==
 889                                             TVMODE_NTSC) ? 5 : 13;
 890                                break;
 891                        case 720:
 892                                filter_tb = (xgifb_info->TV_type ==
 893                                             TVMODE_NTSC) ? 6 : 14;
 894                                break;
 895                        case 800:
 896                                filter_tb = (xgifb_info->TV_type ==
 897                                             TVMODE_NTSC) ? 7 : 15;
 898                                break;
 899                        default:
 900                                filter_tb = 0;
 901                                filter = -1;
 902                                break;
 903                        }
 904                        xgifb_reg_or(XGIPART1,
 905                                     SIS_CRT2_WENABLE_315,
 906                                     0x01);
 907
 908                        if (xgifb_info->TV_type == TVMODE_NTSC) {
 909
 910                                xgifb_reg_and(XGIPART2, 0x3a, 0x1f);
 911
 912                                if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
 913
 914                                        xgifb_reg_and(XGIPART2, 0x30, 0xdf);
 915
 916                                } else if (xgifb_info->TV_plug
 917                                                == TVPLUG_COMPOSITE) {
 918
 919                                        xgifb_reg_or(XGIPART2, 0x30, 0x20);
 920
 921                                        switch (xgifb_info->video_width) {
 922                                        case 640:
 923                                                xgifb_reg_set(XGIPART2,
 924                                                              0x35,
 925                                                              0xEB);
 926                                                xgifb_reg_set(XGIPART2,
 927                                                              0x36,
 928                                                              0x04);
 929                                                xgifb_reg_set(XGIPART2,
 930                                                              0x37,
 931                                                              0x25);
 932                                                xgifb_reg_set(XGIPART2,
 933                                                              0x38,
 934                                                              0x18);
 935                                                break;
 936                                        case 720:
 937                                                xgifb_reg_set(XGIPART2,
 938                                                              0x35,
 939                                                              0xEE);
 940                                                xgifb_reg_set(XGIPART2,
 941                                                              0x36,
 942                                                              0x0C);
 943                                                xgifb_reg_set(XGIPART2,
 944                                                              0x37,
 945                                                              0x22);
 946                                                xgifb_reg_set(XGIPART2,
 947                                                              0x38,
 948                                                              0x08);
 949                                                break;
 950                                        case 800:
 951                                                xgifb_reg_set(XGIPART2,
 952                                                              0x35,
 953                                                              0xEB);
 954                                                xgifb_reg_set(XGIPART2,
 955                                                              0x36,
 956                                                              0x15);
 957                                                xgifb_reg_set(XGIPART2,
 958                                                              0x37,
 959                                                              0x25);
 960                                                xgifb_reg_set(XGIPART2,
 961                                                              0x38,
 962                                                              0xF6);
 963                                                break;
 964                                        }
 965                                }
 966
 967                        } else if (xgifb_info->TV_type == TVMODE_PAL) {
 968
 969                                xgifb_reg_and(XGIPART2, 0x3A, 0x1F);
 970
 971                                if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
 972
 973                                        xgifb_reg_and(XGIPART2, 0x30, 0xDF);
 974
 975                                } else if (xgifb_info->TV_plug
 976                                                == TVPLUG_COMPOSITE) {
 977
 978                                        xgifb_reg_or(XGIPART2, 0x30, 0x20);
 979
 980                                        switch (xgifb_info->video_width) {
 981                                        case 640:
 982                                                xgifb_reg_set(XGIPART2,
 983                                                              0x35,
 984                                                              0xF1);
 985                                                xgifb_reg_set(XGIPART2,
 986                                                              0x36,
 987                                                              0xF7);
 988                                                xgifb_reg_set(XGIPART2,
 989                                                              0x37,
 990                                                              0x1F);
 991                                                xgifb_reg_set(XGIPART2,
 992                                                              0x38,
 993                                                              0x32);
 994                                                break;
 995                                        case 720:
 996                                                xgifb_reg_set(XGIPART2,
 997                                                              0x35,
 998                                                              0xF3);
 999                                                xgifb_reg_set(XGIPART2,
1000                                                              0x36,
1001                                                              0x00);
1002                                                xgifb_reg_set(XGIPART2,
1003                                                              0x37,
1004                                                              0x1D);
1005                                                xgifb_reg_set(XGIPART2,
1006                                                              0x38,
1007                                                              0x20);
1008                                                break;
1009                                        case 800:
1010                                                xgifb_reg_set(XGIPART2,
1011                                                              0x35,
1012                                                              0xFC);
1013                                                xgifb_reg_set(XGIPART2,
1014                                                              0x36,
1015                                                              0xFB);
1016                                                xgifb_reg_set(XGIPART2,
1017                                                              0x37,
1018                                                              0x14);
1019                                                xgifb_reg_set(XGIPART2,
1020                                                              0x38,
1021                                                              0x2A);
1022                                                break;
1023                                        }
1024                                }
1025                        }
1026
1027                        if ((filter >= 0) && (filter <= 7)) {
1028                                DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n",
1029                                        filter_tb, filter,
1030                                        XGI_TV_filter[filter_tb].
1031                                                filter[filter][0],
1032                                        XGI_TV_filter[filter_tb].
1033                                                filter[filter][1],
1034                                        XGI_TV_filter[filter_tb].
1035                                                filter[filter][2],
1036                                        XGI_TV_filter[filter_tb].
1037                                                filter[filter][3]
1038                                );
1039                                xgifb_reg_set(
1040                                        XGIPART2,
1041                                        0x35,
1042                                        (XGI_TV_filter[filter_tb].
1043                                                filter[filter][0]));
1044                                xgifb_reg_set(
1045                                        XGIPART2,
1046                                        0x36,
1047                                        (XGI_TV_filter[filter_tb].
1048                                                filter[filter][1]));
1049                                xgifb_reg_set(
1050                                        XGIPART2,
1051                                        0x37,
1052                                        (XGI_TV_filter[filter_tb].
1053                                                filter[filter][2]));
1054                                xgifb_reg_set(
1055                                        XGIPART2,
1056                                        0x38,
1057                                        (XGI_TV_filter[filter_tb].
1058                                                filter[filter][3]));
1059                        }
1060                }
1061        }
1062}
1063
1064static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1065                struct fb_info *info)
1066{
1067        struct xgifb_video_info *xgifb_info = info->par;
1068        struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info;
1069        unsigned int htotal = var->left_margin + var->xres + var->right_margin
1070                        + var->hsync_len;
1071        unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
1072                        + var->vsync_len;
1073#if defined(__powerpc__)
1074        u8 cr_data;
1075#endif
1076        unsigned int drate = 0, hrate = 0;
1077        int found_mode = 0;
1078        int old_mode;
1079        /* unsigned char reg, reg1; */
1080
1081        DEBUGPRN("Inside do_set_var");
1082        /* 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); */
1083
1084        info->var.xres_virtual = var->xres_virtual;
1085        info->var.yres_virtual = var->yres_virtual;
1086        info->var.bits_per_pixel = var->bits_per_pixel;
1087
1088        if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1089                vtotal <<= 1;
1090        else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1091                vtotal <<= 2;
1092        else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1093                /* vtotal <<= 1; */
1094                /* var->yres <<= 1; */
1095        }
1096
1097        if (!htotal || !vtotal) {
1098                DPRINTK("XGIfb: Invalid 'var' information\n");
1099                return -EINVAL;
1100        } pr_debug("var->pixclock=%d, htotal=%d, vtotal=%d\n",
1101                        var->pixclock, htotal, vtotal);
1102
1103        if (var->pixclock && htotal && vtotal) {
1104                drate = 1000000000 / var->pixclock;
1105                hrate = (drate * 1000) / htotal;
1106                xgifb_info->refresh_rate = (unsigned int) (hrate * 2
1107                                / vtotal);
1108        } else {
1109                xgifb_info->refresh_rate = 60;
1110        }
1111
1112        pr_debug("Change mode to %dx%dx%d-%dHz\n",
1113               var->xres,
1114               var->yres,
1115               var->bits_per_pixel,
1116               xgifb_info->refresh_rate);
1117
1118        old_mode = xgifb_info->mode_idx;
1119        xgifb_info->mode_idx = 0;
1120
1121        while ((XGIbios_mode[xgifb_info->mode_idx].mode_no != 0) &&
1122               (XGIbios_mode[xgifb_info->mode_idx].xres <= var->xres)) {
1123                if ((XGIbios_mode[xgifb_info->mode_idx].xres == var->xres) &&
1124                    (XGIbios_mode[xgifb_info->mode_idx].yres == var->yres) &&
1125                    (XGIbios_mode[xgifb_info->mode_idx].bpp
1126                                                == var->bits_per_pixel)) {
1127                        found_mode = 1;
1128                        break;
1129                }
1130                xgifb_info->mode_idx++;
1131        }
1132
1133        if (found_mode)
1134                xgifb_info->mode_idx = XGIfb_validate_mode(xgifb_info,
1135                                                        xgifb_info->mode_idx);
1136        else
1137                xgifb_info->mode_idx = -1;
1138
1139        if (xgifb_info->mode_idx < 0) {
1140                pr_err("Mode %dx%dx%d not supported\n",
1141                       var->xres, var->yres, var->bits_per_pixel);
1142                xgifb_info->mode_idx = old_mode;
1143                return -EINVAL;
1144        }
1145
1146        if (XGIfb_search_refresh_rate(xgifb_info,
1147                                      xgifb_info->refresh_rate) == 0) {
1148                xgifb_info->rate_idx = 1;
1149                xgifb_info->refresh_rate = 60;
1150        }
1151
1152        if (isactive) {
1153
1154                XGIfb_pre_setmode(xgifb_info);
1155                if (XGISetModeNew(xgifb_info, hw_info,
1156                                  XGIbios_mode[xgifb_info->mode_idx].mode_no)
1157                                        == 0) {
1158                        pr_err("Setting mode[0x%x] failed\n",
1159                               XGIbios_mode[xgifb_info->mode_idx].mode_no);
1160                        return -EINVAL;
1161                }
1162                info->fix.line_length = ((info->var.xres_virtual
1163                                * info->var.bits_per_pixel) >> 6);
1164
1165                xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
1166
1167                xgifb_reg_set(XGICR, 0x13, (info->fix.line_length & 0x00ff));
1168                xgifb_reg_set(XGISR,
1169                              0x0E,
1170                              (info->fix.line_length & 0xff00) >> 8);
1171
1172                XGIfb_post_setmode(xgifb_info);
1173
1174                DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
1175                                XGIbios_mode[xgifb_info->mode_idx].xres,
1176                                XGIbios_mode[xgifb_info->mode_idx].yres,
1177                                XGIbios_mode[xgifb_info->mode_idx].bpp,
1178                                xgifb_info->refresh_rate);
1179
1180                xgifb_info->video_bpp = XGIbios_mode[xgifb_info->mode_idx].bpp;
1181                xgifb_info->video_vwidth = info->var.xres_virtual;
1182                xgifb_info->video_width =
1183                        XGIbios_mode[xgifb_info->mode_idx].xres;
1184                xgifb_info->video_vheight = info->var.yres_virtual;
1185                xgifb_info->video_height =
1186                        XGIbios_mode[xgifb_info->mode_idx].yres;
1187                xgifb_info->org_x = xgifb_info->org_y = 0;
1188                xgifb_info->video_linelength = info->var.xres_virtual
1189                                * (xgifb_info->video_bpp >> 3);
1190                switch (xgifb_info->video_bpp) {
1191                case 8:
1192                        xgifb_info->DstColor = 0x0000;
1193                        xgifb_info->XGI310_AccelDepth = 0x00000000;
1194                        xgifb_info->video_cmap_len = 256;
1195#if defined(__powerpc__)
1196                        cr_data = xgifb_reg_get(XGICR, 0x4D);
1197                        xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0));
1198#endif
1199                        break;
1200                case 16:
1201                        xgifb_info->DstColor = 0x8000;
1202                        xgifb_info->XGI310_AccelDepth = 0x00010000;
1203#if defined(__powerpc__)
1204                        cr_data = xgifb_reg_get(XGICR, 0x4D);
1205                        xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1206#endif
1207                        xgifb_info->video_cmap_len = 16;
1208                        break;
1209                case 32:
1210                        xgifb_info->DstColor = 0xC000;
1211                        xgifb_info->XGI310_AccelDepth = 0x00020000;
1212                        xgifb_info->video_cmap_len = 16;
1213#if defined(__powerpc__)
1214                        cr_data = xgifb_reg_get(XGICR, 0x4D);
1215                        xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1216#endif
1217                        break;
1218                default:
1219                        xgifb_info->video_cmap_len = 16;
1220                        pr_err("Unsupported depth %d",
1221                               xgifb_info->video_bpp);
1222                        break;
1223                }
1224        }
1225        XGIfb_bpp_to_var(xgifb_info, var); /*update ARGB info*/
1226        DEBUGPRN("End of do_set_var");
1227
1228        dumpVGAReg();
1229        return 0;
1230}
1231
1232static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
1233{
1234        struct xgifb_video_info *xgifb_info = info->par;
1235        unsigned int base;
1236
1237        /* printk("Inside pan_var"); */
1238
1239        base = var->yoffset * info->var.xres_virtual + var->xoffset;
1240
1241        /* calculate base bpp dep. */
1242        switch (info->var.bits_per_pixel) {
1243        case 16:
1244                base >>= 1;
1245                break;
1246        case 32:
1247                break;
1248        case 8:
1249        default:
1250                base >>= 2;
1251                break;
1252        }
1253
1254        xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
1255
1256        xgifb_reg_set(XGICR, 0x0D, base & 0xFF);
1257        xgifb_reg_set(XGICR, 0x0C, (base >> 8) & 0xFF);
1258        xgifb_reg_set(XGISR, 0x0D, (base >> 16) & 0xFF);
1259        xgifb_reg_set(XGISR, 0x37, (base >> 24) & 0x03);
1260        xgifb_reg_and_or(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1261
1262        if (xgifb_info->display2 != XGIFB_DISP_NONE) {
1263                xgifb_reg_or(XGIPART1, SIS_CRT2_WENABLE_315, 0x01);
1264                xgifb_reg_set(XGIPART1, 0x06, (base & 0xFF));
1265                xgifb_reg_set(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1266                xgifb_reg_set(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1267                xgifb_reg_and_or(XGIPART1,
1268                                 0x02,
1269                                 0x7F,
1270                                 ((base >> 24) & 0x01) << 7);
1271        }
1272        /* printk("End of pan_var"); */
1273        return 0;
1274}
1275
1276static int XGIfb_open(struct fb_info *info, int user)
1277{
1278        return 0;
1279}
1280
1281static int XGIfb_release(struct fb_info *info, int user)
1282{
1283        return 0;
1284}
1285
1286static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1287{
1288        int rc = 16;
1289
1290        switch (var->bits_per_pixel) {
1291        case 8:
1292                rc = 256;
1293                break;
1294        case 16:
1295                rc = 16;
1296                break;
1297        case 32:
1298                rc = 16;
1299                break;
1300        }
1301        return rc;
1302}
1303
1304static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1305                unsigned blue, unsigned transp, struct fb_info *info)
1306{
1307        struct xgifb_video_info *xgifb_info = info->par;
1308
1309        if (regno >= XGIfb_get_cmap_len(&info->var))
1310                return 1;
1311
1312        switch (info->var.bits_per_pixel) {
1313        case 8:
1314                outb(regno, XGIDACA);
1315                outb((red >> 10), XGIDACD);
1316                outb((green >> 10), XGIDACD);
1317                outb((blue >> 10), XGIDACD);
1318                if (xgifb_info->display2 != XGIFB_DISP_NONE) {
1319                        outb(regno, XGIDAC2A);
1320                        outb((red >> 8), XGIDAC2D);
1321                        outb((green >> 8), XGIDAC2D);
1322                        outb((blue >> 8), XGIDAC2D);
1323                }
1324                break;
1325        case 16:
1326                ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800))
1327                                | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
1328                                >> 11);
1329                break;
1330        case 32:
1331                red >>= 8;
1332                green >>= 8;
1333                blue >>= 8;
1334                ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green
1335                                << 8) | (blue);
1336                break;
1337        }
1338        return 0;
1339}
1340
1341/* ----------- FBDev related routines for all series ---------- */
1342
1343static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1344                struct fb_info *info)
1345{
1346        struct xgifb_video_info *xgifb_info = info->par;
1347
1348        DEBUGPRN("inside get_fix");
1349        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1350
1351        fix->smem_start = xgifb_info->video_base;
1352
1353        fix->smem_len = xgifb_info->video_size;
1354
1355        fix->type = FB_TYPE_PACKED_PIXELS;
1356        fix->type_aux = 0;
1357        if (xgifb_info->video_bpp == 8)
1358                fix->visual = FB_VISUAL_PSEUDOCOLOR;
1359        else
1360                fix->visual = FB_VISUAL_DIRECTCOLOR;
1361        fix->xpanstep = 0;
1362        if (XGIfb_ypan)
1363                fix->ypanstep = 1;
1364        fix->ywrapstep = 0;
1365        fix->line_length = xgifb_info->video_linelength;
1366        fix->mmio_start = xgifb_info->mmio_base;
1367        fix->mmio_len = xgifb_info->mmio_size;
1368        fix->accel = FB_ACCEL_SIS_XABRE;
1369
1370        DEBUGPRN("end of get_fix");
1371        return 0;
1372}
1373
1374static int XGIfb_set_par(struct fb_info *info)
1375{
1376        int err;
1377
1378        /* printk("XGIfb: inside set_par\n"); */
1379        err = XGIfb_do_set_var(&info->var, 1, info);
1380        if (err)
1381                return err;
1382        XGIfb_get_fix(&info->fix, -1, info);
1383        /* printk("XGIfb: end of set_par\n"); */
1384        return 0;
1385}
1386
1387static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1388{
1389        struct xgifb_video_info *xgifb_info = info->par;
1390        unsigned int htotal = var->left_margin + var->xres + var->right_margin
1391                        + var->hsync_len;
1392        unsigned int vtotal = 0;
1393        unsigned int drate = 0, hrate = 0;
1394        int found_mode = 0;
1395        int refresh_rate, search_idx;
1396
1397        DEBUGPRN("Inside check_var");
1398
1399        if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1400                vtotal = var->upper_margin + var->yres + var->lower_margin
1401                                + var->vsync_len;
1402                vtotal <<= 1;
1403        } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1404                vtotal = var->upper_margin + var->yres + var->lower_margin
1405                                + var->vsync_len;
1406                vtotal <<= 2;
1407        } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1408                vtotal = var->upper_margin + (var->yres / 2)
1409                                + var->lower_margin + var->vsync_len;
1410        } else
1411                vtotal = var->upper_margin + var->yres + var->lower_margin
1412                                + var->vsync_len;
1413
1414        if (!(htotal) || !(vtotal))
1415                XGIFAIL("XGIfb: no valid timing data");
1416
1417        if (var->pixclock && htotal && vtotal) {
1418                drate = 1000000000 / var->pixclock;
1419                hrate = (drate * 1000) / htotal;
1420                xgifb_info->refresh_rate =
1421                        (unsigned int) (hrate * 2 / vtotal);
1422                pr_debug(
1423                        "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1424                        "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1425                        __func__, var->pixclock, htotal, vtotal,
1426                        __func__, drate, hrate, xgifb_info->refresh_rate);
1427        } else {
1428                xgifb_info->refresh_rate = 60;
1429        }
1430
1431        /*
1432        if ((var->pixclock) && (htotal)) {
1433                drate = 1E12 / var->pixclock;
1434                hrate = drate / htotal;
1435                refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1436        } else {
1437                refresh_rate = 60;
1438        }
1439        */
1440        /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1441        if ((var->xres == 1024) && (var->yres == 600))
1442                refresh_rate = 60;
1443
1444        search_idx = 0;
1445        while ((XGIbios_mode[search_idx].mode_no != 0) &&
1446                (XGIbios_mode[search_idx].xres <= var->xres)) {
1447                if ((XGIbios_mode[search_idx].xres == var->xres) &&
1448                        (XGIbios_mode[search_idx].yres == var->yres) &&
1449                        (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1450                        if (XGIfb_validate_mode(xgifb_info, search_idx) > 0) {
1451                                found_mode = 1;
1452                                break;
1453                        }
1454                }
1455                search_idx++;
1456        }
1457
1458        if (!found_mode) {
1459
1460                pr_err("%dx%dx%d is no valid mode\n",
1461                        var->xres, var->yres, var->bits_per_pixel);
1462                search_idx = 0;
1463                while (XGIbios_mode[search_idx].mode_no != 0) {
1464                        if ((var->xres <= XGIbios_mode[search_idx].xres) &&
1465                            (var->yres <= XGIbios_mode[search_idx].yres) &&
1466                            (var->bits_per_pixel ==
1467                             XGIbios_mode[search_idx].bpp)) {
1468                                if (XGIfb_validate_mode(xgifb_info,
1469                                                        search_idx) > 0) {
1470                                        found_mode = 1;
1471                                        break;
1472                                }
1473                        }
1474                        search_idx++;
1475                }
1476                if (found_mode) {
1477                        var->xres = XGIbios_mode[search_idx].xres;
1478                        var->yres = XGIbios_mode[search_idx].yres;
1479                        pr_debug("Adapted to mode %dx%dx%d\n",
1480                                var->xres, var->yres, var->bits_per_pixel);
1481
1482                } else {
1483                        pr_err("Failed to find similar mode to %dx%dx%d\n",
1484                                var->xres, var->yres, var->bits_per_pixel);
1485                        return -EINVAL;
1486                }
1487        }
1488
1489        /* TW: TODO: Check the refresh rate */
1490
1491        /* Adapt RGB settings */
1492        XGIfb_bpp_to_var(xgifb_info, var);
1493
1494        /* Sanity check for offsets */
1495        if (var->xoffset < 0)
1496                var->xoffset = 0;
1497        if (var->yoffset < 0)
1498                var->yoffset = 0;
1499
1500        if (!XGIfb_ypan) {
1501                if (var->xres != var->xres_virtual)
1502                        var->xres_virtual = var->xres;
1503                if (var->yres != var->yres_virtual)
1504                        var->yres_virtual = var->yres;
1505        } /* else { */
1506                /* TW: Now patch yres_virtual if we use panning */
1507                /* May I do this? */
1508                /* var->yres_virtual = xgifb_info->heapstart /
1509                        (var->xres * (var->bits_per_pixel >> 3)); */
1510                /* if (var->yres_virtual <= var->yres) { */
1511                /* TW: Paranoia check */
1512                /* var->yres_virtual = var->yres; */
1513                /* } */
1514        /* } */
1515
1516        /* Truncate offsets to maximum if too high */
1517        if (var->xoffset > var->xres_virtual - var->xres)
1518                var->xoffset = var->xres_virtual - var->xres - 1;
1519
1520        if (var->yoffset > var->yres_virtual - var->yres)
1521                var->yoffset = var->yres_virtual - var->yres - 1;
1522
1523        /* Set everything else to 0 */
1524        var->red.msb_right =
1525        var->green.msb_right =
1526        var->blue.msb_right =
1527        var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1528
1529        DEBUGPRN("end of check_var");
1530        return 0;
1531}
1532
1533static int XGIfb_pan_display(struct fb_var_screeninfo *var,
1534                struct fb_info *info)
1535{
1536        int err;
1537
1538        /* printk("\nInside pan_display:\n"); */
1539
1540        if (var->xoffset > (info->var.xres_virtual - info->var.xres))
1541                return -EINVAL;
1542        if (var->yoffset > (info->var.yres_virtual - info->var.yres))
1543                return -EINVAL;
1544
1545        if (var->vmode & FB_VMODE_YWRAP) {
1546                if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual
1547                                || var->xoffset)
1548                        return -EINVAL;
1549        } else {
1550                if (var->xoffset + info->var.xres > info->var.xres_virtual
1551                                || var->yoffset + info->var.yres
1552                                                > info->var.yres_virtual)
1553                        return -EINVAL;
1554        }
1555        err = XGIfb_pan_var(var, info);
1556        if (err < 0)
1557                return err;
1558
1559        info->var.xoffset = var->xoffset;
1560        info->var.yoffset = var->yoffset;
1561        if (var->vmode & FB_VMODE_YWRAP)
1562                info->var.vmode |= FB_VMODE_YWRAP;
1563        else
1564                info->var.vmode &= ~FB_VMODE_YWRAP;
1565
1566        /* printk("End of pan_display\n"); */
1567        return 0;
1568}
1569
1570static int XGIfb_blank(int blank, struct fb_info *info)
1571{
1572        struct xgifb_video_info *xgifb_info = info->par;
1573        u8 reg;
1574
1575        reg = xgifb_reg_get(XGICR, 0x17);
1576
1577        if (blank > 0)
1578                reg &= 0x7f;
1579        else
1580                reg |= 0x80;
1581
1582        xgifb_reg_set(XGICR, 0x17, reg);
1583        xgifb_reg_set(XGISR, 0x00, 0x01); /* Synchronous Reset */
1584        xgifb_reg_set(XGISR, 0x00, 0x03); /* End Reset */
1585        return 0;
1586}
1587
1588static struct fb_ops XGIfb_ops = {
1589        .owner = THIS_MODULE,
1590        .fb_open = XGIfb_open,
1591        .fb_release = XGIfb_release,
1592        .fb_check_var = XGIfb_check_var,
1593        .fb_set_par = XGIfb_set_par,
1594        .fb_setcolreg = XGIfb_setcolreg,
1595        .fb_pan_display = XGIfb_pan_display,
1596        .fb_blank = XGIfb_blank,
1597        .fb_fillrect = cfb_fillrect,
1598        .fb_copyarea = cfb_copyarea,
1599        .fb_imageblit = cfb_imageblit,
1600        /* .fb_mmap = XGIfb_mmap, */
1601};
1602
1603/* ---------------- Chip generation dependent routines ---------------- */
1604
1605/* for XGI 315/550/650/740/330 */
1606
1607static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info)
1608{
1609
1610        u8 ChannelNum, tmp;
1611        u8 reg = 0;
1612
1613        /* xorg driver sets 32MB * 1 channel */
1614        if (xgifb_info->chip == XG27)
1615                xgifb_reg_set(XGISR, IND_SIS_DRAM_SIZE, 0x51);
1616
1617        reg = xgifb_reg_get(XGISR, IND_SIS_DRAM_SIZE);
1618        switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1619        case XGI_DRAM_SIZE_1MB:
1620                xgifb_info->video_size = 0x100000;
1621                break;
1622        case XGI_DRAM_SIZE_2MB:
1623                xgifb_info->video_size = 0x200000;
1624                break;
1625        case XGI_DRAM_SIZE_4MB:
1626                xgifb_info->video_size = 0x400000;
1627                break;
1628        case XGI_DRAM_SIZE_8MB:
1629                xgifb_info->video_size = 0x800000;
1630                break;
1631        case XGI_DRAM_SIZE_16MB:
1632                xgifb_info->video_size = 0x1000000;
1633                break;
1634        case XGI_DRAM_SIZE_32MB:
1635                xgifb_info->video_size = 0x2000000;
1636                break;
1637        case XGI_DRAM_SIZE_64MB:
1638                xgifb_info->video_size = 0x4000000;
1639                break;
1640        case XGI_DRAM_SIZE_128MB:
1641                xgifb_info->video_size = 0x8000000;
1642                break;
1643        case XGI_DRAM_SIZE_256MB:
1644                xgifb_info->video_size = 0x10000000;
1645                break;
1646        default:
1647                return -1;
1648        }
1649
1650        tmp = (reg & 0x0c) >> 2;
1651        switch (xgifb_info->chip) {
1652        case XG20:
1653        case XG21:
1654        case XG27:
1655                ChannelNum = 1;
1656                break;
1657
1658        case XG42:
1659                if (reg & 0x04)
1660                        ChannelNum = 2;
1661                else
1662                        ChannelNum = 1;
1663                break;
1664
1665        case XG40:
1666        default:
1667                if (tmp == 2)
1668                        ChannelNum = 2;
1669                else if (tmp == 3)
1670                        ChannelNum = 3;
1671                else
1672                        ChannelNum = 1;
1673                break;
1674        }
1675
1676        xgifb_info->video_size = xgifb_info->video_size * ChannelNum;
1677        /* PLiad fixed for benchmarking and fb set */
1678        /* xgifb_info->video_size = 0x200000; */ /* 1024x768x16 */
1679        /* xgifb_info->video_size = 0x1000000; */ /* benchmark */
1680
1681        pr_info("SR14=%x DramSzie %x ChannelNum %x\n",
1682               reg,
1683               xgifb_info->video_size, ChannelNum);
1684        return 0;
1685
1686}
1687
1688static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info)
1689{
1690        u8 cr32, temp = 0;
1691
1692        xgifb_info->TV_plug = xgifb_info->TV_type = 0;
1693
1694        switch (xgifb_info->hasVB) {
1695        case HASVB_LVDS_CHRONTEL:
1696        case HASVB_CHRONTEL:
1697                break;
1698        case HASVB_301:
1699        case HASVB_302:
1700                /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1701                break;
1702        }
1703
1704        cr32 = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR32);
1705
1706        if ((cr32 & SIS_CRT1) && !XGIfb_crt1off)
1707                XGIfb_crt1off = 0;
1708        else {
1709                if (cr32 & 0x5F)
1710                        XGIfb_crt1off = 1;
1711                else
1712                        XGIfb_crt1off = 0;
1713        }
1714
1715        if (!xgifb_info->display2_force) {
1716                if (cr32 & SIS_VB_TV)
1717                        xgifb_info->display2 = XGIFB_DISP_TV;
1718                else if (cr32 & SIS_VB_LCD)
1719                        xgifb_info->display2 = XGIFB_DISP_LCD;
1720                else if (cr32 & SIS_VB_CRT2)
1721                        xgifb_info->display2 = XGIFB_DISP_CRT;
1722                else
1723                        xgifb_info->display2 = XGIFB_DISP_NONE;
1724        }
1725
1726        if (XGIfb_tvplug != -1)
1727                /* PR/TW: Override with option */
1728                xgifb_info->TV_plug = XGIfb_tvplug;
1729        else if (cr32 & SIS_VB_HIVISION) {
1730                xgifb_info->TV_type = TVMODE_HIVISION;
1731                xgifb_info->TV_plug = TVPLUG_SVIDEO;
1732        } else if (cr32 & SIS_VB_SVIDEO)
1733                xgifb_info->TV_plug = TVPLUG_SVIDEO;
1734        else if (cr32 & SIS_VB_COMPOSITE)
1735                xgifb_info->TV_plug = TVPLUG_COMPOSITE;
1736        else if (cr32 & SIS_VB_SCART)
1737                xgifb_info->TV_plug = TVPLUG_SCART;
1738
1739        if (xgifb_info->TV_type == 0) {
1740                temp = xgifb_reg_get(XGICR, 0x38);
1741                if (temp & 0x10)
1742                        xgifb_info->TV_type = TVMODE_PAL;
1743                else
1744                        xgifb_info->TV_type = TVMODE_NTSC;
1745        }
1746
1747        /* TW: Copy forceCRT1 option to CRT1off if option is given */
1748        if (XGIfb_forcecrt1 != -1) {
1749                if (XGIfb_forcecrt1)
1750                        XGIfb_crt1off = 0;
1751                else
1752                        XGIfb_crt1off = 1;
1753        }
1754}
1755
1756static int XGIfb_has_VB(struct xgifb_video_info *xgifb_info)
1757{
1758        u8 vb_chipid;
1759
1760        vb_chipid = xgifb_reg_get(XGIPART4, 0x00);
1761        switch (vb_chipid) {
1762        case 0x01:
1763                xgifb_info->hasVB = HASVB_301;
1764                break;
1765        case 0x02:
1766                xgifb_info->hasVB = HASVB_302;
1767                break;
1768        default:
1769                xgifb_info->hasVB = HASVB_NONE;
1770                return 0;
1771        }
1772        return 1;
1773}
1774
1775static void XGIfb_get_VB_type(struct xgifb_video_info *xgifb_info)
1776{
1777        u8 reg;
1778
1779        if (!XGIfb_has_VB(xgifb_info)) {
1780                reg = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR37);
1781                switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {
1782                case SIS_EXTERNAL_CHIP_LVDS:
1783                        xgifb_info->hasVB = HASVB_LVDS;
1784                        break;
1785                case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
1786                        xgifb_info->hasVB = HASVB_LVDS_CHRONTEL;
1787                        break;
1788                default:
1789                        break;
1790                }
1791        }
1792}
1793
1794static int __init xgifb_optval(char *fullopt, int validx)
1795{
1796        unsigned long lres;
1797
1798        if (kstrtoul(fullopt + validx, 0, &lres) < 0 || lres > INT_MAX) {
1799                pr_err("xgifb: invalid value for option: %s\n", fullopt);
1800                return 0;
1801        }
1802        return lres;
1803}
1804
1805static int __init XGIfb_setup(char *options)
1806{
1807        char *this_opt;
1808
1809        if (!options || !*options)
1810                return 0;
1811
1812        pr_info("xgifb: options: %s\n", options);
1813
1814        while ((this_opt = strsep(&options, ",")) != NULL) {
1815
1816                if (!*this_opt)
1817                        continue;
1818
1819                if (!strncmp(this_opt, "mode:", 5)) {
1820                        mode = this_opt + 5;
1821                } else if (!strncmp(this_opt, "vesa:", 5)) {
1822                        vesa = xgifb_optval(this_opt, 5);
1823                } else if (!strncmp(this_opt, "vrate:", 6)) {
1824                        refresh_rate = xgifb_optval(this_opt, 6);
1825                } else if (!strncmp(this_opt, "rate:", 5)) {
1826                        refresh_rate = xgifb_optval(this_opt, 5);
1827                } else if (!strncmp(this_opt, "crt1off", 7)) {
1828                        XGIfb_crt1off = 1;
1829                } else if (!strncmp(this_opt, "filter:", 7)) {
1830                        filter = xgifb_optval(this_opt, 7);
1831                } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
1832                        XGIfb_search_crt2type(this_opt + 14);
1833                } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
1834                        XGIfb_forcecrt1 = xgifb_optval(this_opt, 10);
1835                } else if (!strncmp(this_opt, "tvmode:", 7)) {
1836                        XGIfb_search_tvstd(this_opt + 7);
1837                } else if (!strncmp(this_opt, "tvstandard:", 11)) {
1838                        XGIfb_search_tvstd(this_opt + 7);
1839                } else if (!strncmp(this_opt, "dstn", 4)) {
1840                        enable_dstn = 1;
1841                        /* TW: DSTN overrules forcecrt2type */
1842                        XGIfb_crt2type = XGIFB_DISP_LCD;
1843                } else if (!strncmp(this_opt, "noypan", 6)) {
1844                        XGIfb_ypan = 0;
1845                } else {
1846                        mode = this_opt;
1847                }
1848        }
1849        return 0;
1850}
1851
1852static int __devinit xgifb_probe(struct pci_dev *pdev,
1853                const struct pci_device_id *ent)
1854{
1855        u8 reg, reg1;
1856        u8 CR48, CR38;
1857        int ret;
1858        struct fb_info *fb_info;
1859        struct xgifb_video_info *xgifb_info;
1860        struct xgi_hw_device_info *hw_info;
1861
1862        fb_info = framebuffer_alloc(sizeof(*xgifb_info), &pdev->dev);
1863        if (!fb_info)
1864                return -ENOMEM;
1865
1866        xgifb_info = fb_info->par;
1867        hw_info = &xgifb_info->hw_info;
1868        xgifb_info->fb_info = fb_info;
1869        xgifb_info->chip_id = pdev->device;
1870        pci_read_config_byte(pdev,
1871                             PCI_REVISION_ID,
1872                             &xgifb_info->revision_id);
1873        hw_info->jChipRevision = xgifb_info->revision_id;
1874
1875        xgifb_info->pcibus = pdev->bus->number;
1876        xgifb_info->pcislot = PCI_SLOT(pdev->devfn);
1877        xgifb_info->pcifunc = PCI_FUNC(pdev->devfn);
1878        xgifb_info->subsysvendor = pdev->subsystem_vendor;
1879        xgifb_info->subsysdevice = pdev->subsystem_device;
1880
1881        xgifb_info->video_base = pci_resource_start(pdev, 0);
1882        xgifb_info->mmio_base = pci_resource_start(pdev, 1);
1883        xgifb_info->mmio_size = pci_resource_len(pdev, 1);
1884        xgifb_info->vga_base = pci_resource_start(pdev, 2) + 0x30;
1885        pr_info("Relocate IO address: %Lx [%08lx]\n",
1886               (u64) pci_resource_start(pdev, 2),
1887               xgifb_info->vga_base);
1888
1889        if (pci_enable_device(pdev)) {
1890                ret = -EIO;
1891                goto error;
1892        }
1893
1894        if (XGIfb_crt2type != -1) {
1895                xgifb_info->display2 = XGIfb_crt2type;
1896                xgifb_info->display2_force = true;
1897        }
1898
1899        XGIRegInit(&xgifb_info->dev_info, xgifb_info->vga_base);
1900
1901        xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
1902        reg1 = xgifb_reg_get(XGISR, IND_SIS_PASSWORD);
1903
1904        if (reg1 != 0xa1) { /*I/O error */
1905                pr_err("I/O error!!!");
1906                ret = -EIO;
1907                goto error;
1908        }
1909
1910        switch (xgifb_info->chip_id) {
1911        case PCI_DEVICE_ID_XGI_20:
1912                xgifb_reg_or(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
1913                CR48 = xgifb_reg_get(XGICR, Index_CR_GPIO_Reg1);
1914                if (CR48&GPIOG_READ)
1915                        xgifb_info->chip = XG21;
1916                else
1917                        xgifb_info->chip = XG20;
1918                break;
1919        case PCI_DEVICE_ID_XGI_40:
1920                xgifb_info->chip = XG40;
1921                break;
1922        case PCI_DEVICE_ID_XGI_42:
1923                xgifb_info->chip = XG42;
1924                break;
1925        case PCI_DEVICE_ID_XGI_27:
1926                xgifb_info->chip = XG27;
1927                break;
1928        default:
1929                ret = -ENODEV;
1930                goto error;
1931        }
1932
1933        pr_info("chipid = %x\n", xgifb_info->chip);
1934        hw_info->jChipType = xgifb_info->chip;
1935
1936        if (XGIfb_get_dram_size(xgifb_info)) {
1937                pr_err("Fatal error: Unable to determine RAM size.\n");
1938                ret = -ENODEV;
1939                goto error;
1940        }
1941
1942        /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
1943        xgifb_reg_or(XGISR,
1944                     IND_SIS_PCI_ADDRESS_SET,
1945                     (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
1946        /* Enable 2D accelerator engine */
1947        xgifb_reg_or(XGISR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
1948
1949        hw_info->ulVideoMemorySize = xgifb_info->video_size;
1950
1951        if (!request_mem_region(xgifb_info->video_base,
1952                                xgifb_info->video_size,
1953                                "XGIfb FB")) {
1954                pr_err("unable request memory size %x\n",
1955                       xgifb_info->video_size);
1956                pr_err("Fatal error: Unable to reserve frame buffer memory\n");
1957                pr_err("Is there another framebuffer driver active?\n");
1958                ret = -ENODEV;
1959                goto error;
1960        }
1961
1962        if (!request_mem_region(xgifb_info->mmio_base,
1963                                xgifb_info->mmio_size,
1964                                "XGIfb MMIO")) {
1965                pr_err("Fatal error: Unable to reserve MMIO region\n");
1966                ret = -ENODEV;
1967                goto error_0;
1968        }
1969
1970        xgifb_info->video_vbase = hw_info->pjVideoMemoryAddress =
1971        ioremap(xgifb_info->video_base, xgifb_info->video_size);
1972        xgifb_info->mmio_vbase = ioremap(xgifb_info->mmio_base,
1973                                            xgifb_info->mmio_size);
1974
1975        pr_info("Framebuffer at 0x%Lx, mapped to 0x%p, size %dk\n",
1976               (u64) xgifb_info->video_base,
1977               xgifb_info->video_vbase,
1978               xgifb_info->video_size / 1024);
1979
1980        pr_info("MMIO at 0x%Lx, mapped to 0x%p, size %ldk\n",
1981               (u64) xgifb_info->mmio_base, xgifb_info->mmio_vbase,
1982               xgifb_info->mmio_size / 1024);
1983
1984        pci_set_drvdata(pdev, xgifb_info);
1985        if (!XGIInitNew(pdev))
1986                pr_err("XGIInitNew() failed!\n");
1987
1988        xgifb_info->mtrr = (unsigned int) 0;
1989
1990        xgifb_info->hasVB = HASVB_NONE;
1991        if ((xgifb_info->chip == XG20) ||
1992            (xgifb_info->chip == XG27)) {
1993                xgifb_info->hasVB = HASVB_NONE;
1994        } else if (xgifb_info->chip == XG21) {
1995                CR38 = xgifb_reg_get(XGICR, 0x38);
1996                if ((CR38&0xE0) == 0xC0)
1997                        xgifb_info->display2 = XGIFB_DISP_LCD;
1998                else if ((CR38&0xE0) == 0x60)
1999                        xgifb_info->hasVB = HASVB_CHRONTEL;
2000                else
2001                        xgifb_info->hasVB = HASVB_NONE;
2002        } else {
2003                XGIfb_get_VB_type(xgifb_info);
2004        }
2005
2006        hw_info->ujVBChipID = VB_CHIP_UNKNOWN;
2007
2008        hw_info->ulExternalChip = 0;
2009
2010        switch (xgifb_info->hasVB) {
2011        case HASVB_301:
2012                reg = xgifb_reg_get(XGIPART4, 0x01);
2013                if (reg >= 0xE0) {
2014                        hw_info->ujVBChipID = VB_CHIP_302LV;
2015                        pr_info("XGI302LV bridge detected (revision 0x%02x)\n", reg);
2016                } else if (reg >= 0xD0) {
2017                        hw_info->ujVBChipID = VB_CHIP_301LV;
2018                        pr_info("XGI301LV bridge detected (revision 0x%02x)\n", reg);
2019                }
2020                /* else if (reg >= 0xB0) {
2021                        hw_info->ujVBChipID = VB_CHIP_301B;
2022                        reg1 = xgifb_reg_get(XGIPART4, 0x23);
2023                        printk("XGIfb: XGI301B bridge detected\n");
2024                } */
2025                else {
2026                        hw_info->ujVBChipID = VB_CHIP_301;
2027                        pr_info("XGI301 bridge detected\n");
2028                }
2029                break;
2030        case HASVB_302:
2031                reg = xgifb_reg_get(XGIPART4, 0x01);
2032                if (reg >= 0xE0) {
2033                        hw_info->ujVBChipID = VB_CHIP_302LV;
2034                        pr_info("XGI302LV bridge detected (revision 0x%02x)\n", reg);
2035                } else if (reg >= 0xD0) {
2036                        hw_info->ujVBChipID = VB_CHIP_301LV;
2037                        pr_info("XGI302LV bridge detected (revision 0x%02x)\n", reg);
2038                } else if (reg >= 0xB0) {
2039                        reg1 = xgifb_reg_get(XGIPART4, 0x23);
2040
2041                        hw_info->ujVBChipID = VB_CHIP_302B;
2042
2043                } else {
2044                        hw_info->ujVBChipID = VB_CHIP_302;
2045                        pr_info("XGI302 bridge detected\n");
2046                }
2047                break;
2048        case HASVB_LVDS:
2049                hw_info->ulExternalChip = 0x1;
2050                pr_info("LVDS transmitter detected\n");
2051                break;
2052        case HASVB_TRUMPION:
2053                hw_info->ulExternalChip = 0x2;
2054                pr_info("Trumpion Zurac LVDS scaler detected\n");
2055                break;
2056        case HASVB_CHRONTEL:
2057                hw_info->ulExternalChip = 0x4;
2058                pr_info("Chrontel TV encoder detected\n");
2059                break;
2060        case HASVB_LVDS_CHRONTEL:
2061                hw_info->ulExternalChip = 0x5;
2062                pr_info("LVDS transmitter and Chrontel TV encoder detected\n");
2063                break;
2064        default:
2065                pr_info("No or unknown bridge type detected\n");
2066                break;
2067        }
2068
2069        if (xgifb_info->hasVB != HASVB_NONE)
2070                XGIfb_detect_VB(xgifb_info);
2071        else if (xgifb_info->chip != XG21)
2072                xgifb_info->display2 = XGIFB_DISP_NONE;
2073
2074        if (xgifb_info->display2 == XGIFB_DISP_LCD) {
2075                if (!enable_dstn) {
2076                        reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL);
2077                        reg &= 0x0f;
2078                        hw_info->ulCRT2LCDType = XGI310paneltype[reg];
2079                }
2080        }
2081
2082        if ((hw_info->ujVBChipID == VB_CHIP_302B) ||
2083                        (hw_info->ujVBChipID == VB_CHIP_301LV) ||
2084                        (hw_info->ujVBChipID == VB_CHIP_302LV)) {
2085                int tmp;
2086                tmp = xgifb_reg_get(XGICR, 0x34);
2087                if (tmp <= 0x13) {
2088                        /* Currently on LCDA?
2089                         *(Some BIOSes leave CR38) */
2090                        tmp = xgifb_reg_get(XGICR, 0x38);
2091                        if ((tmp & 0x03) == 0x03) {
2092                                /* XGI_Pr.XGI_UseLCDA = 1; */
2093                        } else {
2094                                /* Currently on LCDA?
2095                                 *(Some newer BIOSes set D0 in CR35) */
2096                                tmp = xgifb_reg_get(XGICR, 0x35);
2097                                if (tmp & 0x01) {
2098                                        /* XGI_Pr.XGI_UseLCDA = 1; */
2099                                } else {
2100                                        tmp = xgifb_reg_get(XGICR,
2101                                                            0x30);
2102                                        if (tmp & 0x20) {
2103                                                tmp = xgifb_reg_get(
2104                                                        XGIPART1, 0x13);
2105                                        }
2106                                }
2107                        }
2108                }
2109
2110        }
2111
2112        xgifb_info->mode_idx = -1;
2113
2114        if (mode)
2115                XGIfb_search_mode(xgifb_info, mode);
2116        else if (vesa != -1)
2117                XGIfb_search_vesamode(xgifb_info, vesa);
2118
2119        if (xgifb_info->mode_idx >= 0)
2120                xgifb_info->mode_idx =
2121                        XGIfb_validate_mode(xgifb_info, xgifb_info->mode_idx);
2122
2123        if (xgifb_info->mode_idx < 0) {
2124                if (xgifb_info->display2 == XGIFB_DISP_LCD &&
2125                    xgifb_info->chip == XG21)
2126                        xgifb_info->mode_idx =
2127                                XGIfb_GetXG21DefaultLVDSModeIdx(xgifb_info);
2128                else
2129                        xgifb_info->mode_idx = DEFAULT_MODE;
2130        }
2131
2132        if (xgifb_info->mode_idx < 0) {
2133                dev_err(&pdev->dev, "no supported video mode found\n");
2134                goto error_1;
2135        }
2136
2137        /* yilin set default refresh rate */
2138        xgifb_info->refresh_rate = refresh_rate;
2139        if (xgifb_info->refresh_rate == 0)
2140                xgifb_info->refresh_rate = 60;
2141        if (XGIfb_search_refresh_rate(xgifb_info,
2142                        xgifb_info->refresh_rate) == 0) {
2143                xgifb_info->rate_idx = 1;
2144                xgifb_info->refresh_rate = 60;
2145        }
2146
2147        xgifb_info->video_bpp = XGIbios_mode[xgifb_info->mode_idx].bpp;
2148        xgifb_info->video_vwidth =
2149                xgifb_info->video_width =
2150                        XGIbios_mode[xgifb_info->mode_idx].xres;
2151        xgifb_info->video_vheight =
2152                xgifb_info->video_height =
2153                        XGIbios_mode[xgifb_info->mode_idx].yres;
2154        xgifb_info->org_x = xgifb_info->org_y = 0;
2155        xgifb_info->video_linelength =
2156                xgifb_info->video_width *
2157                (xgifb_info->video_bpp >> 3);
2158        switch (xgifb_info->video_bpp) {
2159        case 8:
2160                xgifb_info->DstColor = 0x0000;
2161                xgifb_info->XGI310_AccelDepth = 0x00000000;
2162                xgifb_info->video_cmap_len = 256;
2163                break;
2164        case 16:
2165                xgifb_info->DstColor = 0x8000;
2166                xgifb_info->XGI310_AccelDepth = 0x00010000;
2167                xgifb_info->video_cmap_len = 16;
2168                break;
2169        case 32:
2170                xgifb_info->DstColor = 0xC000;
2171                xgifb_info->XGI310_AccelDepth = 0x00020000;
2172                xgifb_info->video_cmap_len = 16;
2173                break;
2174        default:
2175                xgifb_info->video_cmap_len = 16;
2176                pr_info("Unsupported depth %d\n",
2177                       xgifb_info->video_bpp);
2178                break;
2179        }
2180
2181        pr_info("Default mode is %dx%dx%d (%dHz)\n",
2182               xgifb_info->video_width,
2183               xgifb_info->video_height,
2184               xgifb_info->video_bpp,
2185               xgifb_info->refresh_rate);
2186
2187        fb_info->var.red.length         = 8;
2188        fb_info->var.green.length       = 8;
2189        fb_info->var.blue.length        = 8;
2190        fb_info->var.activate           = FB_ACTIVATE_NOW;
2191        fb_info->var.height             = -1;
2192        fb_info->var.width              = -1;
2193        fb_info->var.vmode              = FB_VMODE_NONINTERLACED;
2194        fb_info->var.xres               = xgifb_info->video_width;
2195        fb_info->var.xres_virtual       = xgifb_info->video_width;
2196        fb_info->var.yres               = xgifb_info->video_height;
2197        fb_info->var.yres_virtual       = xgifb_info->video_height;
2198        fb_info->var.bits_per_pixel     = xgifb_info->video_bpp;
2199
2200        XGIfb_bpp_to_var(xgifb_info, &fb_info->var);
2201
2202        fb_info->var.pixclock = (u32) (1000000000 /
2203                        XGIfb_mode_rate_to_dclock(&xgifb_info->dev_info,
2204                                hw_info,
2205                                XGIbios_mode[xgifb_info->mode_idx].mode_no,
2206                                xgifb_info->rate_idx));
2207
2208        if (XGIfb_mode_rate_to_ddata(&xgifb_info->dev_info, hw_info,
2209                XGIbios_mode[xgifb_info->mode_idx].mode_no,
2210                xgifb_info->rate_idx,
2211                &fb_info->var.left_margin,
2212                &fb_info->var.right_margin,
2213                &fb_info->var.upper_margin,
2214                &fb_info->var.lower_margin,
2215                &fb_info->var.hsync_len,
2216                &fb_info->var.vsync_len,
2217                &fb_info->var.sync,
2218                &fb_info->var.vmode)) {
2219
2220                if ((fb_info->var.vmode & FB_VMODE_MASK) ==
2221                    FB_VMODE_INTERLACED) {
2222                        fb_info->var.yres <<= 1;
2223                        fb_info->var.yres_virtual <<= 1;
2224                } else if ((fb_info->var.vmode & FB_VMODE_MASK) ==
2225                           FB_VMODE_DOUBLE) {
2226                        fb_info->var.pixclock >>= 1;
2227                        fb_info->var.yres >>= 1;
2228                        fb_info->var.yres_virtual >>= 1;
2229                }
2230
2231        }
2232
2233        strncpy(fb_info->fix.id, "XGI", sizeof(fb_info->fix.id) - 1);
2234        fb_info->fix.type       = FB_TYPE_PACKED_PIXELS;
2235        fb_info->fix.xpanstep   = 1;
2236        fb_info->fix.ypanstep   = 1;
2237
2238        fb_info->flags = FBINFO_FLAG_DEFAULT;
2239        fb_info->screen_base = xgifb_info->video_vbase;
2240        fb_info->fbops = &XGIfb_ops;
2241        XGIfb_get_fix(&fb_info->fix, -1, fb_info);
2242        fb_info->pseudo_palette = xgifb_info->pseudo_palette;
2243
2244        fb_alloc_cmap(&fb_info->cmap, 256 , 0);
2245
2246#ifdef CONFIG_MTRR
2247        xgifb_info->mtrr = mtrr_add(xgifb_info->video_base,
2248                xgifb_info->video_size, MTRR_TYPE_WRCOMB, 1);
2249        if (xgifb_info->mtrr >= 0)
2250                dev_info(&pdev->dev, "added MTRR\n");
2251#endif
2252
2253        if (register_framebuffer(fb_info) < 0) {
2254                ret = -EINVAL;
2255                goto error_mtrr;
2256        }
2257
2258        dumpVGAReg();
2259
2260        return 0;
2261
2262error_mtrr:
2263#ifdef CONFIG_MTRR
2264        if (xgifb_info->mtrr >= 0)
2265                mtrr_del(xgifb_info->mtrr, xgifb_info->video_base,
2266                        xgifb_info->video_size);
2267#endif /* CONFIG_MTRR */
2268error_1:
2269        iounmap(xgifb_info->mmio_vbase);
2270        iounmap(xgifb_info->video_vbase);
2271        release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
2272error_0:
2273        release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
2274error:
2275        framebuffer_release(fb_info);
2276        return ret;
2277}
2278
2279/*****************************************************/
2280/*                PCI DEVICE HANDLING                */
2281/*****************************************************/
2282
2283static void __devexit xgifb_remove(struct pci_dev *pdev)
2284{
2285        struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
2286        struct fb_info *fb_info = xgifb_info->fb_info;
2287
2288        unregister_framebuffer(fb_info);
2289#ifdef CONFIG_MTRR
2290        if (xgifb_info->mtrr >= 0)
2291                mtrr_del(xgifb_info->mtrr, xgifb_info->video_base,
2292                        xgifb_info->video_size);
2293#endif /* CONFIG_MTRR */
2294        iounmap(xgifb_info->mmio_vbase);
2295        iounmap(xgifb_info->video_vbase);
2296        release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
2297        release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
2298        framebuffer_release(fb_info);
2299        pci_set_drvdata(pdev, NULL);
2300}
2301
2302static struct pci_driver xgifb_driver = {
2303        .name = "xgifb",
2304        .id_table = xgifb_pci_table,
2305        .probe = xgifb_probe,
2306        .remove = __devexit_p(xgifb_remove)
2307};
2308
2309static int __init xgifb_init(void)
2310{
2311        char *option = NULL;
2312
2313        if (forcecrt2type != NULL)
2314                XGIfb_search_crt2type(forcecrt2type);
2315        if (fb_get_options("xgifb", &option))
2316                return -ENODEV;
2317        XGIfb_setup(option);
2318
2319        return pci_register_driver(&xgifb_driver);
2320}
2321
2322module_init(xgifb_init);
2323
2324/*****************************************************/
2325/*                      MODULE                       */
2326/*****************************************************/
2327
2328#ifdef MODULE
2329
2330MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
2331MODULE_LICENSE("GPL");
2332MODULE_AUTHOR("XGITECH , Others");
2333
2334module_param(mode, charp, 0);
2335module_param(vesa, int, 0);
2336module_param(filter, int, 0);
2337module_param(forcecrt2type, charp, 0);
2338
2339MODULE_PARM_DESC(forcecrt2type,
2340        "\nForce the second display output type. Possible values are NONE,\n"
2341        "LCD, TV, VGA, SVIDEO or COMPOSITE.\n");
2342
2343MODULE_PARM_DESC(mode,
2344        "\nSelects the desired default display mode in the format XxYxDepth,\n"
2345        "eg. 1024x768x16.\n");
2346
2347MODULE_PARM_DESC(vesa,
2348        "\nSelects the desired default display mode by VESA mode number, eg.\n"
2349        "0x117.\n");
2350
2351MODULE_PARM_DESC(filter,
2352                "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
2353                "(Possible values 0-7, default: [no filter])\n");
2354
2355static void __exit xgifb_remove_module(void)
2356{
2357        pci_unregister_driver(&xgifb_driver);
2358        pr_debug("Module unloaded\n");
2359}
2360
2361module_exit(xgifb_remove_module);
2362
2363#endif  /*  /MODULE  */
2364