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