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