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